最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

Qt简明教程

来源:动视网 责编:小OO 时间:2025-10-03 04:19:09
文档

Qt简明教程

Qt简明教程1、Qt的安装首先去Qt的官方网站(http://qt.nokia.com/downloads)下载你所需要的安装包,官方提供了Windows、Linux、MacOS等平台的安装包,这里我们选择Linux平台下的安装包。截至到目前为止,Qt的最新版本为4.7,所以我们下载所对应的安装包为qt-sdk-linux-x86-opensource-2010.05.1.bin。下载完毕后我们打开超级终端,切换到root用户(sudosu),然后提升安装包的权限,使其具有执行权限,接着执行.
推荐度:
导读Qt简明教程1、Qt的安装首先去Qt的官方网站(http://qt.nokia.com/downloads)下载你所需要的安装包,官方提供了Windows、Linux、MacOS等平台的安装包,这里我们选择Linux平台下的安装包。截至到目前为止,Qt的最新版本为4.7,所以我们下载所对应的安装包为qt-sdk-linux-x86-opensource-2010.05.1.bin。下载完毕后我们打开超级终端,切换到root用户(sudosu),然后提升安装包的权限,使其具有执行权限,接着执行.
Qt简明教程

1、Qt的安装

首先去Qt的官方网站(http://qt.nokia.com/downloads)下载你所需要的安装包,官方提供了Windows、Linux、Mac OS等平台的安装包,这里我们选择Linux平台下的安装包。截至到目前为止,Qt的最新版本为4.7,所以我们下载所对应的安装包为qt-sdk-linux-x86-opensource-2010.05.1.bin。

下载完毕后我们打开超级终端,切换到root用户(sudo su),然后提升安装包的权限,使其具有执行权限,接着执行./ qt-sdk-linux-x86-opensource-2010.05.1.bin,弹出如下界面:

接着按照提示,一路next就可以了,安装完成后,接下来我们开始进入Qt的学习过程。

2、Qt的发展史

Qt的创建者Haarard Nord(Trolltech公司的CEO)和Eirik Chambe-Eng(Trolltech公司的总裁)是一家瑞典公司的同事。那时(1990)他们在做一个项目,这个项目需要在Unix,Macintosh,Windows上运行同一个GUI,象我们现在的开发人员一样,工作的很累,当时可是没有如今这么多的开发工具。一天他们工作之余去公园散步,晒太阳,喝咖啡。Haarard说:“We need an object-oriented display system。”这成为了后来Qt最重要的思想:提供面向对象的跨平台的GUI框架。看到这里小女我不仅感慨:什么时候我们的程序员们可以在工作的时候出来走走,只有在轻松愉快的环境中才会生产出出色的成果。在沉闷的办公室里,只是机械的堆砌代码而已。

所做就做,Haarard开始写代码,Eirik负责设计,Qt在襁褓中逐渐成长,在开始蹒跚学步的时候(1993年),他们开始让Qt闯荡江湖,两个人开始了创业的艰辛历程。

对这两个年轻人,1994年是非常艰难的一年,他们没有客户,没有钱,只有还没有完全实现的产品。关键时刻,他们的妻子帮他们渡过了难关。

字母Q作为所有类的前缀,是因为Haarard手写这个字母看起来特别的漂亮,字母t代表“toolkit”,在Xt, X toolkit等中得到灵感。

1995年开始出现转机,他们得到了一个合同。这一年,他们雇佣了Arnt Gulbrandsen,他在Trolltech工作了六年,他为Qt实现了优秀的文档系统。

1995年5月,Qt 0.9发布,有商业和开源两个版本。96年9月,Qt1.0发布。

1997年,Matthias Ettrich开始用Qt开发KDE,使Qt成为Linux上GUI开发的 事实上的标准。

1999年,Qt 2 发布。

2000年,Qtopia发布。支持linux嵌入式开发。

2001年,Qt 3 发布。

2005年, Qt 4 发布。

十年来,Qt就是这样从不知名的一个产品,发展到现在拥有全世界范围内成千上万的客户。

3、Qt入门

3.1从Hello Qt开始 

差不多所有的程序教材都从Hello 开始,下面就是这个程序的qt版本。

首先向/etc/profile文件里添加如下内容

#set qt env

QT_HOME=/opt/qtsdk-2010.05/

PATH=$QT_HOME/qt/bin:$PATH

我的qt安装路径是/opt/qtsdk-2010.05/,请大家添加你自己的路径,这样下次重新启动电脑后,就可以使用qmake命令了。

使用VIM编辑器建立一个HelloQt.cpp文件,文件内容如下:

1 #include 

2 #include 

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 }

按行解析以上9行代码

第一,二行:是代码中需要使用的类的头文件。在Qt4中,可以写成的格式,当然也可写成“QApplication.h”。

第三行:是main函数的标准写法

第五行:创建一个QApplication对象,管理应用程序的资源。

第六行:QLabel对象,QLabel是一个Qt提供的小控件,显示一行文本。

第七行:显示QLabel。

第八行:QApplication.exec(),让程序进入消息循环。等待可能的菜单,工具条,鼠标等的输入,进行响应。

打开终端,进入HelloQt.cpp所在目录,执行:

qmake –project

qmake

make

执行完所有的命令后,再执行./HelloQt,出现如下界面

第6行代码还可以如下替换:

QLabel *label = new QLabel("

Hello "

                          "Qt!

");

                           

这里面包含了html文本,显示的字体,颜色会改变,运行结果如下:

实际程序中,下面两行是比不可少的。

QApplication app(argc, argv);

return app.exec();

3.2建立连接

这个例子用来说明怎么响应信号,和hello程序的源代码相似,原来的Label用一个按钮代替,点击时退出程序。

源程序如下:

 1 #include 

 2 #include 

 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的控件会发出消息(signal),例如,当点击按钮时,按钮会发送clicked()消息,这个消息可以连接到一个函数上(这个函数在这里成为slot)。这样,当一个消息发送时,slot函数可以自动执行。在这个例子中,我们连接了按钮的clicked信号和QApplication的quit函数,语法如第七,八行所示。

然后运行程序,点击Quit按钮,程序将会中止。

4创建对话框(Creating Dialogs)

在这章介绍如何创建Qt的对话框。对话框是程序和用户交互的桥梁,提供了程序和用户之间对话的一种方式。

很多程序都是由一个主窗口,在这个主窗口中包含一个菜单条,多个工具条,和足够多的对话框。也有些程序本身就是一个对话框,直接相应用户的输入请求。

本章中我们首先会用代码的方式创建我们的第一个对话框,然后用Qt Designer工具创建对话框。Qt Designer是一个可视化的工具,用它可以更快的创建,修改对话框。

4.1派生对话框类(Subclassing QDialog)

第一个例子是一个用C++实现的查找对话框。我们把这个对话框实现为一个类,这样它就是一个的控件,并有自己的信号(signal)和slot函数

类的源代码分别放在finddialog.h和finddialog.cpp中。首先看finddialog.h的代码

1 #ifndef FINDDIALOG_H

2 #define FINDDIALOG_H

3 #include 

4 class QCheckBox;

5 class QLabel;

6 class QLineEdit;

7 class QPushButton;

 8 class FindDialog : public QDialog

 9 {

10     Q_OBJECT

11 public:

12     FindDialog(QWidget *parent = 0);

13 signals:

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

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

16 private slots:

17     void findClicked();

18     void enableFindButton(const QString &text);

19 private:

20     QLabel *label;

21     QLineEdit *lineEdit;

22     QCheckBox *caseCheckBox;

23     QCheckBox *backwardCheckBox;

24     QPushButton *findButton;

25     QPushButton *closeButton;

26 };

27 #endif

一共27行,第1,2,27行是为了避免头文件被多次包含。

第3行包含QDialog头文件,这个类从QDialog继承,QDialog从QWidget继承。

第4至7行是用到的Qt中类的前向声明。通过前向声明,编译器就知道这个类已经存在,而不用写出包含的头文件。这个问题稍后还要讲。

第8至26行是类FindDialog的定义。

第10行,Q_OBJECT是一个宏定义,如果类里面用到了signal或者slots,就要声明这个宏。

第12行, FindDialog(QWidget *parent = 0);构造函数是Qt控件类的标准格式,默认的父参数为NULL,说明没有父控件。

第13行,signal声明了这个对话框发出的两个信号,如果选择向前查找,那么对话框就发出findPrevious()信号,否则,发出findNext()信号。signal也是一个宏,在编译之前,C++预处理把它变成标准的c++代码。Qt::CaseSensitivity是一个枚举类型,有Qt::CaseSensitive和Qt::CaseInsensitive两个值。

在类的私有部分,声明有两个slot函数。为了实现这两个函数,需要用到对话框的其他控件的信息,所以保存了一些控件的指针。slot关键字和signal一样,也是一个宏。

对于私有成员变量,我们只是使用了它们的指针,没有对它们进行存取操作,编译器不需要知道它们的详细定义,所以只使用了这些类的前向声明。当然,也可以使用等,但是,使用前向声明会让编译速度更快一些。

下面看一下finddialog.cpp源文件代码:

文件头和构造函数部分

1  #include 

2  #include "finddialog.h"

 3 FindDialog::FindDialog(QWidget *parent)

 4     : QDialog(parent)

 5 {

 6     label = new QLabel(tr("Find &what:"));

 7     lineEdit = new QLineEdit;

 8     label->setBuddy(lineEdit);

 9     caseCheckBox = new QCheckBox(tr("Match &case"));

10     backwardCheckBox = new QCheckBox(tr("Search &backward"));

11     findButton = new QPushButton(tr("&Find"));

12     findButton->setDefault(true);

13     findButton->setEnabled(false);

14     closeButton = new QPushButton(tr("Close"));

15     connect(lineEdit, SIGNAL(textChanged(const QString &)),

16             this, SLOT(enableFindButton(const QString &)));

17     connect(findButton, SIGNAL(clicked()),

18             this, SLOT(findClicked()));

19     connect(closeButton, SIGNAL(clicked()),

20             this, SLOT(close()));

21     QHBoxLayout *topLeftLayout = new QHBoxLayout;

22     topLeftLayout->addWidget(label);

23     topLeftLayout->addWidget(lineEdit);

24     QVBoxLayout *leftLayout = new QVBoxLayout;

25     leftLayout->addLayout(topLeftLayout);

26     leftLayout->addWidget(caseCheckBox);

27     leftLayout->addWidget(backwardCheckBox);

28     QVBoxLayout *rightLayout = new QVBoxLayout;

29     rightLayout->addWidget(findButton);

30     rightLayout->addWidget(closeButton);

31     rightLayout->addStretch();

32     QHBoxLayout *mainLayout = new QHBoxLayout;

33     mainLayout->addLayout(leftLayout);

34     mainLayout->addLayout(rightLayout);

35     setLayout(mainLayout);

36     setWindowTitle(tr("Find"));

37     setFixedHeight(sizeHint().height());

38 }

在第4行,把parent参数传递给了基类的构造函数。然后,创建了子窗口部件。在字符串周围的tr()函数调用的是把它们翻译成其他语言的标记。

在这些字符串中,使用了“&”来表示快捷键。例如,第11行创建了一个Find按钮,用户可在那些支持快捷键的平台下通过按下Alt+F快捷键来激活它。符号“&”可以用来控制焦点:在第六行创建一个带有快捷(Alt+W)的标签,而在第8行设置了行编辑器作为标签的伙伴,所谓“伙伴”(buddy),就是一个窗口部件,它可以在按下标签的快捷键时接受焦点(focus)。所以当用户按下Alt+W(该标签的快捷键)时,焦点就会移动到这个行编辑器上。

到这里FindDialog的构造函数就完成了。在传见控件和布局时我们使用了new,一般情况下,我们还需要写析构函数delete这些控件。

但是在Qt中这是不需要的,当父控件销毁时,Qt自动删除它所有的子控件和布局。 

下面是FindDialog类的两个slot函数:

39 void FindDialog::findClicked()

40 {

41     QString text = lineEdit->text();

42     Qt::CaseSensitivity cs =

43             caseCheckBox->isChecked() ? Qt::CaseSensitive

44                                       : Qt::CaseInsensitive;

45     if (backwardCheckBox->isChecked()) {

46         emit findPrevious(text, cs);

47     } else {

48         emit findNext(text, cs);

49     }

50 }

51 void FindDialog::enableFindButton(const QString &text)

52 {

53     findButton->setEnabled(!text.isEmpty());

54 }

当用户点击findButton按钮,findClicked()就会调用,根据backwardCheckBox状态,他发出findPrevious()或者findNext()信号。emit也是一个Qt的宏。

当用户改变lineEdit中的文本,enableFindButton()slot函数就会调用。如果输入了文本,那么让findButton有效,否则就无效。

最后,创建main.cpp测试FindDialog对话框。

1 #include 

2 #include "finddialog.h"

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

4 {

5     QApplication app(argc, argv);

6     FindDialog *dialog = new FindDialog;

7     dialog->show();

8     return app.exec();

9 }

程序运行结果如下:

运行程序,如果看到了快键,测试ALT+W,ALT+C,ALT+B,ALT+F引发相应的处理程序。使用TAB键在将焦点改变到不同的控件上。默认的TAB键是控件创建的顺序。QWidget::setTabOrder()可以改变这个顺序。

提供合适的tab顺序和快键可以让用户不用鼠标也可以运行程序,通过键盘可以快速控制程序。

 

4.2深入信号和槽(Signals and Slots in Depth)

信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方。信号和槽是 QT 自行定义的一种通信机制,它于标准的 C/C++ 语言,因此要正确的处理信号和槽,必须借助一个称为 moc(Meta Object Compiler)的 QT 工具,该工具是一个 C++ 预处理程序,它为高层次的事件处理自动生成所需要的附加代码。

在我们所熟知的很多 GUI 工具包中,窗口小部件 (widget) 都有一个回调函数用于响应它们能触发的每个动作,这个回调函数通常是一个指向某个函数的指针。但是,在 QT 中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了。 信号和槽能携带任意数量和任意类型的参数,他们是类型完全安全的,不会像回调函数那样产生 core dumps。

所有从 QObject 或其子类 ( 例如 Qwidget) 派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射 (emit) 出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。这就是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。

你可以将很多信号与单个的槽进行连接,也可以将单个的信号与很多的槽进行连接,甚至于将一个信号与另外一个信号相连接也是可能的,这时无论第一个信号什么时候发射系统都将立刻发射第二个信号。总之,信号与槽构造了一个强大的部件编程机制。

信号

当某个信号对其客户或所有者发生的内部状态发生改变,信号被一个对象发射。只有 定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。信号 - 槽机制完全于任何 GUI 事件循环。只有当所有的槽返回以后发射函数(emit)才返回。 如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地 执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪 个后执行。

信号的声明是在头文件中进行的,QT 的 signals 关键字指出进入了信号声明区,随后即可 声明自己的信号。例如,下面定义了三个信号:

signals: 

         void mySignal(); 

         void mySignal(int x); 

         void mySignalParam(int x,int y);

在上面的定义中,signals 是 QT 的关键字,而非 C/C++ 的。接下来的一行 void mySignal() 定义了信号 mySignal,这个信号没有携带参数;接下来的一行 void mySignal(int x) 定义 了重名信号 mySignal,但是它携带一个整形参数,这有点类似于 C++ 中的虚函数。从形式上 讲信号的声明与普通的 C++ 函数是一样的,但是信号却没有函数体定义,另外,信号的返回 类型都是 void,不要指望能从信号返回什么有用信息。

信号由 moc 自动产生,它们不应该在 .cpp 文件中实现。

槽是普通的 C++ 成员函数,可以被正常调用,它们唯一的特殊性就是很多信号可以与其相关联。当与其关联的信号被发射时,这个槽就会被调用。槽可以有参数,但槽的参数不能有缺省值。

既然槽是普通的成员函数,因此与其它的函数一样,它们也有存取权限。槽的存取权限决定了谁能够与其相关联。同普通的 C++ 成员函数一样,槽函数也分为三种类型,即 public slots、private slots 和 protected slots。

∙public slots:在这个区内声明的槽意味着任何对象都可将信号与之相连接。这对于组件编程非常有用,你可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。

∙protected slots:在这个区内声明的槽意味着当前类及其子类可以将信号与之相连接。这适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。

∙private slots:在这个区内声明的槽意味着只有类自己可以将信号与之相连接。这适用于联系非常紧密的类。

槽也能够声明为虚函数,这也是非常有用的。

槽的声明也是在头文件中进行的。例如,下面声明了三个槽:

public slots: 

         void mySlot(); 

         void mySlot(int x); 

         void mySignalParam(int x,int y);

信号与槽的关联

通过调用 QObject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。该函数的定义如下:

bool QObject::connect ( const QObject * sender, const char * signal, 

         const QObject * receiver, const char * member ) [static]

这个函数的作用就是将发射者 sender 对象中的信号 signal 与接收者 receiver 中的 member 槽函数联系起来。当指定信号 signal 时必须使用 QT 的宏 SIGNAL(),当指定槽函数时必须使用宏 SLOT()。如果发射者与接收者属于同一个对象的话,那么在 connect 调用中接收者参数可以省略。

例如,下面定义了两个对象:标签对象 label 和滚动条对象 scroll,并将 valueChanged() 信号与标签对象的 setNum() 相关联,另外信号还携带了一个整形参数,这样标签总是显示滚动条所处位置的值。

     QLabel     *label  = new QLabel; 

    QScrollBar *scroll = new QScrollBar; 

    QObject::connect( scroll, SIGNAL(valueChanged(int)), 

                      label,  SLOT(setNum(int)) );
一个信号甚至能够与另一个信号相关联,看下面的例子:

    class MyWidget : public QWidget 

    { 

    public: 

        MyWidget(); 

    ... 

    signals: 

        void aSignal(); 

    ... 

    private: 

    ... 

        QPushButton *aButton; 

    }; 

    MyWidget::MyWidget() 

    { 

        aButton = new QPushButton( this ); 

        connect(aButton,SIGNAL(clicked()), 

SIGNAL(aSignal()) ); 

    }
在上面的构造函数中,MyWidget 创建了一个私有的按钮 aButton,按钮的单击事件产生的信号 clicked() 与另外一个信号 aSignal() 进行了关联。这样一来,当信号 clicked() 被发射时,信号 aSignal() 也接着被发射。当然,你也可以直接将单击事件与某个私有的槽函数相关联,然后在槽中发射 aSignal() 信号,这样的话似乎有点多余。

当信号与槽没有必要继续保持关联时,我们可以使用 disconnect 函数来断开连接。其定义如下:

      bool QObject::disconnect ( const QObject * sender, const char * signal, 

         const Object * receiver, const char * member ) [static]

这个函数断开发射者中的信号与接收者中的槽函数之间的关联。

有三种情况必须使用 disconnect() 函数:

∙断开与某个对象相关联的任何对象。这似乎有点不可理解,事实上,当我们在某个对象中定义了一个或者多个信号,这些信号与另外若干个对象中的槽相关联,如果我们要切断这些关联的话,就可以利用这个方法,非常之简洁。

 disconnect( myObject, 0, 0, 0 ) 

或者

myObject->disconnect()
∙断开与某个特定信号的任何关联。

 disconnect( myObject, SIGNAL(mySignal()), 0, 0 ) 

或者

myObject->disconnect( SIGNAL(mySignal()) )
∙断开两个对象之间的关联。

 disconnect( myObject, 0, myReceiver, 0 ) 

或者

myObject->disconnect( myReceiver )
在 disconnect 函数中 0 可以用作一个通配符,分别表示任何信号、任何接收对象、接收对象中的任何槽函数。但是发射者 sender 不能为 0,其它三个参数的值可以等于 0。

元对象工具

元对象编译器 moc(meta object compiler)对 C++ 文件中的类声明进行分析并产生用于初始化元对象的 C++ 代码,元对象包含全部信号和槽的名字以及指向这些函数的指针。

moc 读 C++ 源文件,如果发现有 Q_OBJECT 宏声明的类,它就会生成另外一个 C++ 源文件,这个新生成的文件中包含有该类的元对象代码。例如,假设我们有一个头文件 mysignal.h,在这个文件中包含有信号或槽的声明,那么在编译之前 moc 工具就会根据该文件自动生成一个名为 mysignal.moc.h 的 C++ 源文件并将其提交给编译器;类似地,对应于 mysignal.cpp 文件 moc 工具将自动生成一个名为 mysignal.moc.cpp 文件提交给编译器。

元对象代码是 signal/slot 机制所必须的。用 moc 产生的 C++ 源文件必须与类实现一起进行编译和连接,或者用 #include 语句将其包含到类的源文件中。moc 并不扩展 #include 或者 #define 宏定义 , 它只是简单的跳过所遇到的任何预处理指令。

应注意的问题

信号与槽机制是比较灵活的,但有些局限性我们必须了解,这样在实际的使用过程中做到有的放矢,避免产生一些错误。下面就介绍一下这方面的情况。

1 .信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上还是有所损失,当然这种损失相对来说是比较小的,通过在一台 i586-133 的机器上测试是 10 微秒(运行 Linux),可见这种机制所提供的简洁性、灵活性还是值得的。但如果我们要追求高效率的话,比如在实时系统中就要尽可能的少用这种机制。

2 .信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能产生死循环。因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。例如 , 在前面给出的例子中如果在 mySlot() 槽函数中加上语句 emit mySignal() 即可形成死循环。

3 .如果一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的。

4. 宏定义不能用在 signal 和 slot 的参数中。

既然 moc 工具不扩展 #define,因此,在 signals 和 slots 中携带参数的宏就不能正确地工作,如果不带参数是可以的。例如,下面的例子中将带有参数的宏 SIGNEDNESS(a) 作为信号的参数是不合语法的:

#ifdef ultrix 

    #define SIGNEDNESS(a) unsigned a 

    #else 

    #define SIGNEDNESS(a) a 

    #endif 

    class Whatever : public QObject 

    { 

    [...] 

    signals: 

        void someSignal( SIGNEDNESS(a) ); 

    [...] 

    };
5. 构造函数不能用在 signals 或者 slots 声明区域内。

的确,将一个构造函数放在 signals 或者 slots 区内有点不可理解,无论如何,不能将它们放在 private slots、protected slots 或者 public slots 区内。下面的用法是不合语法要求的:

class SomeClass : public QObject 

    { 

        Q_OBJECT 

    public slots: 

        SomeClass( QObject *parent, const char *name ) 

            : QObject( parent, name ) {}  // 在槽声明区内声明构造函数不合语法

    [...] 

    };
6. 函数指针不能作为信号或槽的参数。

例如,下面的例子中将 void (*applyFunction)(QList*, void*) 作为参数是不合语法的:

class someClass : public QObject 

    { 

        Q_OBJECT 

    [...] 

    public slots: 

        void apply(void (*applyFunction)(QList*, void*), char*); // 不合语法

    };
你可以采用下面的方法绕过这个:

    typedef void (*ApplyFunctionType)(QList*, void*); 

    class someClass : public QObject 

    { 

        Q_OBJECT 

    [...] 

    public slots: 

        void apply( ApplyFunctionType, char *); 

    };
7. 信号与槽不能有缺省参数。

既然 signal->slot 绑定是发生在运行时刻,那么,从概念上讲使用缺省参数是困难的。下面的用法是不合理的:

class SomeClass : public QObject 

    { 

        Q_OBJECT 

    public slots: 

        void someSlot(int x=100); // 将 x 的缺省值定义成 100,在槽函数声明中使用是错误的

    };
8. 信号与槽也不能携带模板类参数。

如果将信号、槽声明为模板类参数的话,即使 moc 工具不报告错误,也不可能得到预期的结果。 例如,下面的例子中当信号发射时,槽函数不会被正确调用:

                         [...] 

   public slots: 

void MyWidget::setLocation (pair location);

   [...] 

   public signals: 

void MyObject::moved (pair location);
但是,你可以使用 typedef 语句来绕过这个。如下所示:

 typedef pair IntPair; 

   [...] 

   public slots: 

       void MyWidget::setLocation (IntPair location); 

   [...] 

   public signals: 

       void MyObject::moved (IntPair location);
这样使用的话,你就可以得到正确的结果。

9. 嵌套的类不能位于信号或槽区域内,也不能有信号或者槽。

例如,下面的例子中,在 class B 中声明槽 b() 是不合语法的,在信号区内声明槽 b() 也是不合语法的。

class A 

    { 

        Q_OBJECT 

    public: 

        class B 

        { 

        public slots:   // 在嵌套类中声明槽不合语法

            void b(); 

        [....] 

        }; 

    signals: 

        class B 

        { 

        // 在信号区内声明嵌套类不合语法

            void b(); 

        [....] 

        }: 

    };
10. 友元声明不能位于信号或者槽声明区内。

相反,它们应该在普通 C++ 的 private、protected 或者 public 区内进行声明。下面的例子是不合语法规范的:

class someClass : public QObject 

    { 

        Q_OBJECT 

    [...] 

    signals: // 信号定义区

        friend class ClassTemplate; // 此处定义不合语法

    };
5、使用Qt Creator创建应用程序

Qt Creator 是 Qt 被 Nokia 收购后推出的一款新的轻量级集成开发环境(IDE)。此 IDE 能够跨平台运行,支持的系统包括 Linux(32位及 位)、Mac OS X 以及 Windows。根据官方描述,Qt Creator 的设计目标是使开发人员能够利用 Qt 这个应用程序框架更加快速及轻易的完成开发任务。

在功能方面,Qt Creator 包括项目生成向导、高级的 C++ 代码编辑器、浏览文件及类的工具、集成了 Qt Designer、图形化的 GDB 调试前端,集成 qmake 构建工具等。

Qt Creator的主界面如下(所有平台的Qt Creator基本是一模一样的使用):

5.1使用Qt Creator创建空的Qt应用程序

单击菜单栏上的File->New File or Project,出现下面的对话框:

我们选择Other Project下面的Empty Qt Project,单击Choose

在Name中我们输入test1(注意Name可以随便起,但是不应包含空格),然后选择项目的创建位置,单击Next

单击Finish,出现如下界面:

我们一般单击Finish就可以了,至此我们的工程就创建好了:

接下来我们向工程中添加文件,右击test1,单击Add New,出现如下界面:

我们选择C++  Source File,单击Choose:

接下来给你的文件取个名字,这里我们填入test1,单击Next:

一般默认就行,单击Finish,添加文件完毕:

可以看到test1.cpp添加到了工程中了,我们在test1.cpp中写入如下内容:

#include

#include

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

{

    QApplication app(argc, argv);

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

    label->show();

    return app.exec();

}

单击菜单栏上的Build->Build All,然后单击Build->Run就可以运行程序了:

5.2使用Qt Creator创建Qt图形界面应用程序

单击菜单栏上的File->New File or Project,出现下面的对话框:

选择Qt C++ Project下面的Qt Gui Application,单击Choose,出现如下界面:

单击Next:

接下来基本按照提示就可以了,建立后的工程如下:

我们可以看到比一般手动写的工程多出一个mainwindow.ui文件 ,这是什么东西呢?我们双击这个文件,发现跳转到了Qt Designer

Qt Designer的具体用法可以参考自带的帮助文档Assitant–>Content–>Qt Designer Manual。

我们直接编译运行工程,结果如下:

文档

Qt简明教程

Qt简明教程1、Qt的安装首先去Qt的官方网站(http://qt.nokia.com/downloads)下载你所需要的安装包,官方提供了Windows、Linux、MacOS等平台的安装包,这里我们选择Linux平台下的安装包。截至到目前为止,Qt的最新版本为4.7,所以我们下载所对应的安装包为qt-sdk-linux-x86-opensource-2010.05.1.bin。下载完毕后我们打开超级终端,切换到root用户(sudosu),然后提升安装包的权限,使其具有执行权限,接着执行.
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top