Qt在resizeEvent中添加子小部件

Qt adding child widget in resizeEvent

本文关键字:小部 添加 resizeEvent Qt      更新时间:2023-10-16

我有一个小部件W从布局设置为QVBoxLayout实例的QFrame派生。我想知道以下resizeEvent实现是否正确,还是会导致无限循环:

void W::resizeEvent(QResizeEvent *event) {
    for (/* some condition based on the new size of this widget */) {
        // Infinite loop or not?
        qobject_cast<QVBoxLayout *>(layout())->addWidget(new QWidget());
    }
}

到目前为止,它对我有用,这纯粹是运气吗?

没关系。 W拥有一家拥有QWidget QLayout。将QWidget添加到QLayout不会更改W的大小。你总是看到这一点。例如,如果将子构件放置在父构件中,并且父构件太小,则子构件将被裁剪。不同的是,父母的大小不会拉伸以适应孩子的大小。我相信您的代码将根据父级的大小(例如,当窗口大小更改时(隐藏或显示小部件的典型方式。

绘制和构建小部件的层次结构是两回事。因此,添加 QWidget s 很好,但直接在 resizeEvent 中使用 QPainter 则不行。

QWidget的层次结构

QWidget衍生物(QLineEditQPushButton、...(的层次结构是图形用户界面应该是什么样子的高级规范,可以使用QLayout项进行排序。

绘画(使用QPainter(是在屏幕上实际绘制某些内容的过程,并且纯粹是在虚拟功能QWidget::paintEvent中完成的。QWidget的每个导数都应该提供这个空基函数的实现。默认派生物(QLineEdit,...(根据其当前状态(小部件的大小,QLineEdit的当前文本...(和当前QStyle对象提供paintEvent的实现,该对象通常根据您的操作系统自动设置,但可以使用QWidget::setStyleQApplication::setStyle以编程方式进行更改。可以使用 QWidget::update 请求重新绘制。

">

不应该/不需要"与"可能不需要">

句子">不需要(或应该(在此处理程序中完成任何绘图">是为实现自定义QWidget(使用paintEvent的新实现(的人准备的,以明确您不应该在这里实现您的绘画,但将自动触发paintEvent

">

不应该/不需要"是一些建议,他们不写"可能不"。因此,如果您出于某种原因(例如实时应用程序(想要立即刷新屏幕,您可以使用重绘立即调用重绘,从而导致在resizeEvent期间调用paintEvent。只要QWidget上的所有QPainter操作都在paintEvent内(按照 QPainter 文档中的警告的要求(,一切都很好。

resizeEvent函数中使用addWidget将小部件添加到布局不是问题,因为它不会立即触发绘图。

您可以通过编译和执行这个简单的项目来轻松验证这一点:

对话框.h:

#pragma once
#include <QDialog>
class Dialog : public QDialog
{
    Q_OBJECT
public:
    Dialog(QWidget *parent = 0);
    ~Dialog();
    void resizeEvent(QResizeEvent *event);
    void paintEvent(QPaintEvent *event);
private:
    bool resizing;
};

对话框.cpp:

#include "dialog.h"
#include <QResizeEvent>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
Dialog::Dialog(QWidget *parent)
    : QDialog(parent),
      resizing(false)
{
    new QVBoxLayout(this);
}
Dialog::~Dialog()
{
}
void Dialog::resizeEvent(QResizeEvent *event)
{
    resizing = true;
    if ( event->size().width() == event->size().height() )
    {
        qDebug() << "Adding widget";
        // Infinite loop or not?
        layout()->addWidget(new QPushButton());
    }
    resizing = false;
}
void Dialog::paintEvent(QPaintEvent *event)
{
    if ( resizing )
    {
        qDebug() << "Painting while resizing widget";
    }
}

主.cpp:

#include "dialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}

当您运行程序时,调整对话框的大小使其为正方形(宽度==高度(,插入一些按钮("添加小部件"打印到控制台(,但您永远不会看到"在调整小部件大小时绘画"消息。这很可能是因为addWidget设置了一个脏显示标志,稍后由框架处理。它会使显示器失效,但不会立即重新粉刷。

所以你正在做的很好,不违反框架要求("不需要(或应该(在这个处理程序中完成任何绘图。

但是,如果您没有信心(也许该绘画可以立即在不同的操作系统上操作,或者在未来的Qt版本中操作......你不能确定(,你也可以通过使用Qt::QueuedConnection发出连接到插槽的信号来延迟插入,这个插槽将在"稍后"执行,然后调用addWidget,保证它是在resizeEvent功能之外完成的。