程序化QGraphicsView滚动无法正确更新

Joh*_*acs 6 c++ graphics user-interface qt scroll

我有一个派生自QGraphicsView的自定义类,它实现了一个槽调用scrollHorizo​​ntal(int dx),代码里面只是简单的

void CustomView::scrollHorizontal(int dx){
    scrollContentsBy(dx, 0);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,滚动像这样工作,但不能正确更新场景,而是重复在视图边缘找到的任何像素,而不是重新调用项目的paint()方法.

我试过打电话update(),但没有任何反应.我尝试通过拖动和更新工作正常启用滚动!但我需要以编程方式完成它,因为我有滚动条隐藏的东西,如horizontalScrollBar()->setValue()不滚动视图.

我也尝试过:

scrollContentsBy(dx, 0);
this->scene()->invalidate(sceneRect());
this->update();
Run Code Online (Sandbox Code Playgroud)

更新:

QPointF center = mapToScene(viewport()->rect().center()); 
centerOn(center.x() - dx, center.y()); 
update(); 
Run Code Online (Sandbox Code Playgroud)

正在工作,但现在我的顶视图滚动速度比我的底部视图慢,这是一个新问题.它们与signals和slots 相关联,在底层视图中我已经scrollContentsBy(int dx, int dy)超越了emit horizontalScroll(dx); slot在顶视图中被上面捕获.

任何想法为什么卷轴以不同的速率发生?它可能与滚动条有关,它是底视图的一部分,有效地使它成为一个"更小"的窗口?

更新2:

不同的滚动速率似乎源于一些舍入发生给我一个基于整数的"中心"使用mapToScene(viewport()->rect().center());,滚动时滚动越慢,此错误加起来越多,滚动总错误越少.

我有办法解决这个问题吗?我没有看到任何获得浮点中心点的方法.

更新3:

所以我已经解决了这个问题,原来需要mapToScene(我在网上其他地方找到的代码).

我通过存储QPointF视口的FP计算中心来修复此问题,现在滚动两个视图时的错误量是不明显的.

最后一个问题是,当您向右滚动任意数量时,视图不再排列,然后调整窗口大小,然后再次滚动.我认为这与计算中心点和定心发生时的逻辑顺序有关.

现在我使用以下代码片段QGraphicsScene::ResizeEvent()和其他根据需要更新中心的代码片段

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

viewCenter = rectCenter;
Run Code Online (Sandbox Code Playgroud)

和我的 horizontalScroll(int dx) slot

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

如何在重新调整窗口大小来解决两个视图的对齐问题时如何解决问题?如果需要进一步澄清,请问我,如果需要,我可以尝试给骷髅提供我所指的内容.

更新4:

粗糙的代码骨架

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

};
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

类EventView:

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

};
Run Code Online (Sandbox Code Playgroud)

EventView.cpp

void EventView::scrollContentsBy(int dx, int dy)
{
    QGraphicsView::scrollContentsBy(dx, dy);

    if(dx != 0){
        emit horizontalScroll(dx);
    }
}
Run Code Online (Sandbox Code Playgroud)

MainWindow类中的Somwhere:

connect(eventView, SIGNAL(horizontalScroll(int)), headerView, SLOT(horizontalScroll(int));
Run Code Online (Sandbox Code Playgroud)

bus*_*ter 10

我曾QGraphicsView在Qt 4.6.3 - 4.7.2中使用过,并且必须争辩说你可以通过QScrollBar以下方式使用相应的:

//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);
Run Code Online (Sandbox Code Playgroud)

它们是否隐藏无关紧要.setValue(int)只要您的图形场景大于图形视图,它们仍会响应.

QGraphicsView还将响应ensureVisible,其移动滚动条到适当的位置.