在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)。

[cpp] view plain copy print?

  1. #include "ui_gotocelldialog.h"    // uic工具将gotocelldialog.ui生成的C++代码
  2. int main(int argc, char *argv[])
  3. {
  4. QApplication app(argc, argv);
  5. QDialog *dialog= new QDialog;  // 用于显示界面的父窗体QDialog(QWidget的子类)
  6. Ui::GotoCellDialog ui;  // 界面类,必须显示在一个QWidget(或其子类)上
  7. ui.setupUi(dialog); // 将QDialog设置为 GotoCellDialog 的父窗体,这样GotoCellDialog 里面定义的控件就会显示在QDialog窗体内
  8. dialog->show();
  9. return app.exec();
  10. }

 #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

[cpp] view plain copy print?

  1. #include <QDialog>
  2. #include "ui_gotocelldialog.h" // 因为是成员变量形式,必须包含相应的头文件
  3. class GoToCellDialog: public QDialog
  4. {
  5. Q_OBJECT
  6. public:
  7. explicit GoToCellDialog(QDialog *parent = 0);
  8. private slots:
  9. void on_lineEdit_textChanged();
  10. private:
  11. Ui::GoToCellDialog ui;
  12. };

#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

[cpp] view plain copy print?

  1. #include "gotocelldialog.h"
  2. #include <QtGui>
  3. GoToCellDialog::GoToCellDialog(QWidget *parent)
  4. : QDialog(parent)
  5. {
  6. ui.setupUi(this);
  7. QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
  8. lineEdit->setValidator(new QRegExpValidator(regExp, this));
  9. connect(okButton, SIGNAL(clicked()), SLOT(accept()));
  10. connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));
  11. }
  12. void GoToCellDialog::on_lineEdit_textChanged()
  13. {
  14. // bool hasAcceptableInput () const
  15. // This property holds whether the input satisfies the inputMask and the validator.
  16. // By default, this property is true.
  17. okButton->setEnabled(lineEdit->hasAcceptableInput());
  18. }

#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;

因此,相应的头文件中只要前置声明即可:

[cpp] view plain copy print?

  1. namespace Ui
  2. {
  3. class GoToCellDialog;
  4. } // 前置声明即可,只在实现文件中包含相应的头文件
  5. class GoToCellDialog: public QDialog
  6. {
  7. // 同上
  8. private:
  9. Ui::GoToCellDialog *ui;
  10. };

namespace Ui
{
    class GoToCellDialog;
} // 前置声明即可,只在实现文件中包含相应的头文件 

class GoToCellDialog: public QDialog
{
      // 同上
 private:
       Ui::GoToCellDialog *ui;
};

实现文件:

[cpp] view plain copy print?

  1. #include "ui_gotocelldialog.h"
  2. GoToCellDialog::GoToCellDialog(QDialog *parent) :
  3. QDialog(parent), ui(new Ui::GoToCellDialog)
  4. {
  5. ui->setupUi(this);
  6. }
  7. CalculatorForm::~CalculatorForm()
  8. {
  9. delete ui; // 切记删除,释放资源
  10. }

#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类多重派生。看代码就清楚了:

头文件:

[cpp] view plain copy print?

  1. #ifndef GOTOCELLDIALOG_H
  2. #define GOTOCELLDIALOG_H
  3. #include <QDialog>
  4. #include "ui_gotocelldialog.h"
  5. class GoToCellDialog :  public QDialog, public Ui::GoToCellDialog
  6. {
  7. Q_OBJECT
  8. public:
  9. explicit GoToCellDialog(QWidget *parent = 0);
  10. private slots:
  11. void on_lineEdit_textChanged();
  12. };
  13. #endif // GOTOCELLDIALOG_H

#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

实现文件:

[cpp] view plain copy print?

  1. #include "gotocelldialog.h"
  2. #include <QtGui>
  3. GoToCellDialog::GoToCellDialog(QWidget *parent)
  4. : QDialog(parent)
  5. {
  6. this->setupUi(this); //第1个this指Ui::GoToCellDialog,第2个this指(QDialog) 即 Ui::GoToCellDialog->setupUi(QDialog)
  7. QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
  8. lineEdit->setValidator(new QRegExpValidator(regExp, this));
  9. connect(okButton, SIGNAL(clicked()), SLOT(accept()));
  10. connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));
  11. }
  12. void GoToCellDialog::on_lineEdit_textChanged()
  13. {
  14. // bool hasAcceptableInput () const
  15. // This property holds whether the input satisfies the inputMask and the validator.
  16. // By default, this property is true.
  17. okButton->setEnabled(lineEdit->hasAcceptableInput());
  18. }

#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:

[cpp] view plain copy print?

  1. void CalculatorForm::changeEvent(QEvent *e)
  2. {
  3. QWidget::changeEvent(e);
  4. switch (e->type()) {
  5. case QEvent::LanguageChange:
  6. ui->retranslateUi(this);
  7. break;
  8. default:
  9. break;
  10. }
  11. }
  12. http://blog.csdn.net/e5max/article/details/9869977
