编程的QGraphicsView滚动更新不正确(Programmatic QGraphicsView

2019-06-26 08:24发布

我已经从的QGraphicsView派生的自定义类,它实现一个时隙呼叫scrollHorizo​​ntal(INT DX),里面的代码只是

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

我的问题是,滚动这样的工作,但不能正常更新的场景,而不是在视图的边缘发现的像素被重复不必项目的一个新的呼叫,而不是paint()方法。

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

我也尝试:

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

更新:

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

是工作,但现在我的俯视图滚动比我仰视图,这是一个新的问题慢。 它们与连接signal S和slot秒,在仰视图我有scrollContentsBy(int dx, int dy) overrided到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;

horizontalScroll(int dx) slot

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

我该如何解决这个问题时,重新调整大小的窗口,打破这两种观点的对齐? 如果需要更多的说明,请只是问,我可以尝试给什么我指的是如果需要的话的骨架。

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

};

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

Somwhere在类主窗口:

connect(eventView, SIGNAL(horizontalScroll(int)), headerView, SLOT(horizontalScroll(int));

Answer 1:

我使用过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);

如果它们被隐藏或不没关系。 他们仍然会做出反应setValue(int) ,只要你有一个图形场景比图形查看大图。

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



Answer 2:

你不应该叫scrollContentsBy如下解释: http://qt-project.org/doc/qt-4.8/qabstractscrollarea.html#scrollContentsBy

我不知道你是否仍然可以调用隐藏滚动条滚动它。 如果没有, translate是一个选项。



Answer 3:

你尝试使用滚动条? 隐藏他们并不能让他们不存在,并且该文件说,你应该使用QScrollBar::setValue滚动到指定位置。

另一种选择是使用QGraphicsView::centerOn(QPointF)结合当前的中心点-你也尝试-而是直接计算你的方法中的中心点( 不预先计算和存储的中心点 )通过使用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().
}

请注意,如果你有,像你说的,“ scrollContentsBy(int dx, int dy) overrided到emit horizontalScroll(dx) ”,你还必须调用超类的方法,以便视图可以滚动本身:

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!
}


文章来源: Programmatic QGraphicsView scrolling not updating properly