【问题标题】:Infinite QGraphicsView::resizeEvent calls无限 QGraphicsView::resizeEvent 调用
【发布时间】:2020-12-13 04:17:21
【问题描述】:

我有一个自定义布局 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,我将不胜感激。

【问题讨论】:

    标签: qt qgraphicsview qlayout qevent


    【解决方案1】:

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

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

    【讨论】: