• 9109阅读
  • 1回复

【摘录】《KDE2/Qt编程金典》第二章:创建并显示一个窗口——2.6 为一个信号定义slot [复制链接]

上一主题 下一主题
离线XChinux
 

只看楼主 倒序阅读 楼主  发表于: 2005-08-28
  为了让一个部件接收某个信号,它必须定义一个slot,并将此slot和某个信号相连接。下面的例子,显示了一个按钮和一个计数器,无论何时按下此按钮,计数器就加1,为了完成同样的工作需要做几件事情,不过Qt系统将会处理大部分的细节工作。特别需要指出的是,有一些特殊的宏和Meta对象编辑器(MOC, Meta Object Compiler)将自动处理大部分的细节工作。在这个例子中的main()函数很简单地创建并显示了此部件:

1     /* count.cpp */
2     #include <qapplication.h>
3     #include "clickcount.h"
4    
5     int main(int argc, char **argv)
6     {
7         QApplication app(argc, argv);
8         ClickCount clickcount;
9         app.setMainWidget(&clickcount);
10         clickcount.show();
11         return(app.exec());
12     }

  ClickCount部件包含了一个按钮和一个标签。标签用来显示当前计数器的值:

1     /* clickcount.h */
2     #ifndef CLICKCOUNT_H
3     #define CLICKCOUNT_H
4    
5     #include <qpushbutton.h>
6     #include <qlabel.h>
7
8     class ClickCount: public QWidget
9     {
10         Q_OBJECT
11     public:
12         ClickCount(QWidget *parent=0, const char *name=0);
13     public slots:
14         void incrementCounter();
15     private:
16         int counter;
17         QLabel *label;
18         QPushButton *button;
19     };
20
21     #endif

  在任何有slot的类中必须有第10行显示的宏Q_OBJECT(它也必须残存在于需要广播信号的类中,在第5章将学习到有关知识)。宏Q_OBJECT定义了一些标准方法,为了让信号和slot正常工作,它们必须存在于类中。
  第14行中的incrementCounter()方法,在第13行中被设置为 public slot。除了定义为slot之外,incrementCounter()和类中的其它方法完全一样,它不仅可以被一个信号调用,而且也可以被直接调用。
  ClickCount类的构造函数创建的布局包含了按钮和标签,指定了连接,实现从按钮发送信号到名为incrementCount的slot:

1     /* clickcount.cpp */
2     #include <stdio.h>
3     #include "clickcount.h"
4    
5     ClickCount::ClickCount(QWidget *parent, const char *name):
6               QWidget(parent, name)
7     {
8         setMinimumSize(120, 125);
9         setMaximumSize(120, 125);
10
11         counter = 0;
12         button = new QPushButton("Add 1", this);
13         button->setGeometry(15, 15, 90, 40);
14         label = new QLabel("0", this);
15         label->setGeometry(15, 70, 90, 40);
16         label->setAlignment(AlignVCenter | AlignHCenter);
17
18         QObject::connect(
19               button, SIGNAL(clicked()),
20               this, SLOT(incrementCounter()));
21     }
22     void ClickCount::incrementCounter()
23     {
24         char str[30];
25         sprintf(str, "%d", ++counter);
26         label->setText(str);
27     }

  在第8行和第9行调用了setMinimumSize()函数和setMaximumSize()函数,将窗口尺寸设置为120x125像素。在第11行进行计数器的初始化,第12到16行创建和配置了按钮和标签。
  在第18行的调用QObject::connect()将一个slot连接到一个信号上。在第19行中,前两个参数指定了信号的来源是一个名叫clicked()的方法。clicked()信号是按钮类的一个成员,相应的还有其它信号,分别叫做pressed()、released()和toggled()。
  在第20行中,QObject::connect()后两个参数指定了接收信号的对象和方法。对象使用的是this(指当前ClickCount的实例),方法是incrementCounter()。
  每次clicked()信号被按钮发送出去的时候,它就被incrementCounter()方法所接收,此方法在所显示的值上加1,并且更新按钮的文本。
  注意:在信号和slot中间并没有真实的连接。无论有无监控的slot,信号都将被广播,而且对于同一个信号,监控的slot的数目是任意的。此外,一个slot可以被设置成监控任意数目的信号。
  这个例子的makefile文件说明了在Meta对象编译器(Meta Object Compiler)中如何将自己的输入作为定义类的头文件的代码,以便产生一个新的源文件用来编译以及和程序进行链接:

1     INCL= -I$(QTDIR)/include -I$(KDEDIR)/include
2     CFLAGS= -O2 -fno-strength-reduce
3     LFLAGS= -L$(QTDIR)/lib -L$(KDEDIR)/include -L/usr/X11R6/lib
4     LIBS= -lqt -lX11 -lXext
5     CC=g++
6
7     count: count.o clickcount.o moc_clickcount.o
8         $(CC) $(LFLAGS) -o count count.o clickcount.o moc_clickcount.o $(LIBS)
9
10     count.o: count.cpp clickcount.h
11
12     clickcount.o: clickcount.cpp clickcount.h
13     moc_clickcount.cpp: clickcount.h
14         $(QTDIR)/bin/moc clickcount.h -o moc_clickcount.cpp
15
16     clean:
17         rm -f count
18         rm -f count.o
19         rm -f clickcount.o
20         rm -f moc_*
21
22     .SUFFIXES: .cpp
23
24     .cpp.o:
25         $(CC) -c $(CFLAGS) $(INCL) -o $@ $<

  在第7行中显示程序不仅依赖于count.o和clickcount.o ,而且依赖于moc_clickcount.o。这个moc_clickcount.cpp是由MOC编译器从clickcount.h创建而来的。Q_OBJECT宏向ClickCount类定义中增加了一些方法原型,而MOC编译器产生这些新方法的实体。这样做的结果是,信号和slot所需要的重复性的编码工作(这样的工作很容易产生错误)几乎全部自动完成了。
二笔 openSUSE Vim N9 BB10 XChinux@163.com 网易博客 腾讯微博
承接C++/Qt、Qt UI界面、PHP及预算报销系统开发业务
离线mathbox

只看该作者 1楼 发表于: 2006-10-14
哦,明白了,呵呵,顶下天呐,感谢斑竹
快速回复
限100 字节
 
上一个 下一个