Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 编程QGraphicsView滚动未正确更新_C++_Qt_User Interface_Graphics_Scroll - Fatal编程技术网

C++ 编程QGraphicsView滚动未正确更新

C++ 编程QGraphicsView滚动未正确更新,c++,qt,user-interface,graphics,scroll,C++,Qt,User Interface,Graphics,Scroll,我有一个从QGraphicsView派生的自定义类,它实现了一个slot调用scrollHorizontal(intdx),代码中的 void CustomView::scrollHorizontal(int dx){ scrollContentsBy(dx, 0); } 我的问题是,像这样滚动可以正常工作,但不能正确更新场景,相反,在视图边缘发现的任何像素都会重复,而不是重新调用项目的paint()方法 我尝试在之后调用update(),但什么也没发生。我尝试通过拖动启用滚动,更新效

我有一个从QGraphicsView派生的自定义类,它实现了一个slot调用scrollHorizontal(intdx),代码中的

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
s链接,在底部视图中,我将
scrollContentsBy(int-dx,int-dy)
覆盖为
emit horizontalcoll(dx)
;它被上面俯视图中的
插槽捕获

你知道为什么卷轴的速度不同吗?这可能与滚动条作为底部视图的一部分,使其成为一个“更小”的窗口有关吗

更新2:

不同的滚动速率似乎源于一些舍入操作,使用
mapToScene(viewport()->rect().center())给我一个基于整数的“中心”,滚动时,滚动越慢,此错误累积越多,滚动越快,总错误越少

有什么办法让我绕过这件事吗?我看不出有什么办法可以得到一个浮点中心点

更新3:

我已经基本解决了这个问题,结果是需要mapToScene(我在web上的其他地方找到的代码)

我通过存储视口中心的
QPointF
修复了这个问题,现在滚动两个视图时的错误量是不可见的

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

现在,我在
qgraphicscene::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;
和我的
水平滚动(int-dx)
插槽

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();
}
类事件视图:

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);
    }
}
SOM在类主窗口中的位置:

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

您不应该调用
scrollContentsBy
,如下所述:


我不知道你是否还能调用隐藏的滚动条来滚动它。如果没有,则是一个选项。

是否尝试使用滚动条?隐藏它们不会使它们不存在,您应该使用
QScrollBar::setValue
滚动到给定位置

另一种选择是与当前中心点结合使用(正如您也尝试过的那样),但直接在方法中计算中心点(不要预先计算并存储中心点),方法是:

请注意,如果如您所说,“
scrollContentsBy(int-dx,int-dy)
重写为
emit horizontalScroll(dx)
”,则还必须调用super类方法,以便视图可以滚动自身:

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!
}
void CustomView::scrollContentsBy(int-dx,int-dy)
{
发射水平滚动(dx);//(您应该将其称为与插槽不同的名称!)

QGraphicsView::scrollContentsBy(dx,dy);//我在Qt4.6.3-4.7.2中使用了
QGraphicsView
,并且不得不指出,可以通过以下方式使用相应的
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
也会响应
Ensuverible
,这会将滚动条移动到适当的位置。

调用translate(dx,0)对场景没有任何作用。它应该可以工作。但是在场景点上尝试centerOn。您需要自己计算该点。void CustomView::horizontalScroll(int dx){QPointF center=maptosene(viewport()->rect().center());centerOn(center.x()+dx,center.y());update();}不起作用。QPointF center=maptosene(viewport()->rect().center());centerOn(center.x()-dx,center.y());update();正在工作,但现在我的顶视图滚动速度比底视图慢,这是一个新问题。如果目标是跟踪一组视图和场景到另一组,并且两个场景大小相同,我会考虑复制视图转换。每当驱动视图更改时,将受驱动视图设置为具有相同的转换。我会我想看一个复制这个的最小示例代码。我也认为最好的办法是创建一个最小示例代码。只有这两个视图有它们的连接。你能做到吗?这会有很大帮助。也许你会在这样做的时候找到解决方案,这经常发生。;)我确实已经调用了超类方法,当QScrollBar是隐藏的,它们不会初始化,因此QScrollBar::setValue不会导致任何行为。dx会被减去,因为添加dx时滚动方向相反。我的视图原点在左上角(0,0),正数会导致视图中的位置降低。我尝试了horizontalScroll()方法,它向下滚动我的视图…,然后沿发射视图滚动的相反方向水平滚动。更改为viewCenter+=QPointF(-1*dx,0);设置
//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);