QGraphicsItem paint event called continually during QWidget::event loop
-
I am creating an application with a QMainWindow, QGraphicsScene and QGraphicsView with many QGraphicsItems within the view. My items' paint() method is being called continually and I only want them to be called when I update an item. I backtraced the item's paint call and here is what is happening:
The main window's QWidget::event calls QWidgetPrivate::drawWidget which calls QWidgetPrivate::sendPaintEvent and that calls QGraphicsView paintEvent. This draws the items in the scene and calls paint on each item. The loop repeats continually. How do I stop this/why is this happening in the first place? I was under the impression that an item's paint event is called during update() or repaint(). I never call these functions.
-
Hi and welcome to devnet,
The paint event should happen when needed (e.g moving a window) or requested (e.g. with update).
However, without seeing your code, it's pretty much impossible to get an idea about what might be going wrong.
-
Hi,
Fair enough. I can't post my exact code for privacy reasons but this is an abstracted version:
mainwindow.hclass MainWindow : public QMainWindow { Q_OBJECT private: Frame* myFrame; };mainwindow.cpp
MainWindow:: MainWindow( QWidget *parent ) : QMainWindow(parent) { setCentralWidget(myFrame); } bool MainWindow:: event( QEvent *event ) { if ( event->type( ) == QEvent::WindowStateChange ) { if ( this->windowState( ).testFlag( Qt::WindowMinimized ) ) { // Tell other windows emit notifyControl_minimizeApplicationWindow( ); LOG(INFO) << "hiding"; return true; } else if ( this->windowState( ).testFlag( Qt::WindowNoState ) ) { emit notifyControl_restoreApplicationWindow( ); LOG(INFO) << "restoring"; return true; } } return QWidget::event( event ); }frame.h
class Frame :public QFrame { Q_OBJECT private: QGraphicsView* myGraphicsView; DiagramScene* myScene; };frame.cpp
Frame:: Frame(MainWindow* parent) { myDiagramScene = new DiagramScene( this ); myGraphicsView = new QGraphicsView( this ); myGraphicsView->setScene( myScene ); }diagramscene.h
class DiagramScene : public QGraphicsScene { Q_OBJECT private: QVector<Rectangle*> myItems; };diagramscene.cpp
DiagramScene:: DiagramScene(Frame* parent) : QGraphicsScene(parent) { //create and add items to the scene here }rectangle.h
class Rectangle : public QGraphicsRectItem { public: int type( ) const Q_DECL_OVERRIDE { return Type; } void updatePosition( ); void paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *widget = 0 ) Q_DECL_OVERRIDE; void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); private: QGraphicsLineItem* myLine; };rectangle.cpp
Rectangle::Rectangle() QGraphicsRectItem() { setLine(); setRectangle(); } void Rectangle:: paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * ) { painter->setPen( this->myColor ); painter->setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing); if ( this->isSelected( ) ) { painter->setPen( QPen( Qt::red, 2 ) ); painter->setBrush( QColor( Qt::red ) ); } else { painter->setPen( QPen( Qt::blue, 2) ); painter->setBrush( QColor( Qt::blue ) ); } painter->drawRect( this->rect( ) ); painter->drawLine( this->myLine->line( ) ); }Hope this helps
Edit - added code tags - p3c0
-
Is it normal that you don't use any layout in your
Frameclass ? -
So now it's working as you want ?
-
No the paint method is still being called repeatedly for each rectangle in the scene, which is time consuming. I only want paint to be called when something changes in the rectangle like when it is moved or the color is changed. It may be that I am misunderstanding when the paint method is triggered. Is it supposed to be triggered at every QWidget event? Because that is what seems to be happening right now.
-
One other detail, you are not calling the correct base class implementation of MainWindow.
Also, do you really need Frame ? Looks like you could put the QGraphicsView directly as central widget, no ?
-
In
MainWindow::event, you are not callingQMainWindow::eventbutQWidget::event. -
What else are you doing in your application ?
-
We have a palette of icons in a dock widget that the user can add into the scene, copy, paste and delete. Each graphics item has a proxy widget that holds properties for the item. The items are rectangles and lines that connect between them so that moving a rectangle should move the lines that are connected to it. I want the items to update at a reasonable event, for example a mouse release event, instead of repeatedly like they doing now which is causing some lag. Basically I want to install an event filter, but am first trying to understand why all QMainWindow events are triggering a graphics item paint.
-
By proxy do you mean you have QProxyGraphicsProxyWidget ?
-
How many are they at once on your scene ?
-
Are you still experiencing that if you avoid the proxy widgets ?