qingxiao的个人空间 https://bbs.21ic.com/?2545062 [收藏] [复制] [RSS]

日志

给初学Qt者的小TIP

已有 294 次阅读2017-10-14 11:01 |系统分类:兴趣爱好

1、Hello, Qt!

我们以一个非常简单的 Qt 程序开始 Qt 的学习。我们首先一行行的分析代码,然后我

们将会看到怎样编译和运行这个程序。

1 #include <QApplication>

2 #include <QLabel>

3 int main (int argc, char *argv [])

4 {

5 QApplication app (argc, argv);

6 QLabel *label = new QLabel ("Hello Qt!");

7 label->show ();

8 return app. exec ();

9 }

1 行和第 2 行包含了两个类的定义:QApplication 和 QLabel。对于每一个 Qt 的类,

都会有一个同名的头文件,头文件里包含了这个类的定义。因此,你如果在程序中使用了一

个类的对象,那么在程序中就必须包括这个头文件。

3 行是程序的入口。几乎在使用 Qt 的所有情况下,main()函数只需要在把控制权转

交给 Qt 库之前执行一些初始化,然后 Qt 库通过事件来向程序告知用户的行为。argc 是命

令行变量的数量,argv 是命令行变量的数组。这是一个 C/C++特征。它不是 Qt 专有的,无

论如何 Qt 需要处理这些变量

5 行定义了一个 QApplication 对象 App。QApplication 管理了各种各样的应用程序的

广泛资源,比如默认的字体和光标。 App 的创建需要 argc 和 argv 是因为 Qt 支持一些自己的

命令行参数。在每一个使用 Qt 的应用程序中都必须使用一个 QApplication 对象,并且在任

Qt 的窗口系统部件被使用之前创建此对象是必须的。App 在这里被创建并且处理后面的

命令行变量(比如在 X 窗口下的-display)。请注意,所有被 Qt 识别的命令行参数都会从 argv

中被移除(并且 argc 也因此而减少)。

6 行创建了一个 QLabel 窗口部件(widget) ,用来显示“Hello,Qt!”。在 Qt 和 Unix

的术语中,一个窗口部件就是用户界面中一个可见的元素,它相当于 Windows 术语中的“容

”加上“控制器”。按钮(Button)、菜单(menu)、滚动条(scroll bars)和框架(frame)

都是窗口部件的例子。窗口部件可以包含其它的窗口部件。例如,一个应用程序界面通常就

是一个包含了 QMenuBar,一些 QToolBar,一个 QStatusBar 和其它的一些部件的窗口。绝大

多数应用程序使用一个 QMainWindow 或者一个 QDialog 作为程序界面,但是 Qt 允许任何

窗口部件成为窗口。在这个例子中,QLabel 窗口部件就是作为应用程序主窗口的。

7 行使我们创建的 QLabel 可见。当窗口部件被创建的时候,它总是隐藏的,必须调

show()来使它可见。通过这个特点我们可以在显示这些窗口部件之前定制它们,这样就不

会出现闪烁的情况。

8 行就是 main()将控制权交给 Qt。在这里,程序进入了事件循环。事件循环是一种

stand-by 的模式,程序会等待用户的动作(比如按下鼠标或者是键盘)。用户的动作将会产

生程序可以做出反应的事件(也被称为“消息”) 。程序对这些事件的反应通常是执行一个或

几个函数。

为了简单起见,我们没有在 main()函数的结尾处调用 delete 来删除 QLabel 对象。这种

内存泄露是无害的,因为像这样的小程序,在结束时操作系统将会释放程序占用的内存堆。

下面我们来编译这个程序。建立一个名为 hello 的目录,在目录下建立一个名为 hello.cpp

c++源文件,将上面的代码写入文件中。

运行“开始à程序àQt by TrolltechàQt Command Prompt”。

在命令行模式下,切换目录到 hello 下,然后输入命令:qmake    –project。这个命令将

产生一个依赖于工作平台的工程文件(hello.pro)。

再输入命令:qmake    hello.pro。这个命令通过工程文件产生一个可以在特定工作平台

上使用的 makefile。

最后输入命令:make 来产生应用程序。运行这个程序,可以得到如下的程序界面。

Qt 也支持 XML。我们可以把程序的第 6 行替换成下面的语句:

