信号和槽机制是 Qt 编程的基础,它可以让应用程序编程人员把这些互不了解的对象绑定在一起。槽和普通的 C++ 成员几乎是一样的 —— 可以是虚函数;可以被重载;可以是公有的、保护的或者私有的,并且也可以被其他 C++ 成员函数直接调用;还有,它们的参数可以使任意类型。唯一不同的是:槽还可以和信号连接在一起。在这种情况下,每当发射这个信号的时候,就会自动调用这个槽

连接信号

语法格式

connect() 语句的格式如下:

1
connect(sender, SIGNAL(signal), receiver, SLOT(slot));

这里的 senderreceiver 是指向 QObject 的指针, signalslot 是不带参数的函数名。实际上,SIGNAL() 宏和 SLOT() 宏会把它们的参数转换成相应的字符串。

要把信号成功连接到槽(或者连接到另外一个信号),它们的参数必须具有相同的顺序和相同的类型:

1
2
connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),
this, SLOT(processReply(int, const QString &)));

这里有个例外,如果信号的参数比它所连接的槽的参数多,那么多余的参数将会被简单的忽略掉。

1
2
connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),
this, SLOT(checkErrorCode(int)));

一个信号可以连接多个槽

1
2
3
4
connect(slider, SIGNAL(valueChanged(int)),
spinBox, SLOT(setValue(int)));
connect(slider, SIGNAL(valueChanged(int)),
this, SLOT(updateStatusBarIndicator(int)));

在发射这个信号的时候,会以不确定的顺序一个接一个地调用这些槽。

多个信号可以连接同一个槽

1
2
3
4
connect(lcd, SIGNAL(overflow()),
this, SLOT(handleMathError()));
connect(calculator, SIGNAL(divisionByZero()),
this, SLOT(handleMathError()));

无论发射的是哪个信号,都会调用这个槽。

一个信号可以与另一个信号相连接

1
2
connect(lineEdit, SIGNAL(textChanged(const QString &)),
this, SIGNAL(updateRecord(const QString &)));

当发射第一个信号时,也会发射第二个信号 。除此之外,信号与信号之间的连接和信号与槽之间的连接是难以区分的。

移除信号

1
2
disconnect(lcd, SIGNAL(overflow()),
this, SLOT(handleMathError()));

这种情况很少用到,因为当删除对象时,Qt 会自动移除和这个对象相关的所有连接。

非图形窗口部件使用信号和槽

Qt 的信号和槽机制是在 QObject 中实现的,但不只局限于图形用户界面编程中。这种机制可以用于任何 QObject 的子类中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Employee : public QObject
{
Q_OBJECT

public:
Employee() { mySalary = 0; }

int salary() const { return mySalary; }

public slots:
void setSalary(int newSalary);

signals:
void salaryChanged(int newSalary);

private:
int mySalary;
}

void Employee::setSalary(int newSalary)
{
if (newSalary != mySalary){
mySalary = newSalary;
emit salaryChanged(mySalary);
}
}

Comments