Qt学习心得——信号与槽的认识1

来源:互联网 发布:c语言蒲福风力等级 编辑:程序博客网 时间:2024/06/14 12:50

Qt学习心得——信号与槽的认识1

信号与槽的主要实现的功能是对界面中按钮进行定义,比如主界面中有个按钮pushbutton,并设置其显现名称为“计算”,那需要定义一个当这个按钮被点击时的功能,这个功能称之为槽,全称是槽函数,可见槽就是一种函数;点击的操作称之为信号。信号与槽可理解为,当信号为触发时,将自动执行与该信号相关联的槽函数。这其实很好理解,也很常见。有过VB程序设计基础(或者matlab中的GUI设计)的同学应该知道,每个按钮都有一个callback,应该和这里的信号与槽是类似的。《Qt Creator快速入门》第2版一书中提到这二者之间的差别。
信号与槽的实现有两种方式:

1.自动关联

Qt中有很多函数是很特殊的,主要体现在可以通过函数名来判断其功能,比如信号与槽的自动关联函数。在某个按钮上右击,选择“转到槽”,选择触发信号(一般为clicked(),即点击),然后就可以自动转到槽函数进行定义了。非常的方便。这里槽函数的之所以能够和信号关联起来,完全是靠槽函数的命名,虽然这是程序自动完成的。

void Widget::on_pushButton_clicked(){    //在这里定义槽要实现的功能}

这是一个自动关联的槽函数,其命名方式为:on_部件对象名_信号名()。当然,作为一个函数,也需要进行声明,Qt已经自动在头文件中进行了声明:

private slots:    void on_pushButton_clicked();

如果部件对象名称发生改变,相应的声明和定义都要进行更改,当然,可以采用如下的方式:在函数名on_pushButton_clicked()上右击,选择Refactor->Rename Symbol Under Cursor进行替换,或者用快捷键Ctrl+Shift+R亦可。
这种自动关联的方式非常的方便,适合用过VB和MATLAB GUI的用户,跟上述的思路一模一样,但是这种方式有以下几种局限性:

  1. 只能使用Qt提供的信号,比如 clicked()等;
  2. 在同一级的界面中应用比较方便,也就是说如果将从外界读取的数据显示到父界面或者子界面的某个部件上,那这种方式就不太方便了,一般使用下面的手动关联的方式。

2.手动关联

首先确认一点,手动关联比自动关联要复杂一些,但是实现的功能要多,也就是说自动关联一定可以通过手动关联来实现。手动关联的基本格式是:
connect(sender, SIGNAL(signal), receiver, SLOT(slot));
其中 sender 与 receiver 是指向对象的指针,SIGNAL() 与 SLOT() 是转换信号与槽的宏。
现在我们将上述的自动关联的方式改为手动关联的方式:
1.在头文件中添加声明:

private slots:    void function_of_pushButton();//此时,函数的命名是任意的,尽量做到顾名思义就好

2.在源文件中添加定义:

void Widget::function_of_pushButton(){    //在这里定义槽要实现的功能}

3.在构造函数中添加关联:
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(function_of_pushButton()));

可以看出,虽然手动关联的代码只多了一行(第3步),但是添加声明确需要程序员自己敲(声明后,光标停在在函数名上,按下Alt+Enter,选择定义函数的位置(一般为在XXX.cpp中添加定义),就可以自动跳转到槽,进行定义了,省去了敲击第2步中的代码。
另外,需要注意的是,由于clicked()是Qt提供的信号,这里并没有声明信号。注意,信号只需要声明,不需要定义。
总之,在这种同级的界面下,进行信号与槽的操作还是自动关联比较方便。为了完整的体现信号与槽的在不同界面下的信号的传递,通过下面的程序说明一下。

3.应用实例

程序设计如下:
主界面的基类为QWidget,上面有一个label;子界面的基类是QDialog,上面有个spin box获取一个整数,和一个pushbutton,当该按钮被点击后,主界面的label显示了子界面spin box的值。

界面如下图所示:

类的命名如下图:

基本思路为:
1. 当dialog中的按钮被点击后将获取的值发射到主界面widget的槽函数,注意这部操作,“按钮点击就发射信号”这本身就是就是一个信号与槽的操作,信号是:按钮被点击,槽:发射信号。但这里的信号与槽是都是在dialog同一个类中,数据可以访问,所以直接用自动关联的方式最方便,在设计界面,右击按钮->转到槽,然后定义发射信号的操作,槽的定义如下:

void ww_Dialog::on_pushButton_clicked(){    int val=ui->spinBox->value();    emit getdata(val);//信号要在头文件中声明    close();}

信号的声明如下(在ww_dialog.h中):

signals:    void getdata(int);

注意信号不需要定义。可以将信号理解为当信号出现时,自动执行槽函数的一个标识,同时起到参数传递的作用。比如点击clicked(),再比如这里的emit getdata(val),说明getdata()这个信号被执行了,同时将参数val传递给槽函数。经测试,没有emit 也具有相同的功能(版本Qt5.7),所以emit的作用还需要进一步分析。
2. 定义主界面的槽函数为:

void ww_Widget::showdata(int val){    ui->label->setText(tr("the data is %1").arg(val));}

3.在主界面的构造函数中,将界面联系起来。即新建dialog对象,并将其显示出来;同时,将上述的dialog的信号与widget的槽函数联系起来,具体如下:

 ww_Dialog *dialog=new ww_Dialog(this);//新建对话框    connect(dialog,SIGNAL(getdata(int)),this,SLOT(showdata(int)));//关联信号与槽    dialog->show();//对话框默认显示

4.总结

  1. 这里包含参数传递的信号与槽的操作是这么实现的:

    Created with Raphaël 2.1.0开始子界面中的信号:clicked()子界面中的槽函数:on_pushButton_clicked(),同时触发与主界面关联的信号主界面的槽函数:showdata(int val)结束
  2. 信号与槽可以实现参数传递的作用
  3. 信号与槽经常套用来实现功能
  4. 同一类之间的信号与槽用自动关联的方式更加方便
0 0