QGraphicsView soft scrolling not updating properly

I have a custom class derived from QGraphicsView that implements the scrollHorizontal (int dx) slot call, inside the code is just

void CustomView::scrollHorizontal(int dx){ scrollContentsBy(dx, 0); } 

My problem is that such scrolling works, but does not update the scene properly, instead all the pixels found on the edge of the view are repeated instead of a new call to the item paint() method.

I tried calling update() after, but nothing happens. I tried to enable scrolling by dragging and updating work perfectly! But I need this to be done programmatically, and since I have scrollbars, hidden things like horizontalScrollBar()->setValue() do not scroll the view.

I also tried:

 scrollContentsBy(dx, 0); this->scene()->invalidate(sceneRect()); this->update(); 

update:

 QPointF center = mapToScene(viewport()->rect().center()); centerOn(center.x() - dx, center.y()); update(); 

works, but now my top view scrolls slower than my bottom view, which is a new problem. They are associated with signal and slot s, in the lower form I scrollContentsBy(int dx, int dy) redefined to emit horizontalScroll(dx) ; which is captured by the above slot in the upper form.

Any ideas why scrolls occur at different speeds? Perhaps this is due to the fact that scrollbars are part of the bottom view, which makes it a "small" window?

update 2:

Different scroll speeds seem to be due to some rounding, which gives me an β€œcenter” with an integer using mapToScene(viewport()->rect().center()); when you scroll, and the slower you scroll, the more this error adds up, the faster you scroll the least error.

Is there any way around this? I see no way to get a floating point.

update 3:

So, I basically solved it, it turns out that mapToScene is needed (the code I found elsewhere on the Internet).

I fixed this by saving QPointF the FP Computing Center in the viewport, now the number of errors when scrolling through two views is unnoticed.

The last problem is that the views no longer line up when you scroll any number to the right, and then resize the window and then scroll it again. I suppose this has something to do with logical ordering when the center point is calculated and when the centering occurs.

I am now using the following code snippet in QGraphicsScene::ResizeEvent() and elsewhere, which updates the center as needed

 QRectF viewPort(viewport()->rect()); QPointF rectCenter((viewPort.x() + viewPort.x() + viewPort.width())/2.0, (viewPort.y() + viewPort.y() + viewPort.height())/2.0); viewCenter = rectCenter; 

and my horizontalScroll(int dx) slot

 void CustomView::horizontalScroll(int dx) { viewCenter.setX(viewCenter.x() - dx); centerOn(viewCenter.x(), viewCenter.y()); update(); } 

How can I fix the problem when recalibrating a window that violates the alignment of the two views? If you need more clarification, just ask, I can try to give skeletons of what I mean, if necessary.

Update 4:

Rough Skeleton Code

 Class HeaderView: class HeaderView View : public QGraphicsView { Q_OBJECT public: HeaderView(QWidget * parent = 0); HeaderView(QGraphicsScene * scene, QWidget * parent = 0); private: QPointF viewCenter; protected: void resizeEvent ( QResizeEvent * event ); public slots: void horizontalScroll(int); void addModel(qreal, qreal, const QString&); }; 

HeaderView.cpp

 void HeaderView::resizeEvent(QResizeEvent *event) { QGraphicsView::resizeEvent(event); QRectF viewPort(viewport()->rect()); QPointF rectCenter((viewPort.x() + viewPort.x() + viewPort.width())/2.0, (viewPort.y() + viewPort.y() + viewPort.height())/2.0); viewCenter = rectCenter; } void HeaderView::horizontalScroll(int dx) { viewCenter.setX(viewCenter.x() - dx); centerOn(viewCenter.x(), viewCenter.y()); update(); } 

EventView Class:

 class EventView : public QGraphicsView { Q_OBJECT public: EventView(QWidget * parent = 0); EventView(QGraphicsScene * scene, QWidget * parent = 0); QRectF visibleRect(); protected: void scrollContentsBy ( int dx, int dy ); signals: void horizontalScroll(int); }; 

EventView.cpp

 void EventView::scrollContentsBy(int dx, int dy) { QGraphicsView::scrollContentsBy(dx, dy); if(dx != 0){ emit horizontalScroll(dx); } } 

Somewhere in the MainWindow class:

 connect(eventView, SIGNAL(horizontalScroll(int)), headerView, SLOT(horizontalScroll(int)); 
+6
source share
3 answers

I worked with QGraphicsView in Qt 4.6.3 - 4.7.2 and should state that you can use the corresponding QScrollBar as follows:

 //graphics view initialization QGraphicsView *graphicsView = new QGraphicsView(parent); QGraphicsScene *scene = new QGraphicsScene(0,0,widthOfScene,heightOfScene,parent); graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); graphicsView->setScene(scene); //in another method QScrollBar* yPos=graphicsView->verticalScrollBar(); yPos->setValue((int) newValue); 

It doesn't matter if they are hidden or not. They will still respond to setValue(int) if you have a graphical scene that is larger than a graphical representation.

QGraphicsView will also respond to ensureVisible , which moves the scroll bars to the appropriate location.

+9
source

You should not call scrollContentsBy as described here: http://qt-project.org/doc/qt-4.8/qabstractscrollarea.html#scrollContentsBy

I don't know if you can still name the hidden scrollbar to scroll through it. If not, translate is an option.

+3
source

Have you tried to use scroll bars? Hiding them does not make them non-existent, but the documentation says you should use QScrollBar::setValue to scroll to a given position.

Another option would be to use QGraphicsView::centerOn(QPointF) in combination with the current center point - as you also tried - but directly calculate the center point in your method ( do not predict and save the center point ) using QGraphicsView::mapToScene(int,int) :

 void CustomView::horizontalScroll(int dx) { QPointF viewCenter = mapToScene(width() / 2, height() / 2); viewCenter += QPointF(dx, 0); // Why did you subtract instead of add dx? centerOn(viewCenter); // BTW, you don't need to do .x(), .y() // You can remove update(); as this is already called in centerOn(). } 

Note that if you have, as you said, β€œ scrollContentsBy(int dx, int dy) redefined to emit horizontalScroll(dx) ” you also need to call the superclass method so that it can scroll itself:

 void CustomView::scrollContentsBy(int dx, int dy) { emit horizontalScrolled(dx); // (You should call it different than the slot!) QGraphicsView::scrollContentsBy(dx, dy); // <-- This is what I mean! } 
+2
source

Source: https://habr.com/ru/post/920719/


All Articles