【翻译】利用Qt设计师窗体在运行时创建用户界面(Creating a user interface from a Qt Designer form at run-time)
利用Qt设计师窗体在运行时创建用户界面
我们利用Calculator窗体例子中创建的窗体(Form)来展示当一个应用(application)已经生成后,是可以在其运行时产生与例子中相同的用户界面。
准备
Calculator窗体例子定好了一个无须修改,可直接使用的用户界面。在本例子中,我们使用一个资源文件来包含之前例子中的calculatorform.ui,它也可以存储在硬盘上。
为了在运行时生成窗体,我们需要在本例子中将QtUiTools 模块库链接进来,工程文件包含了所有需要的信息:
1 HEADERS = calculatorform.h 2 RESOURCES = calculatorbuilder.qrc 3 SOURCES = calculatorform.cpp \ 4 main.cpp 5 QT += widgets uitools
正常声明其他的必要文件。
定义CalculatorForm类
CalculatorForm类定义了一个部件(widget)来包含该窗体的用户界面
class CalculatorForm : public QWidget { Q_OBJECT public: CalculatorForm(QWidget *parent = 0); 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 = 0); 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>0</x> <y>0</y> <width>276</width> <height>98</height> </rect> </property> <property name="sizePolicy" > <sizepolicy> <hsizetype>5</hsizetype> <vsizetype>5</vsizetype> <horstretch>0</horstretch> <verstretch>0</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>9</number> </property> <property name="spacing" > <number>6</number> </property> <item row="0" column="0" > <layout class="QHBoxLayout" > <property name="objectName" > <string notr="true" /> </property> <property name="margin" > <number>1</number> </property> <property name="spacing" > <number>6</number> </property> <item> <layout class="QVBoxLayout" > <property name="objectName" > <string notr="true" /> </property> <property name="margin" > <number>1</number> </property> <property name="spacing" > <number>6</number> </property> <item> <widget class="QLabel" name="label" > <property name="objectName" > <string notr="true" >label</string> </property> <property name="geometry" > <rect> <x>1</x> <y>1</y> <width>45</width> <height>19</height> </rect> </property> <property name="text" > <string>Input 1</string> </property> </widget> </item> <item> <widget class="QSpinBox" name="inputSpinBox1" > <property name="objectName" > <string notr="true" >inputSpinBox1</string> </property> <property name="geometry" > <rect> <x>1</x> <y>26</y> <width>45</width> <height>25</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>54</x> <y>1</y> <width>7</width> <height>52</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>1</number> </property> <property name="spacing" > <number>6</number> </property> <item> <widget class="QLabel" name="label_2" > <property name="objectName" > <string notr="true" >label_2</string> </property> <property name="geometry" > <rect> <x>1</x> <y>1</y> <width>45</width> <height>19</height> </rect> </property> <property name="text" > <string>Input 2</string> </property> </widget> </item> <item> <widget class="QSpinBox" name="inputSpinBox2" > <property name="objectName" > <string notr="true" >inputSpinBox2</string> </property> <property name="geometry" > <rect> <x>1</x> <y>26</y> <width>45</width> <height>25</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>120</x> <y>1</y> <width>7</width> <height>52</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>1</number> </property> <property name="spacing" > <number>6</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>1</x> <y>1</y> <width>37</width> <height>17</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>1</x> <y>24</y> <width>37</width> <height>27</height> </rect> </property> <property name="frameShape" > <enum>QFrame::Box</enum> </property> <property name="frameShadow" > <enum>QFrame::Sunken</enum> </property> <property name="text" > <string>0</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="1" column="0" > <spacer> <property name="objectName" > <string notr="true" >verticalSpacer</string> </property> <property name="geometry" > <rect> <x>85</x> <y>69</y> <width>20</width> <height>20</height> </rect> </property> <property name="orientation" > <enum>Qt::Vertical</enum> </property> <property name="sizeHint" > <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item row="0" column="1" > <spacer> <property name="objectName" > <string notr="true" >horizontalSpacer</string> </property> <property name="geometry" > <rect> <x>188</x> <y>26</y> <width>79</width> <height>20</height> </rect> </property> <property name="orientation" > <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" > <size> <width>40</width> <height>20</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>