(7)Qt中的自定义槽(函数)

简介: 这篇文章介绍了在Qt中如何定义和使用自定义槽函数,包括类成员函数、静态类成员函数、全局函数和lambda表达式作为槽函数的示例,以及使用lambda表达式时的注意事项。

槽函数定义的规则

1.槽函数返回值类型为void

2.槽函数的参数不能多于信号的参数(只能小于等于信号的参数个数)

关联信号与槽错误的示例

按钮被点击触发一个点击信号,从而导致死循环,之后会导致程序中断。

m_btn = new QPushButton("Button", this);
//错误的示例
connect(m_btn, &QPushButton::clicked, m_btn, &QPushButton::click);

类成员函数函数做槽函数使用

类中做槽函数的成员函数一般写在public slots下,Qt5以及以上版本可以不写public slots。

#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QPushButton>
#include <QMessageBox>

//去掉控制台
#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")

class Widget : public QWidget
{
    Q_OBJECT                            // 使用信号与槽机制必须包含此宏
public:
    Widget(QWidget* parent = nullptr)
        :QWidget(parent)
    {
        setWindowTitle("自定义槽");        // 设置窗口标题
        resize(640, 480);                // 设置窗口大小

        m_btn = new QPushButton("成员函数", this);
        //使用信号与槽关联类成员函数
        connect(m_btn, &QPushButton::pressed, this, &Widget::onPressSlot);    
    }
    ~Widget()
    {
    }
public slots:
    void onPressSlot()
    {
        QMessageBox::information(this, "提示", 
            "类成员函数作为槽函数使用", QMessageBox::Ok);
    }
private:
    QPushButton* m_btn = nullptr;
};

int main(int argc, char* argv[]) {

    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}
#include "main.moc"

静态类成员函数做槽函数使用

class Widget : public QWidget
{
    Q_OBJECT                            // 使用信号与槽机制必须包含此宏
public:
    Widget(QWidget* parent = nullptr)
        :QWidget(parent)
    {
        setWindowTitle("自定义槽");        // 设置窗口标题
        resize(640, 480);                // 设置窗口大小

        m_btn = new QPushButton("成员函数", this);
        //使用信号与槽关联静态类成员函数
        connect(m_btn, &QPushButton::pressed, this, &Widget::onPressSlot1);

    }
    ~Widget()
    {

    }
public slots:
    static void onPressSlot1()
    {
        QMessageBox::information(nullptr, "提示",
            "静态类成员函数作为槽函数使用", QMessageBox::Ok);
    }
private:
    QPushButton* m_btn = nullptr;
};

全局函数做槽函数使用

void globalSlot()
{
    QMessageBox::information(nullptr, "提示",
        "全局函数作为槽函数使用", QMessageBox::Ok);
}

class Widget : public QWidget
{
    Q_OBJECT                            // 使用信号与槽机制必须包含此宏
public:
    Widget(QWidget* parent = nullptr)
        :QWidget(parent)
    {
        setWindowTitle("自定义槽");        // 设置窗口标题
        resize(640, 480);                // 设置窗口大小

        m_btn = new QPushButton("全局函数", this);
        //使用信号与槽关联全局函数
        connect(m_btn, &QPushButton::pressed, this, globalSlot);

    }
    ~Widget()
    {

    }
public slots:
private:
    QPushButton* m_btn = nullptr;
};

lambda表达式做槽函数使用

class Widget : public QWidget
{
    Q_OBJECT                            // 使用信号与槽机制必须包含此宏
public:
    Widget(QWidget* parent = nullptr)
        :QWidget(parent)
    {
        setWindowTitle("自定义槽");        // 设置窗口标题
        resize(640, 480);                // 设置窗口大小

        m_btn = new QPushButton("lambda", this);
        //lambda表达式做槽函数使用
        connect(m_btn, &QPushButton::pressed, this, []() {
            QMessageBox::information(nullptr, "提示",
                "lambda表达式作为槽函数使用", QMessageBox::Ok);
        });
    }
    ~Widget()
    {

    }
public slots:
private:
    QPushButton* m_btn = nullptr;
};

使用lambda表达式的注意事项

这样使用是没有问题的,但是如果想让cnt的值每点击一次就++,就需要使用引用捕获的方式。

m_btn = new QPushButton("Button", this);
int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=]() {
    m_btn->setText(QString::number(cnt));
});

注意事项一:

使用引用捕获的方式捕获cnt会导致错误,因为cnt是一个栈区变量,构造函数结束内存会被销毁。

m_btn = new QPushButton("Button", this);
int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=,&cnt]() {
    m_btn->setText(QString::number(cnt++));
});

使用mutable的方式解决上述问题

m_btn = new QPushButton("Button", this);
int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=]() mutable{
    m_btn->setText(QString::number(cnt++));
});

使用静态变量解决上述问题

m_btn = new QPushButton("Button", this);
static int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [=](){
    m_btn->setText(QString::number(cnt++));
});

注意事项二:

当m_btn是类成员变量时,使用引用捕获的方式捕获是没有错误的。

m_btn = new QPushButton("Button", this);
static int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [&](){
    m_btn->setText(QString::number(cnt++));
});

当m_btn是局部变量的时候,使用引用捕获的方式会直接导致程序中断。因为此时的m_btn为栈区内存,构造函数结束之后内存被释放。因此,尽量避免使用引用捕获的方式去捕获。

auto m_btn = new QPushButton("Button", this);
static int cnt = 0;
connect(m_btn, &QPushButton::pressed, m_btn, [&](){
    m_btn->setText(QString::number(cnt++));
});

相关文章
|
3天前
(8)Qt中的自定义信号
本文介绍了如何在Qt框架中创建和使用自定义信号,并通过一个父子窗口切换的示例来展示自定义信号的实现和应用。
19 3
(8)Qt中的自定义信号
|
2月前
|
搜索推荐 C++
【Qt 学习笔记】Qt窗口 | 对话框 | 创建自定义对话框
【Qt 学习笔记】Qt窗口 | 对话框 | 创建自定义对话框
48 4
|
2月前
【qt】自定义对话框(2)
【qt】自定义对话框(2)
20 0
|
2月前
【qt】自定义对话框(1)
【qt】自定义对话框(1)
18 0
|
3月前
|
C++
Qt中的信号与槽如何学习?(包括自定义信号)这篇文章告诉你
以现实中的事件来举例的话,例如有两把不同颜色的信号枪,分别是红色,绿色,打响不通颜色的信号枪会触发不同的槽发生,比如说打响红色这个人就跑步,绿色就走步,但是还有一个很重要的机制,那就是连接,我们需要把信号枪去跟这个人的动作连接起来。 如果上面理解没问题的话我们可以把信号和槽看成两个工具,我们最重要的是如何去把这两个工具连接起来。 它的作用可以让我们更加灵活的去使用不同窗口间的切换以及某些事件的连接。
Qt 窗口常用位置API函数 & 绘图原理 & 双缓冲机制 总结
Qt 窗口常用位置API函数 & 绘图原理 & 双缓冲机制 总结
|
5月前
|
C++
【qt】自定义代理类
【qt】自定义代理类
50 0
|
5月前
|
搜索推荐
【qt】自定义界面类
【qt】自定义界面类
46 0
|
5月前
|
编译器 API
【Qt】- 信号和槽函数
【Qt】- 信号和槽函数
|
5月前
|
监控
QT按键监控函数
QT按键监控函数