我们知道,QT是一个图形化界面设计的第三方库,功能很强大,可以和python、C++等多种语言配合,提供图形化界面库。
在QT中创建一个应用程序,从大的方面分,有两种界面。一种是控制台界面(Console Application),一种是图形用户界面(Widget Application)。
而在QT图形用户界面(GUI)程序创建中,又有两种选项:可视化方法(在创建应用程序的向导中,勾选生成*.ui文件)和纯代码方法(不勾选生成*.ui文件)。本文今天探讨的是可视化方法背后的机理。
在QT 中,完成可视化界面设计的是QT Designer软件, 用户只需要把控件一个个拖放到QWidget界面上,安排好位置,不用写相关代码,这些写代码的工作都由Designer在后台自动完成了。
Designer后台完成代码后,对外部会提供一个接口给程序员,这个接口就是 *ui,即ui指针。在Designer生成的代码内部,定义了一个名字空间(namespace) Ui。在这个名字空间中,放置了一个类的完整定义形式,正是这个类负责创建控件、控件布局、关联信号槽等工作。
初学者在看这些代码的时候,往往云里雾里,一方面,QT背后有一套机理,把可视化的工作转化为实现的代码,另一方面,用到的C++语法比较深,比如类的继承、对象的指针、名字空间、动态创建对象,都是C++中比较深奥难懂的知识点。想要清晰明了地理解这里的机制,难度不是一般的大。
下面通过一个具体例子,说明可视化创建一个图形界面程序的过程,并对背后的机理,用伪代码方式,进行深入浅出的说明。重点是提出了中间类(mid_GUI)的概念,涵盖设计师(Designer)所作的工作,设计师会在内部设计一个类,这个类不对外,所以一直没有一个统一的名称,英文资料没有,中文各种技术博客也没有统一。对这个类的中文命名,如果拘泥于技术术语就会晦涩难懂。本文从这个类的作用出发,命名为“中间类”,非常形象贴切,这个名称的字面意思,就能提供类的作用是充当图形界面和可视乎图形控件之间的桥梁,接地气,好理解。这个命名的提出,能够给那些热爱C++ QT编程的初学者一个清晰的概念,为学子扫清学习中的障碍创造良好的条件。
程序包含三个方面的内容:
1、 用QT Designer(设计师) 可视化定义一个QWidge为Base class的窗体类Widget,拖放QPushButton、 QLabel、 QLineEdit到界面内。
2、 设计师在后台创建中间类,包含三个QPushButton、 QLabel、 QLineEdit。然后把这个创建界面耦合类添加为Widget类的一个新成员,这个新成员在Widget类中用指针ui代表。
3、 在Widget类的成员函数中,用ui指针引用ui的成员QPushButton、 QLabel、 QLineEdit三个控件,编写代码操作这些控件。
把这些工作用伪代码的方式展示:
第一步:选用QWidget类作为基类,创建myWindow自定义类(勾选.ui文件选项)。这是QT程序员根据向导创建的图形界面的类。Designer并不会另外再创建图形界面,只是在利用这个图形界面,然后创建控件并安排在这个图形界面中。
class myWindow( ) : public QWidgt...
{
public:
....
myWindow( );
~ myWindow( );
private:
....
};
myWindow w;
第二步:Qt Designer在后台创建中间类,把可视化界面上的控件都纳入该类的成员。这个中间类,是设计师内部定义的,不同于程序员定义的myWindow类。中间类会传入myWindow类的指针,从而在中间类和程序主窗口之间架起了桥梁,中间类的得名,也是受此启发。
中间类代码示意:
class mid_GUI
{
public:
...
private:
QPushButton *pushButton;
QLable *label;
QLineEdit *lineEdit;
};
第三步:myWindow类的定义中,添加一个中间类的指针变量( mid_GUI *ui)作为成员变量。
class myWindow( )
{
public:
....
myWindow( );
~ myWindow( );
private:
mid_GUI *ui;
};
在myWindow的成员函数中,多了一个中间类的指针,表示中间类在创建对象时,需要使用动态创建的方式(new命令)。在中间类的定义中,按钮等控件作为其成员,类型也是指针类型。
取图形界面中控件的代码写法,比如取图形界面中的按钮对象,就需要经过两重指针,第一重指的是myWindow成员--ui指针,第二重是中间类mid_GUI的成员--指针pushButton。这样引用可视化界面中控件的语法:
ui→pushButton→setText(“click me”);
到这里,对设计师(QT Designer)所作的工作,已经诠释完毕。如果再深入一点,可以看看设计师在名字空间中对类做了完整的定义:
namespace Ui
{
class myWindow: pubilic ui_MyWindow
{
};
}
QT软件把设计师在后台定义的内部类,取了一个与程序员定义的窗口类相同的名字,并且用名字控件Ui来限定,以示区别。在程序员定义的类中,自动添加了一行代码 namespace Ui ( class myWindow;), 把设计师创建的内部类及其名字空间在myWindow类中通告一下,告诉你,Ui名字空间及其包含的同名类myWindow是设计师后台生成的。不得不说,这个处理方法,很容易引起初学者的混淆,因此,本文对设计师的内部类Ui::myWindow起了一个别名mid_GUI,以示这个类不是程序员定义的那个myWindow类,把QT架构中的一个大坑给排除了。
【结束语】
本文回顾了QT设计师辅助程序员设计图形化界面的机理,提出一个重要别名:中间类(mid_GUI),以帮助初学者消化、理解图形界面创建的背后机制,从而自由驰骋在C++ QT代码的世界。