Qt在resizeEvent中添加子窗口小部件

时间:2016-06-26 15:26:21

标签: c++ qt

我有一个小工具W派生自QFrame,其布局设置为QVBoxLayout的实例。我想知道以下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());
    }
}

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

3 个答案:

答案 0 :(得分:1)

这没关系。 W拥有拥有QLayout的{​​{1}}。将QWidget添加到QWidget不会更改QLayout的大小。你总是这样看。例如,如果将子窗口小部件放在父窗口中并且父窗口太小,则子窗口小部件将被剪切。在状态上不同,父母的大小不会延伸以适应孩子的大小。我相信您的代码是基于父级大小隐藏或显示小部件的典型方式(例如,当窗口大小更改时)。

答案 1 :(得分:1)

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

QWidget s

的层次结构

QWidget s衍生物(QLineEditQPushButton,......)的层次结构是图形用户界面应如何显示的高级规范,可以使用{ {1}}项目。

<强>绘画

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

&#34;不应该/不需要&#34; vs&#34;可能不会&#34;

句子&#34; 在此处理程序中不需要(或应该)完成绘图。&#34;适用于实现自定义QStyle(使用QWidget的新实现)的人员,以明确您不应在此处实现您的绘画,但会自动触发paintEvent

"Should not/need not"是一些建议,他们不会写#34;可能不会&#34;。因此,如果由于某种原因(例如实时应用程序)想要立即刷新屏幕,则可以使用重绘立即调用重绘,从而在paintEvent期间调用paintEvent。只要resizeEvent上的所有QPainter操作都在QWidget内(根据warning in the QPainter documentation的要求),一切都很好。

答案 2 :(得分:1)

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

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

<强> dialog.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;
};

<强> dialog.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";
    }
}

<强> main.cpp中:

#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();
}

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

所以你正在做的事情很好并且没有违反框架要求(&#34;在这个处理程序中不需要(或应该)完成绘图。&#34;)。

然而,如果你没有信心(也许这幅画可以在不同的操作系统上立即操作,或者在将来的Qt版本中......你无法确定),你也可以通过发射来延迟插入使用Qt::QueuedConnection连接到插槽的信号,此插槽将被执行&#34;稍后&#34;然后拨打addWidget电话,保证在resizeEvent功能之外完成。