博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[转] Qt namespace Ui

Posted on 2011-11-05 19:24  |orz  阅读(2187)  评论(0编辑  收藏  举报
  1 /*****************************************************************************/
2 dialog.h
3 /*****************************************************************************/
4 #ifndef DIALOG_H
5 #define DIALOG_H
6
7 #include <QtGui/QDialog>
8
9 namespace Ui
10 {
11 class Dialog;
12 }
13
14 class Dialog : public QDialog
15 {
16 Q_OBJECT
17
18 public:
19 Dialog(QWidget *parent = 0);
20 ~Dialog();
21
22 private:
23 Ui::Dialog *ui;
24 };
25
26 #endif // DIALOG_H
27 /*****************************************************************************/
28 ui_dialog.h
29 /*****************************************************************************/
30 /********************************************************************************
31 ** Form generated from reading ui file 'dialog.ui'
32 **
33 ** Created: Thu May 14 22:52:58 2009
34 ** by: Qt User Interface Compiler version 4.5.0
35 **
36 ** WARNING! All changes made in this file will be lost when recompiling ui file!
37 ********************************************************************************/
38
39 #ifndef UI_DIALOG_H
40 #define UI_DIALOG_H
41
42 #include <QtCore/QVariant>
43 #include <QtGui/QAction>
44 #include <QtGui/QApplication>
45 #include <QtGui/QButtonGroup>
46 #include <QtGui/QDialog>
47 #include <QtGui/QHeaderView>
48 #include <QtGui/QListView>
49 #include <QtGui/QPushButton>
50
51 QT_BEGIN_NAMESPACE
52
53 class Ui_Dialog
54 {
55 public:
56 QListView *listView;
57 QPushButton *pushButton
58
59
60 void setupUi(QDialog *Dialog)
61 {
62 if (Dialog->objectName().isEmpty())
63 Dialog->setObjectName(QString::fromUtf8("Dialog"));
64 Dialog->resize(600, 400);
65 listView = new QListView(Dialog);
66 listView->setObjectName(QString::fromUtf8("listView"));
67 listView->setGeometry(QRect(30, 10, 256, 192));
68 pushButton = new QPushButton(Dialog);
69 pushButton->setObjectName(QString::fromUtf8("pushButton"));
70 pushButton->setGeometry(QRect(140, 280, 75, 23));
71
72 retranslateUi(Dialog);
73
74 QMetaObject::connectSlotsByName(Dialog);
75 } // setupUi
76
77 void retranslateUi(QDialog *Dialog)
78 {
79 Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", 0, QApplication::UnicodeUTF8));
80 pushButton->setText(QApplication::translate("Dialog", "bye", 0, QApplication::UnicodeUTF8));
81 Q_UNUSED(Dialog);
82 } // retranslateUi
83
84 };
85
86 namespace Ui {
87 class Dialog: public Ui_Dialog {};
88 } // namespace Ui
89
90 QT_END_NAMESPACE
91
92 #endif // UI_DIALOG_H
93 /*******************************************************************************/
94 dialog.cpp
95 /*******************************************************************************/
96
97 #include "dialog.h"
98 #include "ui_dialog.h"
99
100 Dialog::Dialog(QWidget *parent)
101 : QDialog(parent), ui(new Ui::Dialog)
102 {
103 ui->setupUi(this);
104 //QObject::connect(ui->pushButton, SIGNAL(clicked()),this, SLOT(quit()));
105 }
106
107 Dialog::~Dialog()
108 {
109 delete ui;
110 }
111 /********************************************************************************/

ui_dialog.h代码中有很多被硬编码的地方:

listView->setGeometry(QRect(30, 10, 256, 192)); 
pushButton = new QPushButton(Dialog);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(140, 280, 75, 23));

designer生成的这个东西, 如何让程序的其他代码去使用呢?

最直接的, 它应该产生一个:

class Ui_Dialog {
QListView *listView;
QPushButton *pushButton;
};

这样的类去让其他代码使用:

 1 // My.h
2 #include "ui_dialog.h"
3 class My
4 {
5 Ui_Dialog dlg;
6 };
7
8 // My.cpp
9 #include "My.h"
10 // 实现My

但是这样存在问题, 如果ui_dialog.h文件的内容被改变, 不但My.cpp会被重新编译,
所有包含My.h的文件也都会被重新编译。
而且这确实是一个问题: designer确实经常被拖来拖去。

如果产生ui_dialog.h的那个程序能将如下代码:

listView->setGeometry(QRect(30, 10, 256, 192)); 
pushButton = new QPushButton(Dialog);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(140, 280, 75, 23));

移动到一个ui_dialog.cpp 中, 至少在移动dlg上的那些界面元素时,  只会重新编译ui_dialog.cpp。
不会修改ui_dialog.h, 也就不会引发另一连串重编译。

但是, 除了将界面元素拖来拖去, designer还经常干的一些事就是添加,删除一些界面元素,如:

class Ui_Dialog 
{
public:
QListView *listView;
QPushButton *pushButton;
// ...
};

这样 ui_dialog.h 文件还是得改变。
如何让designer改变GUI外观后, 不会引发工程大范围的重新编译?

所以designer使用了pimpl手法 ……

前置声明一个 Ui:: Dialog类

namespace Ui  { 
class Dialog;
}

class Dialog : public QDialog {
Ui:: Dialog *ui; // 使用该类的一个指针
};

然后用户使用 dialog.h 头文件以及 Dialog类。
该文件被修改的频率就会低很多很多。
无论是将designer上的界面元素拖来拖去, 还是添加删除, dialog.h文件的内容——Dialog类的定义——都不会改变。

然后用户可以使用这个Dialog了:

#include "dialog.h"
class My
{
Dialog dlg;
};

Ui 创建两种不同的方式:
1. 在qt4中使用了继承的方式来使用designer创建的窗体,也就是同时继承QDialog和UI_Dialog。

2. 而在Qt Creator自动创建的项目中,使用了组合的方式来使用Designer创建的窗体,就是集成QDialog,而将UI_Dialog作为一个成员变量来使用,也就是

private:
Ui::Dialog *ui;

区别:
在前一种方式中,你可以在继承类中直接使用UI_Dialog上的组件。
在后一种方式中,你要使用ui->XXX的方式使用UI_Dialog上的组件。
两种方式都可以,但个人感觉第二种好一些,毕竟组合比继承的耦合度来的弱一些,就是稍有点麻烦,要加ui->,但同时也带来了更清晰的代码结构。