zoukankan      html  css  js  c++  java
  • 在Qt中如何使用QtDesigner创建的UI文件

            使用Qt有一些时间了,一直在IDE环境(qtcreator和VS2003+集成器)中使用,自然少了很多麻烦的步骤。但是在享受这种便利的同 时,我们也失去了理解更多知识背后的点滴。在IDE中,如果我们要开发一个对话框,通常是使用 “新建—>Qt—>Qt设计师界面类” 这样IDE会自动的帮我们生成三个文件(filename.ui, filename.h,filename.cpp)。qmake也非常智能,可以自动检测到这个用户界面文件(filename.ui)并且生产适当的 makefile规则。这样在编译之前,IDE会自动调用uic(Qt自带的用户界面编译器,User Interface Compiler)将界面文件(filename.ui)转换成C++代码并保存在ui_filename.h文件中。并且在另外两个C++源文件 (filename.h和filename.cpp)中使用了组合(即委托或代理)的方式使用了ui_filename.h里的类(该类通常定义在命名空 间Ui下)。

            如果你不主动的留心这些细节,你可能永远都不明白这些,即使使用了多年的Qt,我就是这样。一次,项目组的需求人员嫌弃我们开发人 员做的界面布局不够恰当,美观。于是有了自己来开发界面的想法。很好!开发人员很快手把手的教会了需求人员用Qt Designer设计窗体界面,然而,等到需求人员把 pureui_filename.ui文件扔给我们开发人员使用时,我们顿时傻了眼,怎么用?于是使用了一个最愚蠢当然也是最简单的办法: 还是和之前一样,通过IDE“新建—>Qt—>Qt设计师界面类”生成与“pureui_filename.”同名的文件,然后用需求人员给 的pureui_filename.ui替换IDE自动生成的 *.ui 文件。虽然转了一个小弯,但目的达到!

           后来想想,总觉得多少有些遗憾,于是查阅了Qt文档之Using a Designer UI File in Your Application

           在这个文档中,详细说明了在应用程序中使用UI文件的方法。

    一、直接的方法(The Direct Approach

         即把filename.ui经过uic转换后的C++代码文件ui_filename.h直接包含,使用其里面Ui命名空间下的类(名称和主窗体的objectname相同,这里假设为GoToCellDialog)。

     
     #include "ui_gotocelldialog.h"    // uic工具将gotocelldialog.ui生成的C++代码
     
     int main(int argc, char *argv[])
     {
         QApplication app(argc, argv);
     
         QDialog *dialog= new QDialog;  // 用于显示界面的父窗体QDialog(QWidget的子类) 
          Ui::GotoCellDialog ui;  // 界面类,必须显示在一个QWidget(或其子类)上
          ui.setupUi(dialog); // 将QDialog设置为 GotoCellDialog 的父窗体,这样GotoCellDialog 里面定义的控件就会显示在QDialog窗体内
     
          dialog->show();
         return app.exec();
     }
     
    二、单继承方式(The Single Inheritance Approach)
     
           单继承方式是相对于后面要讲的多继承方式,单继承方式也称组合(即委托或代理)方式。单继承方式简单来说就是在代码中首先要自定义一个子类(例如下文中的GoToCellDialog类),该类要从form对应的窗体类(或其兼容的子类)派生;并用ui生成的类定义一个类里的成员变量,该成员变量可以是值也可以是指针,根据使用成员变量的形式不同,又分为成员变量和指针成员变量两种形式。这样在GoToCellDialog的构造函数中可以直接调用ui和ui中的变量和函数,使用起来很方便。
     
    1、使用成员变量
     
          即将 Ui::GotoCellDialog ui; 作为类GotoCellDialog(只继承自QDialog,单一继承)的成员变量。这里有一点值得注意的地方,就是ui文件提供的类被包含在了名为Ui的name space里,这样做的目的是将ui文件的命名空间与用户的代码分离,避免两者出现命名冲突的情况。
     
    头文件: gotocelldialog.h
     
    #include <QDialog>
    #include "ui_gotocelldialog.h" // 因为是成员变量形式,必须包含相应的头文件
     
    class GoToCellDialog: public QDialog
     {
         Q_OBJECT
     
     public:
        explicit GoToCellDialog(QDialog *parent = 0);
     
     private slots:
         void on_lineEdit_textChanged();
     
     private:
         Ui::GoToCellDialog ui;
     };
     
    实现文件: gotocelldialog.cpp
     
    #include "gotocelldialog.h"
     
    #include <QtGui>
     
    GoToCellDialog::GoToCellDialog(QWidget *parent)
        : QDialog(parent)
    {
        ui.setupUi(this);  
     
        QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
        lineEdit->setValidator(new QRegExpValidator(regExp, this));
     
        connect(okButton, SIGNAL(clicked()), SLOT(accept()));
        connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));
    }
     
    void GoToCellDialog::on_lineEdit_textChanged()
    {
        // bool hasAcceptableInput () const
        // This property holds whether the input satisfies the inputMask and the validator.
        // By default, this property is true.
        okButton->setEnabled(lineEdit->hasAcceptableInput());
    }
     
     
    2、使用指针成员变量
           与成员变量形式相似,唯一不同的是,将Ui::GoToCellDialog声明为指针成员,即 Ui::GoToCellDialog *ui;
     
    因此,相应的头文件中只要前置声明即可:
     
    namespace Ui 
        class GoToCellDialog; 
    } // 前置声明即可,只在实现文件中包含相应的头文件 
     
    class GoToCellDialog: public QDialog
          // 同上 
     private: 
           Ui::GoToCellDialog *ui; 
    };
     
    实现文件:
     
    #include "ui_gotocelldialog.h"
     
     GoToCellDialog::GoToCellDialog(QDialog *parent) :
         QDialog(parent), ui(new Ui::GoToCellDialog)
     {
         ui->setupUi(this);
     }
     
     CalculatorForm::~CalculatorForm()
     {
         delete ui; // 切记删除,释放资源
     }
     
     三、多继承方式(The Multiple Inheritance Approach)
            多继承方式就是自定义的类从窗体类和Ui类多重派生。看代码就清楚了:
     
    头文件:
     
    #ifndef GOTOCELLDIALOG_H
    #define GOTOCELLDIALOG_H
     
    #include <QDialog>
    #include "ui_gotocelldialog.h"
     
    class GoToCellDialog :  public QDialog, public Ui::GoToCellDialog
    {
        Q_OBJECT
     
    public:
        explicit GoToCellDialog(QWidget *parent = 0);
     
    private slots:
        void on_lineEdit_textChanged();
    };
     
    #endif // GOTOCELLDIALOG_H
     
     
    实现文件:
     
    #include "gotocelldialog.h"
     
    #include <QtGui>
     
    GoToCellDialog::GoToCellDialog(QWidget *parent)
        : QDialog(parent)
    {
        this->setupUi(this); //第1个this指Ui::GoToCellDialog,第2个this指(QDialog) 即 Ui::GoToCellDialog->setupUi(QDialog)
     
        QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
        lineEdit->setValidator(new QRegExpValidator(regExp, this));
     
        connect(okButton, SIGNAL(clicked()), SLOT(accept()));
        connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));
    }
     
    void GoToCellDialog::on_lineEdit_textChanged()
    {
        // bool hasAcceptableInput () const
        // This property holds whether the input satisfies the inputMask and the validator.
        // By default, this property is true.
        okButton->setEnabled(lineEdit->hasAcceptableInput());
     

    PS:关于UI界面中的国际化

           如果用户界面语言发送了改变,Qt通过发送 QEvent::LanguageChange 事件通知应用程序。为了调用 retranslateUi() 函数以达到切换语言的目的,我们需要重新实现界面类里面的QWidget::changeEvent() 事件处理函数。

    Reacting to Language Changes

    Qt notifies applications if the user interface language changes by sending an event of the type QEvent::LanguageChange. To call the member function retranslateUi() of the user interface object, we reimplement QWidget::changeEvent() in the form class, as follows:

     
     void CalculatorForm::changeEvent(QEvent *e)
     {
         QWidget::changeEvent(e);
         switch (e->type()) {
         case QEvent::LanguageChange:
             ui->retranslateUi(this);
             break;
         default:
             break;
        }
     }
     
     
       除了在编译时处理ui文件外,Qt还提供了在运行时动态加载ui文件的机制。通过QtUiTools模块的QUiLoader可以在运行时加载ui文件。

        加载ui文件的方式如以下代码所示:

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. QWidget* TextFinder::loadUiFile()  
    2. {  
    3.     QUiLoader loader;  
    4.   
    5.     QFile file(":/forms/textfinder.ui"); //  文件名可以是绝对路径或相对于应用程序的相对路径  
    6.     file.open(QFile::ReadOnly);  
    7.   
    8.     QWidget *formWidget = loader.load(&file, this);  
    9.     file.close();  
    10.   
    11.     return formWidget;  
    12. }  

       使用方式:
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. ui_lineEdit = qFindChild<QLineEdit*>(formWidget, "lineEdit"); //  需要指定对象的名字QUiLoader类放在一个独立的库中。  


       为了在应用程序中使用QUiLoader,必须在工程文件 .pro 中加入一行内容:

                         CONFIG += uitools

        在实际项目中,动态加载ui文件的需求似乎不怎么强烈,我所经历的项目就还从来没有使用过这种方式。


  • 相关阅读:
    第4月第1天 makefile automake
    第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash
    第3月第27天 uitableviewcell复用
    learning uboot fstype command
    learning uboot part command
    linux command dialog
    linux command curl and sha256sum implement download verification package
    learning shell script prompt to run with superuser privileges (4)
    learning shell get script absolute path (3)
    learning shell args handing key=value example (2)
  • 原文地址:https://www.cnblogs.com/findumars/p/5185124.html
Copyright © 2011-2022 走看看