跳到主要内容

信号和槽的连接

可以使用引用类型参数吗

曾一度认为信号/槽参数如果使用指针/引用,则当信号传输到槽的时候,所传输的指针/引用指向内存已经释放,因此槽接收到的是野指针/无效引用。因此,信号/槽的参数只能使用值传递。
现在才发现上面的认识是错误的。在 单线程 的情况之下,就算信号/槽使用了引用类型的参数也是允许的。由于是单线程,槽接收到引用时发送信号的函数其实还没结束,因此就算传递过来的是一个局部变量的引用,也是有效的。当槽返回的时候,发送信号的函数再继续往下执行,这其实就相当于单片机中断处理。

各种连接方式

连接信号槽 connect 函数的第五个参数

enum ConnectionType {
AutoConnection,
DirectConnection,
QueuedConnection,
BlockingQueuedConnection,
UniqueConnection = 0x80
};

  • Qt::AutoConnection:默认值。根据 sender 和 receiver 所处线程在信号发出时作出判断。如果在同一线程则使用 Qt::DirectConnection 连接,否则使用 Qt ::QueuedConnection 连接。需要注意的是,这个判断和 sender 对象所处线程无关,真正判断的是发出信号这个动作所在的线程
  • Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。需要注意的是,在多线程环境下比较危险,可能会造成奔溃
  • Qt::QueuedConnection:槽函数在控制回到接收者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循环之后,槽函数才会被调用。多线程环境下一般用这个
  • Qt::BlockingQueuedConnection:槽函数的调用时机与 Qt::QueuedConnection 一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完,在多线程间需要同步的场合可能需要这个。需要注意的是,接收者和发送者绝对不能在一个线程,否则程序会死锁
  • Qt::UniqueConnection:这个 flag 可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败,也就是避免了重复连接
//Qt4
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(close()))
//Qt5
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::close)
//函数指针
void(MainWindow:: *buttonClickSlot)() = &MainWindow::onButtonPushed;
connect(ui->pushButton, &QPushButton::clicked, this, buttonClickSlot);
//Lambda表达式
connect(ui->pushButton, &QPushButton::clicked, this, [=](){ this->close(); });