【翻译】利用Qt设计师窗体在运行时创建用户界面(Creating a user interface from a Qt Designer form at run-time)

时间:2024-01-20 11:27:15

利用Qt设计师窗体在运行时创建用户界面

【翻译】利用Qt设计师窗体在运行时创建用户界面(Creating a user interface from a Qt Designer form at run-time)

我们利用Calculator窗体例子中创建的窗体(Form)来展示当一个应用(application)已经生成后,是可以在其运行时产生与例子中相同的用户界面。

准备

Calculator窗体例子定好了一个无须修改,可直接使用的用户界面。在本例子中,我们使用一个资源文件来包含之前例子中的calculatorform.ui,它也可以存储在硬盘上。

为了在运行时生成窗体,我们需要在本例子中将QtUiTools 模块库链接进来,工程文件包含了所有需要的信息:

 HEADERS     = calculatorform.h
RESOURCES = calculatorbuilder.qrc
SOURCES = calculatorform.cpp \
main.cpp
QT += widgets uitools

正常声明其他的必要文件。

定义CalculatorForm类

CalculatorForm类定义了一个部件(widget)来包含该窗体的用户界面

class CalculatorForm : public QWidget
{
Q_OBJECT public:
CalculatorForm(QWidget *parent = ); private slots:
void on_inputSpinBox1_valueChanged(int value);
void on_inputSpinBox2_valueChanged(int value); private:
QSpinBox *ui_inputSpinBox1;
QSpinBox *ui_inputSpinBox2;
QLabel *ui_outputWidget;
};

注意到,我们并不需要包含一个头文件来解释该用户界面。我们只是使用了uic要求的auto-connection naming convention定义了两个public槽(slot),并声明了两个私有变量来访问我们构造的窗体中的部件。

实现(Implementation)CalculatorForm类

我们需要使用libQtUiTools库提供的QUiLoader类,因此我们包含该库的头文件

#include <QtUiTools>

构造函数使用窗体载入对象和QFile对象通过资源文件来构造我们要实现的用户界面

CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent)
{
QUiLoader loader; QFile file(":/forms/calculatorform.ui");
file.open(QFile::ReadOnly);
QWidget *formWidget = loader.load(&file, this);
file.close();

通过在该例子的资源中包含用户界面,确保其在该例子运行时显示出来。loader.load()函数读取文件中包含的用户界面信息,并构造一个窗体作为该CalculatorForm对象的子部件。

我们对生成的用户界面中的两个spin box和一个标签(label)感兴趣,我们重新得到三个指向它们的指针。qFindChild()模板函数使得我们可以按名字依次遍历部件来找到对应的子部件。

    ui_inputSpinBox1 = findChild<QSpinBox*>("inputSpinBox1");
ui_inputSpinBox2 = findChild<QSpinBox*>("inputSpinBox2");
ui_outputWidget = findChild<QLabel*>("outputWidget");

窗体载入器(form loader)创建的部件需要与CalculatorForm对象中专有命名(specially-named)的槽连接起来,我们使用Qt的meta-object system来实现

    QMetaObject::connectSlotsByName(this);

将窗体部件添加到一个布局(layout)中,并设置标题。

    QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(formWidget);
setLayout(layout); setWindowTitle(tr("Calculator Builder"));
}

两个修改窗体部件的槽函数与Calculator Form例子中的类似,唯一的区别在于我们使用指针来读写这些部件

void CalculatorForm::on_inputSpinBox1_valueChanged(int value)
{
ui_outputWidget->setText(QString::number(value + ui_inputSpinBox2->value()));
}
void CalculatorForm::on_inputSpinBox2_valueChanged(int value)
{
ui_outputWidget->setText(QString::number(value + ui_inputSpinBox1->value()));
}

文件:

calculatorbuilder/calculatorform.cpp

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/ #include <QtUiTools>
#include <QSpinBox>
#include <QLabel>
#include <QVBoxLayout>
#include <QFile> #include "calculatorform.h" CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent)
{
QUiLoader loader; QFile file(":/forms/calculatorform.ui");
file.open(QFile::ReadOnly);
QWidget *formWidget = loader.load(&file, this);
file.close(); ui_inputSpinBox1 = findChild<QSpinBox*>("inputSpinBox1");
ui_inputSpinBox2 = findChild<QSpinBox*>("inputSpinBox2");
ui_outputWidget = findChild<QLabel*>("outputWidget"); QMetaObject::connectSlotsByName(this); QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(formWidget);
setLayout(layout); setWindowTitle(tr("Calculator Builder"));
} void CalculatorForm::on_inputSpinBox1_valueChanged(int value)
{
ui_outputWidget->setText(QString::number(value + ui_inputSpinBox2->value()));
} void CalculatorForm::on_inputSpinBox2_valueChanged(int value)
{
ui_outputWidget->setText(QString::number(value + ui_inputSpinBox1->value()));
}

