我有一个自定义布局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
发出的,当视口对于场景来说太小时会出现这些事件。然而,只有当对象处于适合和不适合场景的边缘时,滚动条才会出现和消失,并且在事件周期中发生了一些复杂的事情,我无法理解,因为很难找到关于发生了什么以及何时发生的文档。
然而,如果我们改变缩放系数,使滚动条要么总是出现,要么总是不出现,一切都会很好。这可能不是一个正确的解决方案,只在实践中有效,因为有些事件总是处理得足够快,这是不能保证的。