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));