Qt信号槽机制的简单例子

回到QT,先在VS中新建一个QT Application,项目里面有几个目录:

1、Form Files目录,它里面放的是使用QT designer制作的基于XML的布局文件,双击它就会自动进入QT designer。

2、Generated Files目录,它里面放的是一些临时生成的文件,这些文件用来处理QT的信号和槽等机制。

3、Resource Files目录,它里面放的是基于XML的资源文件,你可以在窗体里面使用它们。

4、Header Files和Source Files这两个和VS默认是一样的。

 

理解了目录结构之后,先来试着写一个Hello World,先把除了main.cpp之外的所有文件移除(使用QT designer会提高制作效率,但是会让QT入门门槛变高)!打开main.cpp,仅保留以下代码:


#include <QtGui/QApplication>   
int main(int argc, char *argv[])  
 
{   
         QApplication a(argc, argv);         
         return a.exec();   
}  

编译通过。运行没有任何反应,因为还没有往里面增加任何东西。

在代码中,Main函数是C语言的入口,之后申请的QApplication用来管理控制流和主要设置,这是核心,一定要保留。

按钮是GUI中最基本的一个控件,先看看怎么增加一个按钮。使用按钮控件必须先包含头文件:

 

#include <QtGui/QPushButton>

然后在QApplication a(argc, argv);与return a.exec();中间插入下面代码:


QPushButton button("HELLO");   
  
button.setGeometry(100,100,300,300);   
  
button.show();  

代码第一行是申请一个按钮,并把按钮的Caption标题设为HELLO,第二行表示这个按钮出现在屏幕坐标(100,100)的位置,宽高为(300,300),最后一行是显示这个按钮,你可以尝试把它去掉看看效果(官方助手里有QPushButton的更多资料,请自行查看)。

编译出来,发现屏幕上出现一个框,框里面有一个按钮,按钮可以点击,但是没有任何反应,因为还没有为这个按钮增加任何的槽(Slot)。

 

在MFC对控件的处理一般是通过事件机制,而在QT中是使用信号(Signal)和槽(Slot)机制,其实你也可以把它理解为事件机制。

简单理解信号其实就是输入,而槽就是输出,拿按钮打比方,在一次点击中,这个点击,就是一个信号,而点击后的反馈,就是槽。

每一个控件都拥有一些默认的Signal和Slot,这些都可以在官方提供的助手中查看。

绑定Signal和slot是使用静态函数connect。函数原型是:


Bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection ) 


其中sender是发送者,而receiver是接收者,signal是信号,而method就是slot,type里面提供了几种绑定方式,可以详细查看助手。

         先看一个例子,在上面代码中加入点击按钮后关闭应用程序的效果。很简单,只需要在
button. setGeometry(100,100,300,300);

后面加入


QObject::connect(&button, SIGNAL(clicked()), &a, SLOT(quit()));

编译运行,点击后窗体关闭。

这是使用默认槽的例子,有时候需要点击按钮之后执行自定义的效果,那么就需要使用自定义槽了。

 

下面是一个使用自定义Slot的例子,鼠标点击按钮之后,文本框文字会改变。

先加入一个QLabel控件,你先加入头文件:

 
#include <QtGui/QLabel>

然后在connect前加入


QLabel label("World");

label.setGeometry(50,50,300,300);
 

先尝试编译一下,结果label没有出现在窗体里面!它当然不会出现在窗体里面,因为我们只是对Button使用了Show()函数,尝试加入label.show(),结果出现了两个窗体,一个里面有按钮,另一个里面有一个label。那么怎么把它们放在一起呢

通过上面的测试发现,调用一次show就会产生一个窗口,那么是不是只调用一次show就行了?把函数里面代码改为:


QApplication a(argc, argv);   
 
QWidget window;   
 
QPushButton button("HELLO");   
 
button.setGeometry(100,100,300,300);   
 
QLabel label("World");   
  
label.setGeometry(50,50,300,300);   
 
QHBoxLayout layout;   
 
Layout.addWidget(&button);   
 
Layout.addWidget(&label);   
  
QObject::connect(&button, SIGNAL(clicked()), &window, SLOT(close()));   
 
window.setLayout(&layout);   
  
window.show();          
  
 return a.exec(); 

附上此时的头文件列表:


#include <QtGui/QPushButton>

#include <QtGui/QApplication>

#include <QtGui/QLabel>

#include <QtGui/QHBoxLayout>