QLabel *label = new QLabel ("<h2><i>Hello</i> " "<font color=red>Qt! </h2>");

重新编译程序,我们发现界面拥有了简单的 HTML 风格。如下图:

2、调用退出信盈达嵌入式企鹅要妖气呜呜吧久零就要

第二个例子展示了如何使应用程序对用户的动作进行响应。这个应用程序包括了一个按

钮,用户可以点击这个按钮来退出程序。程序代码与上一个程序非常相似,不同之处在于我

们使用了一个 QPushButton 来代替 QLabel 作为我们的主窗口,并且我们将一个用户动作(点

击一个按钮)和一些程序代码连接起来。

1 #include <QApplication>

2 #include <QPushButton>

3 int main (int argc, char *argv [])

4 {

5 QApplication app (argc, argv);

6 QPushButton *button = new QPushButton ("Quit");

7 QObject::connect (button, SIGNAL (clicked ()),

8 &app, SLOT (quit ()));

9 button->show ();

10 return app. exec ();

11 }

Qt 程序的窗口部件发射信号(signals)来指出一个用户的动作或者是状态的变化。在这

个例子中,当用户点击这个按钮的时候,QPushButton 就会发射一个信号——clicked()。一

个信号可以和一个函数(在这种情况下我们把这个函数叫做“槽(slot)”)相连,当信号

被发射的时候,和信号相连的槽就会自动执行。在这个例子中,我们把按钮的信号“clicked()”

和一个 QApplication 对象的槽“quit()”相连。当按钮被按下的时候,这个程序就退出了。

3、窗口布局

在本小节,我们将用一个样例来展现如何在窗口中规划各个部件的布局,并学习使用信

号和槽来使两个窗口部件同步。这个应用程序要求输入用户的年龄,使用者可以通过一个旋

转窗口或者一个滑块窗口来输入。

这个应用程序包括三个窗口部件:一个 QSpinBox,一个 QSlider 和一个 QWidget。窗口

部件 QWidget 是程序的主窗口。 QSpinBox 和 QSlider 被放置在 QWidget 中;他们是 QWidget

的子窗口。当然,我们也可以说 QWidget 是 QSpinBox 和 QSlider 的父窗口。QWidget 本身

没有父窗口,因为它被当作一个顶级的窗口。 QWidget 以及所有它的子类的构造函数都拥有

一个参数:QWidget *,这说明了它的父窗口。

下面是程序的代码:

1 #include <QApplication>

2 #include <QHBoxLayout>

3 #include <QSlider>

4 #include <QSpinBox>

5 int main (int argc, char *argv [])

6 {

7 QApplication app (argc, argv);

8 QWidget *window = new QWidget;

9 window->setWindowTitle ("Enter Your Age");

10 QSpinBox *spinBox = new QSpinBox;

11 QSlider *slider = new QSlider (Qt::Horizontal);

12 spinBox->setRange (0, 130);

13 slider->setRange (0, 130);

14 QObject::connect (spinBox, SIGNAL (valueChanged (int)),

15 slider, SLOT (setValue (int)));

16 QObject::connect (slider, SIGNAL (valueChanged (int)),

17 spinBox, SLOT (setValue (int)));

18 spinBox->setValue (50);

19 QHBoxLayout *layout = new QHBoxLayout;

20 layout->addWidget (spinBox);

21 layout->addWidget (slider);

22 window->setLayout (layout);

23 window->show ();

24 return app. exec ();

25 }

8 行和第 9 行设置了 QWidget ,它将被作为程序的主窗口。我们调 用函数

setWindowTitle()来设置窗口的标题栏。

10 行和第 11 行创建了一个 QSpinBox 和一个 QSlider,第 12 行和第 13 行设置了它们

的取值范围(我们假设用户最大也只有 130 岁)。我们可以将之前创建的 QWidget 对象 window

传递给 QSpinBox 和 QSlider 的构造函数,用来说明这两个对象的父窗口,但是这么做并不

是必须的。原因是窗口布局系统将会自己指出这一点,自动将 window 设置为父窗口。我们

一会儿就可以看到这个特性。

在第 14 行和第 17 行,两个对于 QObject::connect()函数的调用确保了旋转窗口和滑块窗

口的同步,这样这两个窗口总是显示同样的数值。不管一个窗口对象的数值何时发生变化,

