《C++ GUI Programming with Qt 4》学习笔记之UI设计器实现机制

时间:2021-01-30 09:57:42

开始看起《C++ GUI Programming with Qt 4》这本书来,突然觉得看书时如果不做点笔记来学到的东西会很容易忘记,所以还是花点时间把东西记下来,以加深自己的理解,同时也能供自己以后进行查阅。

众所周知,在Qt的工具中有一个Qt Designer专门用来绘制软件UI。它可以让我们像VSC#制作桌面程序时一样直接将控件拖曳到程序中对其进行排布,而不用再自己一个一个地写QLabel, QPushButton, 再用QLayout对它们进行布局。这样做不仅速度上会比手写代码快上许多,以后对布局进行修改也将是一件轻而易举的事情。接下来讲下这个UI设计器到底是怎么进行工作的。

Qt Designer中绘制控件时,它最终其实也是生成一份记录布局外观信息的文本文件而已。就比如你用Dreamwaver设计网页时生成的HTML文件,用 Blend设计WPF外观时所生成的xaml文件一样,Qt Designer也会生成一份后缀名为ui, XML为格式的记录布局信息的文本文件。

以书中的跳转到单元格对话框为例,它生成的文本文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GoToCellDialog</class>
<widget class="QWidget" name="GoToCellDialog">
 <property name="geometry">
  <rect>
   <x>0</x>
   <y>0</y>
   <width>223</width>
   <height>71</height>
  </rect>
 </property>
 <property name="windowTitle">
  <string>Go to Cell</string>
 </property>
 <layout class="QVBoxLayout" name="verticalLayout">
  <item>
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QLabel" name="label">
      <property name="text">
       <string>&amp;Cell Location:</string>
      </property>
      <property name="buddy">
       <cstring>lineEdit</cstring>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLineEdit" name="lineEdit"/>
    </item>
   </layout>
  </item>
  <item>
   <widget class="QDialogButtonBox" name="buttonBox">
    <property name="standardButtons">
     <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
    </property>
   </widget>
  </item>
 </layout>
</widget>
<tabstops>
 <tabstop>lineEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

接下来讲的是Qt如何使用这个XML文件来创建布局和如何去使用这个UI文件。

在使用ui文件时,你需要在Qt中将这个ui文件以头文件的形式给包含进来,其格式为#include "ui_UI文件的名称.h"。在Qt Creator中按Ctrl键将这个文件打开,可以看到如下的内容。

#ifndef UI_GOTOCELLDIALOG_H
#define UI_GOTOCELLDIALOG_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>

QT_BEGIN_NAMESPACE

class Ui_GoToCellDialog
{
public:
   QVBoxLayout *verticalLayout;
   QHBoxLayout *horizontalLayout;
   QLabel *label;
   QLineEdit *lineEdit;
   QDialogButtonBox *buttonBox;

   void setupUi(QWidget *GoToCellDialog)
   {
       if (GoToCellDialog->objectName().isEmpty())
           GoToCellDialog->setObjectName(QString::fromUtf8("GoToCellDialog"));
       GoToCellDialog->resize(223, 71);
       verticalLayout = new QVBoxLayout(GoToCellDialog);
       verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
       horizontalLayout = new QHBoxLayout();
       horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
       label = new QLabel(GoToCellDialog);
       label->setObjectName(QString::fromUtf8("label"));

       horizontalLayout->addWidget(label);

       lineEdit = new QLineEdit(GoToCellDialog);
       lineEdit->setObjectName(QString::fromUtf8("lineEdit"));

       horizontalLayout->addWidget(lineEdit);


       verticalLayout->addLayout(horizontalLayout);

       buttonBox = new QDialogButtonBox(GoToCellDialog);
       buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
       buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);

       verticalLayout->addWidget(buttonBox);

#ifndef QT_NO_SHORTCUT
       label->setBuddy(lineEdit);
#endif // QT_NO_SHORTCUT

       retranslateUi(GoToCellDialog);

       QMetaObject::connectSlotsByName(GoToCellDialog);
   } // setupUi

   void retranslateUi(QWidget *GoToCellDialog)
   {
       GoToCellDialog->setWindowTitle(QApplication::translate("GoToCellDialog", "Go to Cell", 0, QApplication::UnicodeUTF8));
       label->setText(QApplication::translate("GoToCellDialog", "&Cell Location:", 0, QApplication::UnicodeUTF8));
   } // retranslateUi

};

namespace Ui {
   class GoToCellDialog: public Ui_GoToCellDialog {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_GOTOCELLDIALOG_H

通过这个文件,我们了解到:Qt在使用ui布局文件是其实将一个XML文件翻译成一个UI类。这个类中的成员是我们之前所拖曳的控件,而其中有一个setupUi的方法实际将这个布局给创建起来,就如同我们不使用Ui文件时自己手写代码将布局给创建起来一样。

知道了这点,我们也就知道该用什么方法来使用这个ui文件了。主要有以下两种方法:

一、创建ui类,比如上面这个例子:Ui::GoToCellDialog ui; 然后调用其中的setupUi方法并将要进行布局的控件,如对话框等作为参数传进去。

    二、这也是最为常用的方法。既然其本身实际是一个类,那我们只要将这个类作为我们要对其进行布局的类的父类即可,然后在构造函数中调用继承到的setupUi方法便可将布局创建起来。