时间: 2024-12-28 00:34:21

在Qt中如何使用QtDesigner创建的UI文件(一) (转)的相关文章

在Qt中如何使用QtDesigner创建的UI文件

使用Qt有一些时间了,一直在IDE环境(qtcreator和VS2003+集成器)中使用,自然少了很多麻烦的步骤.但是在享受这种便利的同 时,我们也失去了理解更多知识背后的点滴.在IDE中,如果我们要开发一个对话框,通常是使用 “新建—>Qt—>Qt设计师界面类” 这样IDE会自动的帮我们生成三个文件(filename.ui, filename.h,filename.cpp).qmake也非常智能,可以自动检测到这个用户界面文件(filename.ui)并且生产适当的 makefile规则.这

使用 PySide2 开发 Maya 插件系列一:QT Designer 设计GUI, pyside-uic 把 .ui 文件转为 .py 文件

使用 PySide2 开发 Maya 插件系列一:QT Designer 设计GUI, pyside-uic 把 .ui 文件转为 .py 文件 前期准备: 安装 python:https://www.python.org/downloads/ 安装 PySide2:安装 python 后,在安装目录下有 /script 文件夹,里面有 pip.exe ,cmd执行:pip install PySide,pip install PySide2(注意: python2.x 对应 PySide,py

在Qt中使用C++代码创建界面

Qt 支持两种创建界面的方式: 一种是使用C++代码,Qt 自诞生以来就支持: 一种是使用 QML,可以创建个性化的界面: Qt 提供了多种工程类型,选择不同的工程类型将导致使用不同的方式来创建界面. 首次打开Qt,会出现欢迎界面,点击New Project按钮,或者在菜单栏点击文件,然后选择新建文件或项目, 都会弹出向导对话框,如下图所示:(不同的Qt编译器版本,界面可能会有所差别) Qt Widgets Application和Qt Console Application工程将会使用C++代

javaScript中利用ActiveXObject来创建FileSystemObject操作文件

注:如果用javascript读本地文件,遇到安全问题. 需在浏览器中进行设置,如下:     工具—> Internet选项->安全->自定义级别->启用“没有标识为安全的ActiveX控件进行初始化和脚本运行” 一.功能实现核心:FileSystemObject 对象   要在javascript中实现文件操作功能,主要就是依靠FileSystemobject对象. 二.FileSystemObject编程 使用FileSystemObject 对象进行编程很简单,一般要经过如

QT中检索设定目录下所有指定文件的方法

void MainWindow::on_pushButton_clicked() { QDir dir=QFileDialog::getExistingDirectory(this, tr("Open Directory"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); QStringList nameFilters; nameFilters << "*.

QT中的qmake详解

关于qmake,好一段时间令我一头雾水,不知道用来干嘛的,只知道怎么用,而且也只懂那么一两个命令,详细看过资料以后整理如下: 1.首先,感性的认识是,qmake可以利用源文件(包括头文件h,实现文件cpp,qt的ui文件等等)生成各种不同类型的工程,工程需要的Makefile文件,可执行的与不可执行的,这取决于所用的模板(包括app.lib.subdirs.vcapp.vclib). 2.创建pro文件,添加各种源文件,还可以设定平台相关的不同源文件,设置各种规则,利用qmake命令生成工程.后

qt中进程的使用

qt中的进程使用需要用到头文件:include<QProcess> 首先来看看需要用到的主要的函数 (1)进程的定义: QProcess *mprocess; //定义一个进程参数 (2)进程的初始化: //初始化进程对象 mprocess = new QProcess(); (3)启动进程 //启动计算器 mprocess->start("calc"); (4)使用进程读取数据 while(mprocess->canReadLine()) //全部读出进程中的

QT中QtConcurrent创建并行线程的方法

本文介绍了Qt中QtConcurrent的使用方式,由于作者不习惯该编辑器,现将作者的语雀链接分享出来:https://×××w.yuque.com/docs/share/b113af35-f23b-4120-83dd-d123fe1c9cb5 原文地址:http://blog.51cto.com/4754569/2321337

第三十八课、Qt中的事件处理(上)

一.图形界面应用程序的消息处理模型 二.Qt的事件处理 1.Qt平台将系统产生的消息转换为Qt事件(每一个系统消息对象Qt平台的一个事件) (1).Qt事件是一个QEvent的对象 (2).Qt事件用于描述程序内部或者外部发生的动作 (3).任意的QObject对象都具备事件处理的能力 2.GUI应用程序的事件处理方式 (1).Qt事件产生后立即被分发到QWidget对象 (2).QWidget中的event(QEvent*)进行事件处理 (3).event()根据事件类型调用不同的事件处理函数