【翻译】利用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>

 

posted @ 2016-09-01 14:22  heart307  阅读(715)  评论(0编辑  收藏  举报