天天看点

15 信号与槽

在Qt中使用信号和槽机制来完成对象之间的协同操作。  

简单来说,信号和槽都是函数,比如按下窗口上的一个按钮后想要改变一个窗口上label的文字,那么就可以将这个按钮的单击信号和我们定义的槽关联起来,在槽中中修改label上的文字。这样,当单击这个按钮时就会发射信号,进而执行我们的槽来修改文字。

信号与槽的三种关联方式:

  1. 使用connect()关联
  2. 设计模式中关联
  3. 自动关联

关联方式一:使用connect()关联

实例代码:

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
private slots:
    void showChildDialog();  //槽声明
};

#endif // WIDGET_H      

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->pushButtonOn, SIGNAL(clicked()),  //实现信号与槽的连接
                this, SLOT(showChildDialog()));

}

Widget::~Widget()
{
    delete ui;
}

void Widget::showChildDialog()  //槽实现
{
    ui->labelOn->setText("PushButtonConnectClicked");
    ui->labelOn->resize(20,30);
}      

说明:

这里自定义了一个槽,槽一般使用slots关键字进行修饰(Qt 4中必须使用,Qt 5使用新connect语法时可以不用,为了与一般函数进行区别,建议使用),这里使用了private slots,表明这个槽不可以在类外被调用。

clicked()信号在QPushButton类中进行了定义,而connect()是QObject类中的函数,因为我们的类继承自QObject,所以可以直接使用它。

connect函数原型:

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

connect()函数中的四个参数分别是:发送信号的对象、发送的信号、接收信号的对象和要执行的槽。

当指定信号signal时必须使用QT的宏SIGNAL(),当指定槽函数时必须使用宏SLOT()。如果发射者和接收者属于同一个对象的话,那么在connect调用中接收者参数能省略。 

关联方式二:在设计模式关联

首先添加自定义对话框类MyDialog。在设计模式中向窗口上添加两个Push Button,并且分别更改其显示文本为“进入主界面”和“退出程序”。

点击设计器上方的“编辑信号/槽”图标,或者按下快捷键F4,这时便进入了部件的信号和槽的编辑模式。在“退出程序”按钮上按住鼠标左键,然后拖动到窗口界面上,这时松开鼠标左键。

在弹出的配置连接对话框中,选中下面的“显示从QWidget继承的信号和槽”选项,然后在左边的QPushButton栏中选择信号clicked(),在右边的QDialog栏中选择对应的槽close(),完成后按下“确定”。

15 信号与槽
15 信号与槽

关联方式三:自动关联

在“进入主界面”按钮上右击,在弹出的菜单上选择“转到槽”,然后在弹出的对话框中选择clicked()信号,并按“确定”。这时便会进入代码编辑模式,并且定位到自动生成的on_pushButton_clicked()槽中。在其中添加代码:

15 信号与槽

会自动生成函数:

void MyDialog::on_pushButton_clicked()
{
    //里面的就可以自己填充
}      

自动关联就是将关联函数整合到槽命名中。

例如on_pushButton_clicked()就是由字符“on”和发射信号的部件对象名,还有信号名组成。这样就可以去掉那个connect()关联函数了。每当pushButton被按下,就会发射clicked()信号,然后就会执行on_pushButton_clicked()槽。

这里accept()函数是QDialog类中的一个槽,对于一个使用exec()函数实现的模态对话框,执行了这个槽,就会隐藏这个模态对话框,并返回QDialog::Accepted值,我们就是要使用这个值来判断是哪个按钮被按下了。与其对应的还有一个reject()槽,它可以返回一个QDialog::Rejected值。其实,前面的“退出程序”按钮也可以关联这个槽。

断开联系

当信号和槽没有必要继续保持关联时,我们能使用disconnect函数来断开连接。其定义如下: 

bool QObject::disconnect ( const QObject * sender, const char * signal, 
                    const Object * receiver, const char * member ) [static]      

这个函数断开发射者中的信号和接收者中的槽函数之间的关联。 

有三种情况必须使用disconnect()函数: 

(1)断开和某个对象相关联的所有对象。这似乎有点不可理解,事实上,当我们在某个对象中定义了一个或多个信号,这些信号和另外若干个对象中的槽相关联,如果我们要切断这些关联的话,就能利用这个方法,非常之简洁

disconnect( myObject, 0, 0, 0 ) 或 myObject->disconnect()      

(2)断开和某个特定信号的所有关联。 

disconnect( myObject, SIGNAL(mySignal()), 0, 0 ) 或 myObject->disconnect( SIGNAL(mySignal()) )      

(3)断开两个对象之间的关联。 

disconnect( myObject, 0, myReceiver, 0 ) 或 myObject->disconnect( myReceiver )