Qt信号槽的使用

admin2024-04-03  0

写Qt文章貌似没有信号槽内容就是没有灵魂。(●’◡’●)
Qt的信号和槽机制是一种用于对象间通信的强大且灵活的方法,它允许组件间的解耦以及响应式的编程风格。在Qt中,当一个事件发生时(例如,用户点击了一个按钮),相应组件会发射一个信号;而其他组件可以通过槽函数来接收和处理这些信号。

1. 信号(Signal):

信号是Qt对象中定义的特殊成员函数,它们不具有返回值,也不需要显式调用。信号通常用来表示一个事件的发生,例如按钮点击 (clicked())、状态改变 (textChanged()) 等。信号的声明是在类定义中,且该类必须包含Q_OBJECT宏。

2. 槽(Slot):

槽是可被信号触发的成员函数。槽可以是任意形式的可调用实体,包括普通的成员函数、Lambda表达式或者全局函数。槽函数可以处理信号带来的数据,执行相应的操作。

3. 连接(Connection):

QObject::connect()函数是用来建立信号和槽之间的联系。当信号被发射时,与其连接的所有槽将会按照连接顺序被自动调用。

示例代码:

// 首先,定义一个包含信号和槽的类
class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = nullptr);

signals:
    void buttonClicked(); // 定义一个信号

public slots:
    void onButtonClicked(); // 定义一个槽函数

private:
    QPushButton m_button;
};

// 实现类
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    m_button.setText("Click me!");
    connect(&m_button, &QPushButton::clicked, this, &MyWidget::onButtonClicked); // 连接信号和槽
}

// 槽函数实现
void MyWidget::onButtonClicked()
{
    qDebug() << "Button was clicked!";
}

// 主函数中创建并显示窗口
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}

示例代码过于简单,不进行讲解了。

QObject::connect()函数详细参数说明:

bool QObject::connect(const QObject *sender, const char *signal,
                      const QObject *receiver, const char *slot,
                      Qt::ConnectionType type = Qt::AutoConnection);
  • sender: 发送信号的对象的指针,这里通常是发射信号的那个QObject子类对象。

  • signal: 字符串形式的信号名称。在Qt 5及以后版本中,更推荐使用指针到成员函数的形式指定信号,如 &QPushButton::clicked。

  • receiver: 接收信号并调用槽的对象指针。

  • slot: 字符串形式的槽函数名称,同样在Qt 5后推荐使用指向成员函数的指针,如 &MyWidget::onButtonClicked。

  • type: 连接类型,决定信号与槽的调用时机和线程关系,常见的有:

    • Qt::AutoConnection(默认):如果信号和槽在同一个线程,则进行直接连接(同步调用),否则排队到接收者的事件循环进行异步调用。
    • Qt::DirectConnection:无论是否跨线程,都直接调用槽函数,适合同一线程内同步操作。
    • Qt::QueuedConnection:槽函数总是在接收者的事件循环中异步调用,适用于跨线程通信。
    • 其他连接类型如Qt::BlockingQueuedConnection(阻塞型异步连接)和Qt::UniqueConnection(单次连接,当连接成功后再次连接会失败)。

数据传递:

信号和槽之间还可以传递参数,信号的参数类型和数量必须与槽的匹配。例如,若信号是void signal(QString text),则槽可以是void slot(QString text)。

在Qt 5中,为了支持类型安全和更好的编译时检查,推荐使用新式的连接方式,避免使用字符串形式的信号和槽名称。同时,对于带有参数的信号和槽,无需再使用SIGNAL()和SLOT()宏。例如:

connect(senderObject, &SenderClass::valueChanged, receiverObject, &ReceiverClass::processValue);

以上代码连接了SenderClass的valueChanged()信号和ReceiverClass的processValue()槽,两个函数应当具有匹配的参数列表。

信号槽关联的多种写法

Qt中信号槽关联有多种不同的写法,以下是几种常见的关联方式:

1. Qt Designer UI 文件中的图形化关联

  • 在Qt Designer中设计UI界面时,可以直接在设计界面中通过鼠标拖拽的方式关联信号和槽。右键单击某个控件,选择“转到槽”(Go To Slot),然后选择你需要处理的信号,Qt Designer会自动生成相应的槽函数并在代码中做好连接。

2. 使用QObject::connect()函数手动关联

Qt 4 中的传统写法:
connect(sender, SIGNAL(signalSignature), receiver, SLOT(slotFunction()));

例如:

connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(on_pushButton_clicked()));
Qt 5 及更高版本推荐的类型安全写法:
connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);

例如:

connect(ui->pushButton, &QPushButton::clicked, this, &MyClass::onPushButtonClicked);

3. 自动连接(仅适用于使用Qt Designer生成的UI文件类)

如果你遵循Qt Creator的信号槽命名规范,可以在.cpp文件中利用Ui类的自动连接功能:

void MyClass::setupUi(QMainWindow *parent)
{
    ...
    setupUi(parent);
    ...
}

void MyClass::on_pushButton_clicked() // 自动关联到pushButton的clicked信号
{
    // 处理点击事件的代码
}

4. Lambda表达式作为槽

connect(sender, &SenderClass::signalName, this, [this](){
    // Lambda函数体,处理信号的动作
});

Qt5中支持Qt4的connect的写法。
每种连接方式都需要考虑线程环境,可以选择合适的Qt::ConnectionType作为connect()函数的最后一个参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!