Can someone help me understand why I end up with artifacts in this QGraphicsView?
-
I am working on an application that has multiple scenes, and each scene has one or more views attached to it. Each view has a foreground layer that prints out the cursor position in front of the scene content. There are also items that I want to keep in sync between scenes (for example a graphics item moves in one scene, I move it in the other). I am running into an issue with artifacts appearing in the second scene. I have tried to reproduce this in a minimal example here. Basically i'm just trying to figure out where I am going wrong.
In this example I have an ellipse following the cursor in the first scene. In the mouseMoveEvent for the first scene, I emit a signal telling the second scene to update the position of its own ellipse. I also tell the second view to update an arbitrary location (In my actual program this would correspond to a view-specific overlay basically). I have tried to understand why I am getting artifacts in the second view. I know that I can set a full viewport update in the views, but the scene is very complicated and expensive to paint. I am only moving one graphics item, so it shouldn't need a full update.
I'm trying to understand why the artifacts are appearing in this minimal example to get more understanding on what's incorrect in this chain of events.
Here's an image of what the example looks like after moving the mouse around in scene1 (on the left) for a bit:

main.cpp
#include "myscene.h" #include "myview.h" #include <QApplication> #include <QWidget> #include <QHBoxLayout> int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget *w = new QWidget; MyScene *scene1 = new MyScene(w); MyScene *scene2 = new MyScene(w); MyView *view1 = new MyView(scene1, w); MyView *view2 = new MyView(scene2, w); QHBoxLayout *layout = new QHBoxLayout(w); layout->addWidget(view1); layout->addWidget(view2); QObject::connect(scene1, SIGNAL(mousePosChanged(QPointF)), scene2, SLOT(setTrackerPos(QPointF))); QObject::connect(scene1, SIGNAL(mousePosChanged(QPointF)), view2, SLOT(onMouseMoveEvent())); w->show(); return a.exec(); }myview.h
#ifndef MYVIEW_H #define MYVIEW_H #include <QGraphicsView> #include <QGraphicsScene> class MyView : public QGraphicsView { Q_OBJECT public: MyView(QGraphicsScene *scene, QWidget *parent = 0); public slots: void onMouseMoveEvent(); }; #endif // MYVIEW_Hmyview.cpp
#include "myview.h" MyView::MyView(QGraphicsScene *scene, QWidget *parent) : QGraphicsView(scene, parent) { setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); setMouseTracking(true); } void MyView::onMouseMoveEvent() { viewport()->update(QRect(0,0,250,250)); }myscene.h
#ifndef MYSCENE_H #define MYSCENE_H #include <QGraphicsScene> #include <QGraphicsEllipseItem> #include <QGraphicsSceneMouseEvent> class MyScene : public QGraphicsScene { Q_OBJECT public: MyScene(QObject *parent = 0); public slots: void setTrackerPos(const QPointF &pos); signals: void mousePosChanged(const QPointF &pos); protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent); //override private: QGraphicsEllipseItem *mCursorTracker; }; #endif // MYSCENE_Hmyscene.cpp
#include "myscene.h" MyScene::MyScene(QObject *parent) : QGraphicsScene(QRectF(0.,0.,1000.,1000.), parent), mCursorTracker(new QGraphicsEllipseItem(0., 0., 50., 50.)) { mCursorTracker->setFlag(QGraphicsItem::ItemSendsGeometryChanges); mCursorTracker->setBrush(QBrush(Qt::red, Qt::SolidPattern)); addItem(mCursorTracker); } void MyScene::setTrackerPos(const QPointF &pos) { mCursorTracker->setPos(pos); } void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) { mCursorTracker->setPos(mouseEvent->scenePos()); emit mousePosChanged(mouseEvent->scenePos()); QGraphicsScene::mouseMoveEvent(mouseEvent); } -
I don't see any errors in your code. Only thing I normally never did was manually calling update on the viewport. I wonder if that may have an influence.
-
I don't see any errors in your code. Only thing I normally never did was manually calling update on the viewport. I wonder if that may have an influence.
@Asperamanca It definitely has something to do with the update call. I just don't understand why it breaks the code. This is just the most minimal example I could come up with to demonstrate the issue I am having. Why does update() seem to make the viewport "forget" about other areas it needs to repaint?