#include <QtGui/QWidget>
 

一开始,我就申请了一个QWidget,QWidget类是QT中所有用户界面对象的基类,它本身并没有什么实际意义,在这里你可以把它看成一个窗体容器,然后又添加了一个

QHBoxLayout layout; QHBoxLayout这是个可以对子widget进行特定布局的控件,通过它可以把按钮和label并排,之后把窗体的layout设为指定的layout,然后调用show()。

调试运行,终于两个控件都出现了。

回到之前的话题,自定义槽。在QT中所有自定义槽都需要先编译成moc,才可以被使用。不过你放心,这个过程由QT自动完成,当然你也可以手动进行编译,QT的Bin目录里面有moc.exe,参照说明进行使用。

你应该可以看到我已经偷偷把按钮的点击信号转向了窗体的close槽。为什么要这样做呢,因为我们需要把自定义槽函数定义放在头文件里。

第一步,先把window封装起来,我新建一个MainWidget类,继承自QWidget类,类的头文件如下:

view plaincopy to clipboardprint?
#ifndef _MAIN_WIDGET_H_ 
 
#define _MAIN_WIDGET_H_ 
 
#include <QtGui/QLabel> 
 
#include <QtGui/QHBoxLayout> 
 
#include <QtGui/QWidget> 
 
#include <QtGui/QPushButton>  
 
class MainWidget: public QWidget  
 
{  
 
public:  
 
         MainWidget();  
 
         ~MainWidget();  
 
   
 
protected:                   
 
   
 
private:      
 
         QLabel*                               m_pLabel;  
 
         QPushButton*          m_pButton;  
 
         QHBoxLayout*                   m_pLayout;  
 
}; 
 
#endif  
 
CPP如下: 
 
#include "MainWidget.h"  
 
MainWidget::MainWidget()  
 
{  
 
         m_pLabel = new QLabel("World");  
 
         m_pLabel ->setGeometry(50,50,300,300);  
 
         m_pButton = new QPushButton ("HELLO");  
 
         m_pButton ->setGeometry(100,100,300,300);  
 
         m_pLayout = new QHBoxLayout();  
 
         m_pLayout -> addWidget(m_pButton);  
 
         m_pLayout -> addWidget(m_pLabel);  
 
         connect(m_pButton, SIGNAL(clicked()), this, SLOT(close()));  
 
         setLayout(m_pLayout);  
 
}  
 
MainWidget::~MainWidget()  
 
{  
 

Main.cpp改为:

#include <QtGui/QApplication> 
 
#include "MainWidget.h"  
 
int main(int argc, char *argv[])  
 
{  
 
         QApplication a(argc, argv);  
 
         MainWidget window;        
 
         window.show();         
 
         return a.exec();  
 

编译运行,结果和上次一样。

接下来申请一个自定义Slot,首先在头文件public:前加入宏

Q_OBJECT;

只有加入了Q_OBJECT,你才能使用QT中的signal和slot机制。这点很重要,不然你编译的时候会报“找不到slot”的错误。

然后在protected:  前加入:
private slots:

void                SetText ();
 

slot同样也分private、public、protected,意义和c++一样。

CPP中加入相应执行:


void MainWidget:: SetText ()

{

         m_pLabel -> setText("Test");

}
 

把connect改成: 
connect(m_pButton, SIGNAL(clicked()), this, SLOT(SetText ()));

编译运行,这时点击按钮就会改变文字了。就这么简单。

 

信号也可以自定义,不过信号自定义相对来说用武之地稍微小一点,定义的方式和slot定义差不多,都得在头文件中定义,举个例子:点击按钮后文本改变,触发一个新信号,这个信号会把文字又变回来。

在头文件中加入:
signals:

     void TextChanged ();
 

再增加一个Slot用来对这个信号进行反馈。在private slots:后加入


void                              RecoverText ();

CPP中加入执行:


void MainWidget::RecoverText()

{

         m_pLabel -> setText("Hello");

}
 

注意信号是不需要加执行代码。

然后修改SetText()函数加入触发新信号的代码:

emit TextChanged();

最后加入新的connect:

 
connect(this, SIGNAL(TextChanged()), this, SLOT(RecoverText()));

编译运行,结果和我们想要的一样。


注:信号和槽都是可以有参数的。

有关QT的基础知识就介绍到这里,具体控件的使用方法,请自行参考助手。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pizi0475/archive/2010/05/19/5609474.aspx

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值