calculatorbuilder/calculatorform.h

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/ #ifndef CALCULATORFORM_H
#define CALCULATORFORM_H #include <QWidget> class QLabel;
class QSpinBox; class CalculatorForm : public QWidget
{
Q_OBJECT public:
CalculatorForm(QWidget *parent = ); private slots:
void on_inputSpinBox1_valueChanged(int value);
void on_inputSpinBox2_valueChanged(int value); private:
QSpinBox *ui_inputSpinBox1;
QSpinBox *ui_inputSpinBox2;
QLabel *ui_outputWidget;
}; #endif

calculatorbuilder/calculatorform.ui

<ui version="4.0" >
<author></author>
<comment></comment>
<exportmacro></exportmacro>
<class>CalculatorForm</class>
<widget class="QWidget" name="CalculatorForm" >
<property name="objectName" >
<string notr="true" >CalculatorForm</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="sizePolicy" >
<sizepolicy>
<hsizetype></hsizetype>
<vsizetype></vsizetype>
<horstretch></horstretch>
<verstretch></verstretch>
</sizepolicy>
</property>
<property name="windowTitle" >
<string>Calculator Builder</string>
</property>
<layout class="QGridLayout" >
<property name="objectName" >
<string notr="true" />
</property>
<property name="margin" >
<number></number>
</property>
<property name="spacing" >
<number></number>
</property>
<item row="" column="" >
<layout class="QHBoxLayout" >
<property name="objectName" >
<string notr="true" />
</property>
<property name="margin" >
<number></number>
</property>
<property name="spacing" >
<number></number>
</property>
<item>
<layout class="QVBoxLayout" >
<property name="objectName" >
<string notr="true" />
</property>
<property name="margin" >
<number></number>
</property>
<property name="spacing" >
<number></number>
</property>
<item>
<widget class="QLabel" name="label" >
<property name="objectName" >
<string notr="true" >label</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="text" >
<string>Input </string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="inputSpinBox1" >
<property name="objectName" >
<string notr="true" >inputSpinBox1</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="mouseTracking" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_3" >
<property name="objectName" >
<string notr="true" >label_3</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="text" >
<string>+</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="objectName" >
<string notr="true" />
</property>
<property name="margin" >
<number></number>
</property>
<property name="spacing" >
<number></number>
</property>
<item>
<widget class="QLabel" name="label_2" >
<property name="objectName" >
<string notr="true" >label_2</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="text" >
<string>Input </string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="inputSpinBox2" >
<property name="objectName" >
<string notr="true" >inputSpinBox2</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="mouseTracking" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_3_2" >
<property name="objectName" >
<string notr="true" >label_3_2</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="text" >
<string>=</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
<property name="objectName" >
<string notr="true" />
</property>
<property name="margin" >
<number></number>
</property>
<property name="spacing" >
<number></number>
</property>
<item>
<widget class="QLabel" name="label_2_2_2" >
<property name="objectName" >
<string notr="true" >label_2_2_2</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="text" >
<string>Output</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="outputWidget" >
<property name="objectName" >
<string notr="true" >outputWidget</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="frameShape" >
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Sunken</enum>
</property>
<property name="text" >
<string></string>
</property>
<property name="alignment" >
<set>Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="" column="" >
<spacer>
<property name="objectName" >
<string notr="true" >verticalSpacer</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width></width>
<height></height>
</size>
</property>
</spacer>
</item>
<item row="" column="" >
<spacer>
<property name="objectName" >
<string notr="true" >horizontalSpacer</string>
</property>
<property name="geometry" >
<rect>
<x></x>
<y></y>
<width></width>
<height></height>
</rect>
</property>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width></width>
<height></height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<pixmapfunction></pixmapfunction>
<resources/>
<connections/>
</ui>

calculatorbuilder/main.cpp

/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/ #include <QApplication> #include "calculatorform.h" int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(calculatorbuilder); QApplication app(argc, argv);
CalculatorForm calculator;
calculator.show();
return app.exec();
}

calculatorbuilder/calculatorbuilder.pro

HEADERS     = calculatorform.h
RESOURCES = calculatorbuilder.qrc
SOURCES = calculatorform.cpp \
main.cpp
QT += widgets uitools target.path = $$[QT_INSTALL_EXAMPLES]/designer/calculatorbuilder
INSTALLS += target

calculatorbuilder/calculatorbuilder.qrc

<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/forms">
<file>calculatorform.ui</file>
</qresource>
</RCC>