• 12419阅读
  • 0回复

【摘录】《KDE2/Qt编程金典》第四章:显示弹出式对话框——4.2 使用信号和slot [复制链接]

上一主题 下一主题
离线XChinux
 

只看楼主 倒序阅读 楼主  发表于: 2005-09-14
  下面的例子使用QDialog作为基类,构建一个对话框,用于接收一个字符串;当选择OK(确定)或者Apply(应用)按钮的时候,字符串被传送给程序的主窗口,使用它作为标题栏的新标题。
Mainline
1 /* responder.cpp */
2 #include <kapp.h>
3 #include “mainwidget.h”
4
5 int main(int argc,char **argv)
6 {
7 KApplication app(argc,argv,”responder”);
8 MainWidget mainwidget;
9 mainwidget.show();
10 app.setMainWidget(&mainwidget);
11 return(app.exec());
12 }


主程序相当简单。在第8行和第9行创建了MainWidget对象,在第10行将它设置为主窗口。
MainWidget Header
1 /* mainwidget.h */
2 #ifndef MAINWIDGET_H
3 #define MAINWIDGET_H
4
5 #include <qwidget.h>
6 #include <qstring.h>
7
8 class MainWidget: public QWidget
9 {
10 Q_OBJECT
11 public:
12 MainWidget(QWidget *parent=0,const char *name=0);
13 private slots:
14 void popupEnterName();
15 void changeCaption(QString &);
16 };
17
18 #endif

  这段程序是作为这个例子主窗口的部件的头文件。除了第12行的构造函数之外,这个类只包含了一对slot。命名为popupEnterName()的slot用于弹出对话框,命名为changeCaption()的slot改变部件的标题文本(也就是主窗口的标题)。
  因为在这个类中有slot,因此必须使用宏Q_OBJECT作为类的第一个成员。Q_OBJECT中的定义允许头文件作为标准C++代码正常地进行编译,它插入一些Meta对象编译器(MOC)使用的专门信息,产生处理信号和slot所必需的代码。
MainWidget
1 /* mainwidget.cpp */
2 #include “mainwidget.h”
3 #include “entername.h”
4 #include <qpushbutton.h>
5
6 MainWidget::MainWidget(QWidget *parent,const char *name)
7 : QWidget(parent,name)
8 {
9 setMinimumSize(200,80);
10 setMaximumSize(200,80);
11
12 QPushButton *button =
13 new QPushButton(“Update Name”,this);
14 button->setGeometry(50,20,100,40);
15 connect(button,SIGNAL(clicked()),
16 this,SLOT(popupEnterName()));
17 }
18 void MainWidget::popupEnterName()
19 {
20 EnterName *dialog = new EnterName(0,”entername”);
21 connect(dialog,SIGNAL(captionString(QString &)),
22 this,SLOT(changeCaption(QString &)));
23 dialog->exec();
24 delete dialog;
25 }
26 void MainWidget::changeCaption(QString &caption)
27 {
28 setCaption(caption);
29 }

  这个类作为应用程序的主窗口。
  因为这个类是由QWidget继承而来的,参见第7行,因此这个类也是一个部件。第9行和第10行将最大尺寸和最小尺寸设置为相同的值,这样此部件的大小保持固定不变。
  在第12行和第13行创建了QPushButton,在第14行中将它定位在窗口的中心。按钮拥有一个叫做clicked()的信号,只要鼠标按下此按钮,就将发出此信号。在第15行的connect()调用指定了无论何时发出的clicked()信号,都将调用局部的slot方法popupEnterName()。
注意:将方法用作slot并不限制直接调用此方法。在这个例子中,方法popupEnterName()被信号调用,但它也可以轻易地被此类内部其它的方法所调用,甚至被其它外部类的方法所调用。slot是一个正常的方法,只不过加入了用来捕捉信号的特性。
  在第18行,popupEnterName()方法创建了EnterName对话框,用来弹出给用户以输入新的标题。第21行调用了connect()方法建立连接,使得对话框中的captionString()信号将触发调用changeCaption()局部slot。
  在第23行,调用exec()弹出对话框,并且只有对话框具有处理输入队列的权利。这个方法只有用户选择了OK或者Cancel按钮时才返回。也就是说,只有用户响应了对话框,这个应用程序的其它窗口才能接收鼠标或者键盘的信号。在第23行,用户做出选择后,将删除此对话框。
  只有当用户选择了对话框中的OK按钮,才会调用第26行的slot方法,这样,新的标题字符串就赋给主窗口了。
EnterName Header
1 /* entername.h */
2 #ifndef ENTERNAME_H
3 #define ENTERNAME_H
4
5 #include <qdialog.h>
6 #include <qlineedit.h>
7 #include <qpushbutton.h>
8
9 class EnterName: public QDialog
10 {
11 Q_OBJECT
12 private:
13 QLineEdit *lineedit;
14 QPushButton *okButton;
15 QPushButton *applyButton;
16 QPushButton *cancelButton;
17 public:
18 EnterName(QWidget *parent=0,const char *name=0);
19 private slots:
20 void okButtonSlot();
21 void applyButtonSlot();
22 void cancelButtonSlot();
23 signals:
24 void captionString(QString &);
25 };
26
27 #endif

  这个头文件定义了弹出对话框的类,用来输入新的标题字符串。它还有slot接收按钮的点击事件,以及发送带有标题字符串的信号。
  这个类定义为一个对话框,因为在第9行,它使用了QDialog作为它的基类。任何包含了slot或者信号的类中都必须使用Q_OBJECT作为它的第一个成员。第13行到第16行为4个部件声明了存储空间,用于构建对话框的成员。
  第19行到第22行指定了slot的名字。okButtonSlot()、applyButtonSlot()和cancelButtoNSlot()方法是局部slot,用来接收按钮的点击事件。无论用户什么时候提交新的标题字符串,第24行的captionString()信号都将发送出去。
