Unsolved QGraphicsItem paint event called continually during QWidget::event loop
-
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
-
@qtshah While posting the code enclose them within ```
-
Is it normal that you don't use any layout in your
Frame
class ? -
My mistake there is a layout in the Frame class.
QHBoxLayout * layout = new QHBoxLayout; layout->addWidget(myGraphicsView); setLayout(layout);
-
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 ?
-
No the QFrame is not necessary, we will need to refactor that. I'm not sure what you mean by not calling the correct base class implementation. Are you referring to the QMainWindow constructor?
-
In
MainWindow::event
, you are not callingQMainWindow::event
butQWidget::event
. -
Oh yes that is true. I tried switching it to QMainWindow::event but the result was the same
-
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 ?
-
yes that's it
-
How many are they at once on your scene ?
-
There's no limit to how many can be in the scene and the scenes are likely to get complicated . Most likely there will be between ~10 and ~50 items at a time.
-
Are you still experiencing that if you avoid the proxy widgets ?
-
Yes we are
-
This post is deleted!