Painting without PaintEvent and QGraphicsItem s Management - qt

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 ?

Related

What to paint in the paintEvent implementation?

The Qt's documentation says:
Many widgets can simply repaint their entire surface when asked to, but some slow widgets need to optimize by painting only the requested region: QPaintEvent::region(). This speed optimization does not change the result, as painting is clipped to that region during event processing. QListView and QTableView do this, for example.
Do this mean that when I write a QWidget's paintEvent function, there's no need to manually write codes about which part of the widget should be painted and it is all handled automatically by qt itself?
when I write a QWidget's paintEvent function, there's no need to manually write codes about which part of the widget should be painted [?]
That's correct. The painter passed to you is already clipped to your widget's rectangle, so you can't paint outside of your widget. If your painting is cheap, then you can certainly repaint the entire widget at once, and ignore the repaint rectangle or region passed in the paint event.
You should also not blindly assume that painting only a part of the widget will be somehow inherently faster. You must measure this!
Could you explain more about the paintevent's propagation direction, usually qt's events are propagated as child->parent, but is the paintevent different?
All widgets that need to be painted are painted. The event is not propagated, it is delivered directly to the relevant widgets, under the direction of the widget compositor.
[...] when a Child widget's paintEvent is called, it also gets its Parent widget's paintEvent called. Why is this?
Two separate widgets happen to be painted. Just because they happen to be a parent and a child doesn't mean much. Each widget cares about its paint event in isolation. The widget compositor (backing store) has the big picture. If the parent is painted for seemingly no reason just prior to the child being painted, then likely the child isn't opaque and the parent is painted so that the child can be composited on top of it. Set Qt::WA_OpaquePaintEvent if your paintEvent does opaque painting and no part of the parent is visible through what's painted.

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.

How can I prevent a QWidget from painting, but still respond to events?

I have a QGLWidget that renders an OpenGL scene inside a Qt application. I would like to add some other translucent Qt widgets that are overlaid on top of the QGLWidget. This is more difficult than with standard widgets since the OpenGL drawing context is unknown to Qt's painter classes. So, if I just do the obvious thing and place a transparent toolbar on top of the QGLWidget for instance, the transparent part of the toolbar instead renders black (it doesn't have access to the OpenGL frame buffer when painting).
It seems that the recommended way for handling this sort of thing is to overpaint the 2D content after drawing the OpenGL scene. The linked example seems very straightforward, as long as you're just drawing simple shapes. Instead, what I would like to do is to defer the painting of some child QWidget objects to be done inside the paint event for the QGLWidget.
So, my problem boils down to this:
Prevent the overlay QWidgets from painting in the normal, 2D context.
In the paint event handler for the QGLWidget, paint the overlays after painting the 3D scene that makes up the background.
The second item on this list seems to be simple: I can use QWidget::render() inside the QGLWidget's paint event to draw the desired widgets on top of the viewport. This works just fine.
The first item is more tricky: I need a way to prevent the widgets from painting during the normal course of events and only paint them in the QGLWidget's paint handler. One obvious way to do this is to hide the overlays using QWidget::hide(). This does allow me to paint the widgets atop the OpenGL scene as I would like. However, since the widgets are hidden, they do not respond to mouse or keyboard events. As an example, I'm using a QToolBar with a few buttons on it, and the toolbar is painted properly, but is non-functional (none of the buttons respond to clicks). So, if going down this path, it seems that I would need a way to force the widget to still respond to events even though it is hidden.
Another approach that I've tried is to intercept the QToolBar's paint event using an event filter, with the goal of preventing the toolbar from painting itself. However, the toolbar is still rendered; I'm assuming that this is because the various buttons on the toolbar are child widgets that are still painted, even if I intercept the parent's paint event.
Any ideas on a way that I could accomplish my goal?
I don't understand your issue completely, but I'll try to answer the question stated in the title. You should use event filters. Install an event filter using widget->installEventFilter(object), where widget is a widget you want to block painting, and object is an object of any of your QObject-derived classes. Reimplement eventFilter of this class:
bool MyClass::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::Paint) { return true; }
return false;
}
When you return true from your eventFilter, the event is filtered and paint doesn't occur.
You can also try to use widget->setUpdatesEnabled(false) to temporarily disable painting. Don't forget to re-enable it when you're done.

How to draw a header in my own widget in 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.

how to stop repainting of a widget when it's resized

i am making a software in which paint event painting a widget as per my need but the problem
is that when i re-size my application window it painted it again so please tell me the way
to stop paint event from painting my widget on resizing the main window.
my file are:
v_lab.h(http://qt.pastebin.com/tjHAWkPH)
v_lab.cpp(http://qt.pastebin.com/teJDmMmt)
main.cpp(http://qt.pastebin.com/gsUytaCN)
Thanks
No, you do want to redraw every time the main window resizes. But your design is somewhat weird, as you are creating random stuff inside the paintEvent function. You should create that stuff elsewhere as needed, store that stuff in a QPixmap or something and just redraw the image in the paintEvent function.
In other words, paintEvent should only repaint the view in its current state and should not contain anything that changes the state.

Resources