第五章 同步的拨盘

信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本章介绍了信号与槽的一些基本概念以及在实际使用过程如何使用。通过两个同步的拨盘的例子介绍信号和槽的使用。下面分别说一下两个基本概念。

信号

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

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

signals:

         void mySignal();

         void mySignal(int x);

         void mySignalParam(QString str,int y);

 

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

注意:信号一定没有实现

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

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

  • public slots:在这个区内声明的槽意味着任何对象都可将信号与之相连接。这对于组件编程非常有用,你可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。
  • protected slots:在这个区内声明的槽意味着当前类及其子类可以将信号与之相连接。这适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。
  • private slots:在这个区内声明的槽意味着只有类自己可以将信号与之相连接。这适用于联系非常紧密的类。

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

信号与槽的关联

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

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

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

 

示例程序

我们首先创建一个Gui程序,继承自QDialog,然后设计界面,拖动两个Dial和一个Horizontal Scroll Bar。我们创建这个程序要实现的就是三个控制能够同步动作。

我们在Dialog类的构造函数中添加信号和槽的连接,操作很简单,如下所示

connect(ui->dial,SIGNAL(valueChanged(int)),ui->dial_2,SLOT(setValue(int)));

connect(ui->dial,SIGNAL(valueChanged(int)),ui->horizontalSlider,SLOT(setValue(int)));

connect(ui->dial_2,SIGNAL(valueChanged(int)),ui->dial,SLOT(setValue(int)));

connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),ui->dial,SLOT(setValue(int)));

这样运行程序,操作任何一个控件,另两个就会跟着动作了。

下面我们自己定义一个信号和槽。

signals:

void mySignal(int);

private:

Ui::Dialog *ui;

private slots:

void my_slot(int);
下面
我们把我们刚才的几个连接注释掉,然后使用自己的信号和槽建立中间的连接。通过水平条控制dial的动作。

 

Dialog::Dialog(QWidget *parent) :

QDialog(parent),

ui(new Ui::Dialog)

{

ui->setupUi(this);

// connect(ui->dial,SIGNAL(valueChanged(int)),ui->dial_2,SLOT(setValue(int)));

// connect(ui->dial,SIGNAL(valueChanged(int)),ui->horizontalSlider,SLOT(setValue(int)));

// connect(ui->dial_2,SIGNAL(valueChanged(int)),ui->dial,SLOT(setValue(int)));

// connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),ui->dial,SLOT(setValue(int)));

connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(my_slot(int)));

connect(this,SIGNAL(mySignal(int)),ui->dial,SLOT(setValue(int)));

}

Dialog::~Dialog()

{

delete ui;

}

void Dialog::my_slot(int a){

emit mySignal(a);

}

上面的实现是通过水平条的变化连接到Dialog的my_slot(int a),然后在槽函数中发射一个信号,然后再将这个信号和dial的setval()槽函数相连,这样同样能实现我们上面的联动。

其实,不光信号和槽能够连接,信号和信号也能够连接。

下面我们再稍加改动,让信号和信号相连。看一下效果。注释掉上面的代码,然后重新建立如下的连接。能够实现相同的功能。

connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SIGNAL(mySignal(int)));

connect(this,SIGNAL(mySignal(int)),ui->dial,SLOT(setValue(int)));

这一节实现起来很简单,这个例子只是给大家演示如何使用信号和槽,主要是理解信号和槽的概念。下一节讲解如何使用SignalMapper,敬请关注。

转载于:https://www.cnblogs.com/hyarm/p/3199350.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值