EnterName
1 /* entername.cpp */
2 #include “entername.h”
3 #include <qdialog.h>
4 #include <qlayout.h>
5
6 EnterName::EnterName(QWidget *parent,const char *name)
7 : QDialog(parent,name,TRUE)
8 {
9 QString caption(“Enter Name”);
10 setCaption(caption);
11
12 QVBoxLayout *vLayout = new QVBoxLayout(this,10);
13
14 lineedit = new QLineEdit(this);
15 vLayout->addWidget(lineedit);
16
17 QHBoxLayout *hLayout = new QHBoxLayout(vLayout,10);
18
19 okButton = new QPushButton(“OK”,this);
20 connect(okButton,SIGNAL(clicked()),
21 this,SLOT(okButtonSlot()));
22 hLayout->addWidget(okButton);
23
24 applyButton = new QPushButton(“Apply”,this);
25 connect(applyButton,SIGNAL(clicked()),
26 this,SLOT(applyButtonSlot()));
27 hLayout->addWidget(applyButton);
28
29 cancelButton = new QPushButton(“Cancel”,this);
30 connect(cancelButton,SIGNAL(clicked()),
31 this,SLOT(cancelButtonSlot()));
32 hLayout->addWidget(cancelButton);
33 }
34 void EnterName::okButtonSlot()
35 {
36 QString str = lineedit->text();
37 emit captionString(str);
38 accept();
39 }
40 void EnterName::applyButtonSlot()
41 {
42 QString str = lineedit->text();
43 emit captionString(str);
44 }
45 void EnterName::cancelButtonSlot()
46 {
47 reject();
48 }

  这个类是一个对话框,用于让用户输入文本,然后通过选择适当的按钮,让输入的文本安装为主窗口的标题:
  第6行输入给EnterName构造函数的参数在第7行传递给上一级的类QDialog。输入给QDialog的第3个参数是TRUE,说明这是一个模式对话框。
  在第12行创建了垂直框,用作窗口的主容器。在第14行创建的QLineEdit对象被插入到垂直框的上部。一个水平框被创建为垂直框的子项,这样水平框将成为垂直框的下一个成员。向水平框中插入3个按钮。
  第20行、第25行和第30行调用了connect()方法,将3个按钮的clicked()信号与它们各自相对应的slot关联起来。
  无论何时点击OK按钮,第34行的slot方法okButtonSlot()就会被调用。调用QLineEdit对象的text()方法返回用户输入的字符串。第37行发出的信号名叫captionString()。发出这个信号所使用的语法几乎和调用一个方法一样,只不过在前面的关键词"emit"指明它不是一个调用——而是一个被发送的信号。这个slot方法被第38行调用的accept()所包含。此调用设置了一个内部标志为TRUE,指明用户给出了一个肯定的响应,然后调用hide(),使这个部件隐藏起来。
  无论何时点击Apply按钮,就会调用第40行的applyButtonSlot()方法。就像OK按钮的slot所做的工作一样,返回并且用信号的方法captionString()放送字符串。由于对话框保持显示状态由此不调用accept()方法。
  无论何时点击Cancel按钮,都会调用第45行的cancelButtonSlot()方法。用户取消改变标题名称的动作,由此没有信号发出。将会调用reject()把内部标志设置为FALSE,关闭对话框窗口。
Makefile
1 INCL= -I$(QTDIR)/include -I$(KDEDIR)/include
2 CFLAGS= -O2 -fno-strength-reduce
3 LFLAGS= -L$(QTDIR)/lib -L$(KDEDIR)/lib -L/usr/X11R6/lib
4 LIBS= -lkdecore -lkdeui -lqt -lX11 -lXext -ldl
5 CC=g++
6
7 recaption: recaption.o mainwidget.o moc_mainwidget.o \
8 entername.o moc_entername.o
9 $(CC) $(LFLAGS) -o recaption recaption.o \
10 mainwidget.o moc_mainwidget.o \
11 entername.o moc_entername.o $(LIBS)
12
13 recaption.o: recaption.cpp mainwidget.h
14 mainwidget.o: mainwidget.cpp mainwidget.h
15 moc_mainwidget.cpp: mainwidget.h
16 $(QTDIR)/bin/moc mainwidget.h -o moc_mainwidget.cpp
17 entername.o: entername.cpp entername.h
18 moc_entername.cpp: entername.h
19 $(QTDIR)/bin/moc entername.h -o moc_entername.cpp
20
21 clean:
22 rm -f recaption
23 rm -f *.o
24 rm -f moc_*
25
26 .SUFFIXES: .cpp
27
28 .cpp.o:
29 $(CC) -c $(CFLAGS) $(INCL) -o $@ $<

  上面的代码说明,当在源程序代码中包含slot或者信号时,需要在makefile文件中包含专门的入口。此代码并不直接编译,它也是被MOC编译器翻译成单独的需要编译的代码。
  第7行有连接recaption所需要的文件列表。不仅有与.cpp文件名字想对应的.o文件,而且有以4个字符moc_开头的其它的.o文件。任何把Q_OBJECT作为第一成员的类,必须有MOC编译器处理得到的头文件。第15行所需要的文件表明源文件moc_mainwidget.cpp是由源文件mainwidget.h得到的。第16行使用了mainwidget.h作为插入来创建moc_mainwidget.cpp。然后 moc_mainwidget.cpp被编译成moc_mainwidget.o,并且被包含在第9行的连接中。
二笔 openSUSE Vim N9 BB10 XChinux@163.com 网易博客 腾讯微博
承接C++/Qt、Qt UI界面、PHP及预算报销系统开发业务
快速回复
限100 字节
 
上一个 下一个