How to draw a header in my own widget in Qt? - qt

Does anyone know how to draw a header (and other simple elements), just like in, for example, QTreeWidget, in my own widget?
I would like to use style and call something like:
drawElement(CE_Header, rect, painter);
to draw standard header in specified rect.
QStyle::drawControl can't do it, because it draws control over whole widget.
Qt documentation doesn't say much about it.

Subclass QHeaderView and reimplement the paint method, inside there you can use the QStyleOption data. Then use QTreeWidget::setHeader(QHeaderView* header) to set your header in the widget.

Related

Drawing inside a QFrame: coordinate system

I would like to draw inside a Qt QFrame, however the QFrame will have a border. As far as I understand, the paintEvent receives a QPainter which is associated to the whole frameRect, so I will have to offset my paint operations of the border. Is this correct? Is there a way of getting a QPainter already associated to the inner part of the widget, without the (variable in size) border?
you have to consider the contentsRect contentsRect()-> Returns the area inside the widget's margins.using the return value rect of contensRect() you can restrict to draw anything inside the rect.
One way to do this would be to embed a QWidget inside the QFrame, place it in a simple QVBoxLayout layout or QStackedLayout layout with no margins and paint the QWidget instead. You'll probably get better performance if you simply offset your painting, though.

QTextEdit: How to add fixed position text on top of an image

I am using QTextEdit to implement an editor. One of the requirements I have is to add fixed position text on top of an image.
For example:
I have an image of dimensions: 300x300. I need to add text beginning at the location (20, 20) of the image and ensure that the text does not flow beyond the width of the image.
Something like below:
I am thinking that if I can add a QGraphicView, I can add the image and position text appropriately. Is this possible? Is there a way to introduce a graphic element into a QTextedit? If not, what is the right approach?
Is there a way to introduce a graphic element into a QTextEdit? If not, what is the right approach?
You could look at this the other way and add the QTextEdit to a QGraphicsScene. The graphics scene provides a QGraphicsProxyWidget to add standard Qt widgets.
Therefore, you could create a QGraphicsScene and QGraphicsView. Add a QGraphicsPixmapItem for the image and add the QTextEdit item with a call to QGraphicsScene::addWidget, which returns a QGraphicsProxyWidget, allowing you to position, scale and resize the widget.
Alternatively, you could start with a QGraphicsItem, inherit from that and create your own object which encapsulates the image and proxy object of the QTextEdit.
There are other ways of tackling this too, but I'd probably go for the custom QGraphicsItem. It also depends on your specification, but you can add text items in a graphics scene, without the QTextEdit, though you'd probably have to implement the editing feature, if this is required.

QT - overriding QToolButton paint event

I have own widget MyToolButton which inherit from QToolButton. In paintEvent I want draw only "background" from original QToolButton. I mean, I need draw only style (clicked, hover, etc) but without text and image. These things I want draw by my self (with custom formatting etc). When I call QToolButton::paintEvent(ev) then everything is painted. How to exclude image and text from painting? I supose that I should use drawControl(), drawPrimitive() and drawComplexControl() but can't understands all these states
Source code of void QToolButton::paintEvent(QPaintEvent *) is:
QStylePainter p(this);
QStyleOptionToolButton opt;
initStyleOption(&opt);
p.drawComplexControl(QStyle::CC_ToolButton, opt);
QStylePainter::drawComplexControl calls QStyle::drawComplexControl, which is a pure virtual function, and its implementation depends on a style, you are using. What you need is to go to a source code of concrete impementation (like QWindowsXPStyle or QGtkStyle), find drawComplexControl() implementation and use it in your paintEvent. For a simple control like QPushButton, you can easy rewrite its drawing quite style-independently. Redrawing QToolButton would be a bit more tricky task.
A good choice would be using source code of QCommonStyle.

How can you know when a specific part of an item drawn with a QStyledItemDelegate is hovered?

I have a custom QAbstractItemModel used to display information in a QTreeWidget. However, individual indices are drawn using a QStyledItemDelegate. One item that is drawn using the delegate is a pixmap. When the user hovers the mouse over the pixmap (either help event style or hover enter style is fine) I need to do something, what it is isn't important.
So my question is, how can I know when the mouse has hovered over a specific item inside a QTreeWidget, when that item is drawn using a delegate?
In other situations, I could just subclass QLabel, set the pixmap on it, and then do whatever I need in the event() function, but in this case there is no object behind the pixmap, it is just painted onto the screen, so it doesn't actually receive events. Is it possible to use the delegate to paint an actual widget where I want it to so that widget can receive events, or do I have to work around this some other way?
You could subclass QTreeWidget and reimplement the mouseMoveEvent. In the event you can use the itemAt function in order to check if a valid item is at the mouse position and then do what you want.
void MyTreeWidget::mouseMoveEvent(QMouseEvent * event)
{
QTreeWidget::mouseMoveEvent(event);
QTreeWidgetItem* treeItem = itemAt(event->pos());
if (treeItem != NULL)
doSomething(treeItem);
}
You could avoid subclassing QTreeWidget and implement it in the parent widget/main window. Notice however that the itemAt function expects coordinates in the widget's viewport so you should transform the coordinates to tree widget's coordinates. IMHO it is more elegant to subclass it and just implement the mouseMoveEvent function.
EDIT
If you need to detect the position of an icon within the widget item, it is a bit more advanced but you can check my answer to an older question for more details:
Position of icon in QTreeWidgetItem
There is no Qt built-in solution to this problem. The problem can be solved, however, by saving the geometry of the individual items that are painted using the delegate as they are painted. The paint() function, however, has a const modifier so the data structure you use to save the geometry must be mutable. In this case, I don't think this constitutes a breach of the principles of OOP, but is rather a prime example of why the mutable keyword exists and when it should be used.
You then need to subclass QTreeWidget so you can re-implement the mouseMoveEvent() function as webclectic said. Inside that function you can compare the position of the mouse to the geometry of the item that you painted earlier. If the mouse is inside the item, then it is being hovered.

Painting without PaintEvent and QGraphicsItem s Management

The Scenario is I am getting Rects of Images over the socket and I need to draw it in a Scrollable Canvas. at the moment I am using a QGraphicsScene and drawing using QGraphicsPixmapItem but after few times when one pixmap overlaps another there is no need to keep the bottom one. and I dont know any simple way to find out the overlapped item and delete it. so its supposed to take huge memory if overlapping goes on like this.
there exists another way out. Make a QWidget and put it in a QScrollArea now draw the QWidget using a QPainter (outside paintEvent ?). If I draw it outside paintEvent I need to inherit the QWidget and make a custom one. pass it a Pixmap and let it draw in its own paintEvent by calling update()
Any critiques ? any other Straight forward solutions there ?

Resources