Infinite QGraphicsView::resizeEvent calls



我有一个自定义布局BoardLayout,它继承了QLayout。它是以类似BorderLayout示例的方式编写的(https://doc.qt.io/qt-5/qtwidgets-layouts-borderlayout-example.html),采用以下setGeometry()方法:

void BoardLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
int d = qMin(rect.width() - 175, rect.height() - 100);
for (auto e : list) {
if (e->position == Board) {
e->item->setGeometry({50, 50, d, d});
}
}
}

它也有一个更改后的BoardLayout::calculateSize方法,但由于应用它的小部件是窗口的centralWidget,所以这可能无关紧要;在运行时有问题的部分也不会调用此方法(。

我为一个窗口设置了这个布局,并在其中(Board的位置(添加了一个BoardView类的实例(BoardView继承了QGraphicsView(:

auto lt = new BoardLayout();
setLayout(lt);

board_view_ = new BoardView(config_, this);
lt->addWidget(board_view_, BoardLayout::Board);

我没有在布局中添加任何其他对象,所以它可能会写得更简单,但BoardLayout的结构和API保持不变,以保持与工作示例的相似性。

这个BoardView类有一个替代方法resizeEvent,通过每次调整视口的大小来保持内部对象占据视口的所有空间:

void BoardView::resizeEvent(QResizeEvent *event) {
if (event->oldSize().width() == -1) {
qreal k = (qreal)qMin(width(), height()) / ((config_->scene_cell_size + 4) * config_->board_size);
scale(k, k);
}
else {
qreal prev_w = event->oldSize().width(), prev_h = event->oldSize().height();
qreal w = event->size().width(), h = event->size().height();
qreal k = qMin(w, h) / qMin(prev_w, prev_h);
scale(k, k);
}
}

问题是,在这样的设置中,当我启动应用程序时,BoardView::resizeEvent会被一对不同的QSize一个接一个地不停地调用,即使窗口(以及包含BoardLayout作为布局的小部件(没有被调整大小。在这个过程中,BoardLayout::setGeometry不会被调用,所以我不知道这个调整大小事件可能来自哪里。

此外,如果我从BoardView::resizeEvent中删除scale(k, k);,它将按预期正常工作(调整大小事件仅在调整窗口大小后发生,由BoardLayout::setGeometry中的e->item->setGeometry触发(。

如果我将布局更改为标准布局,或者为e->item->setGeometry({50, 50, d, d});选择一些不同的矩形,也会发生同样的情况。

因此,如果有人能解释这个架构的问题,以及不必要的resizeEvents是如何触发的,我将不胜感激。

事实证明,事件是由两个QScrollBar发出的,当视口对于场景来说太小时会出现这些事件。然而,只有当对象处于适合和不适合场景的边缘时,滚动条才会出现和消失,并且在事件周期中发生了一些复杂的事情,我无法理解,因为很难找到关于发生了什么以及何时发生的文档。

然而,如果我们改变缩放系数,使滚动条要么总是出现,要么总是不出现,一切都会很好。这可能不是一个正确的解决方案,只在实践中有效,因为有些事件总是处理得足够快,这是不能保证的。

相关内容

  • 没有找到相关文章

最新更新