它的信号 valueChanged(int)就将被发射,而另一个窗口对象的槽 setValue(int)会接受到这个信

号,使得自身的数值与其相等。

18 行将旋转窗口的数值设置为 50。当这个事件发生的时候,QSpinBox 发射信号

valueChanged(int) ,这个信号包括一个值为 50 的整型参数。这个参数被 QSlider 的槽

setValue(int)接受,就会将滑块的值也设置为 50。由于 QSlider 的值被改变,所以 QSlider 也

会发出一个 valueChanged(int)信号并触发 QSpinBox 的 setValue(int)槽。但是在这个时候,

QSpinBox 不会再发出任何信号,因为旋转窗口的值已经被设置为 50 了。这将有效地防止信

号的无限循环。

从第 19 行到第 22 行,我们通过使用一个 layout 管理器对旋转窗口和滑块窗口进行了布

局设置。一个布局管理者就是一个根据窗口作用设置其大小和位置的对象。Qt 有三个主要

的布局管理类:

QHBoxLayout:将窗口部件水平自左至右设置(有些情况下是自右向左)。

QVBoxLayout:将窗口部件垂直自上向下设置。

QGridLayout:  以网格形式设置窗口部件。

22 行我们调用 QWidget::setLayout()函数在对象 window 上安装布局管理器。通过这

个调用,QSpinBox 和 QSlider 自动成为布局管理器所在窗口的子窗口。现在我们明白为什

么在设置子窗口时不用显式地说明父窗口了。

可以看到,虽然没有明显地给出任何窗口的大小和位置,但 QSpinBox 和 QSlider 是很

完美地被水平依次放置的。这是因为 QHBox-Layout 根据各个窗口的作用自动的为其设置了

合理的大小和位置。这个功能使我们从烦琐的界面调整中解放出来,更加专注于功能的实现。

Qt 构建用户界面的方法很容易理解,并且有很高的灵活性。Qt 程序员最常用的设计模

式是:说明所需要的窗口部件,然后设置这些部件必须的特性。程序员把窗口部件添加到布

局管理器中,布局管理器就将自动地设置这些部件的大小和位置。而用户界面的行为是通过

连接各个部件(运用信号/槽机制)来实现的。

4、派生 QDialog

我们现在开始尝试着在 Qt 里只用 C++语言而不是借助界面设计器来完成一个对话框:

FIND。我们将这个对话框作为一个类来完成,这么做的好处是我们使这个对话框成为了一

个独立的,拥有自己的信号和槽的,设备齐全的组件。

程序的源代码由两部分组成:finddialog.h 和 finddialog.cpp。我们从头文件开始。

1 #ifndef    FINDDIALOG_H

2 #define    FINDDIALOG_H

3 #include <QDialog>

4 class QCheckBox;

5 class QLabel;

6 class QLineEdit;

7 class QPushButton;

1 行,第 2 行(和第 27 行)的作用是防止头文件被重复包含。

3 行包含了 QDialog 的定义。QDialog 从 QWidget 继承而来,是 Qt 的对话框基类。

4 行到第 7 行是对我们将要用来填充对话框的对象的类的预定义。一个预先的声明

将会告诉 C++编译器这个类的存在,而不用给出所有关于实现的细节。

然后我们定义 FindDialog 作为 QDialog 的一个子类:

8 class FindDialog: public QDialog

9 {

10  Q_OBJECT

11 public:

12 FindDialog (QWidget *parent = 0);

在类定义顶端出现了宏:Q_OBJECT。这对于所有定义了信号或槽的类都是必须的。

FindDialog 的构造函数拥有 Qt 窗口类的典型特征。参数 parent 声明了父窗口。其默认

值是一个空指针,表示这个对话框没有父窗口。

13 signals:

14 void findNext (const QString &str, Qt::CaseSensitivity cs);

15    void findPrevious (const QString &str, Qt::CaseSensitivity cs);

标记为  signals 的这一段声明了两个信号。当用户点击对话框的“Find”按钮的时候,

信号将被发射。如果选项“Search backward”被选中,对话框将发射消息 findPrevious();相

反的,对话框将发射消息 findNext()。

关键字“signals”实际上也是一个宏。 C++预处理器将在编译器看到它之前就已经将它


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)