C++ 编程QGraphicsView滚动未正确更新
我有一个从QGraphicsView派生的自定义类,它实现了一个slot调用scrollHorizontal(intdx),代码中的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(),但什么也没发生。我尝试通过拖动启用滚动,更新效
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);