• 用 VS Code 搞 Qt6:让信号和槽自动建立连接


    Qt 具备让某个对象的信号与符合要求的槽函数自动建立连接。弄起来也很简单,只要调用这个静态方法即可:

    QMetaObject::connectSlotsByName(...);

    connectSlotsByName 方法需要一个参数,此参数的指针指向一个实例,这个实例自身的信号,以及它的子级对象的信号都会自动连接。

    不过,在用的时候要注意以下几点,否则 connectSlotsByName 方法是不起作用的。

    1、如果类是从某个 QObject 类派生的,比如常见的 QWidget 类,在类的声明中一个定要加上 Q_OBJECT 宏。这条老周在上一篇中说过,不加这个信号和槽不能建立连接。

    2、对象一定要有 Name,即用 setObjectName 方法设置。虽然对象可以使用重复的名字,但不建议这样做,因为 connectSlotsByName 方法只要找到一个名字匹配的对象,就会停止查找。所以,就算你设置了 10 个名为“myButton” 的对象,结果也只能有一个会自动绑定信号和槽,其他的同名对象会忽略。

    3、一定要在所有对象都初始化完毕,包括调用 setObjectName 方法设置对象名称后调用 connectSlotsByName 方法。这样才会有效。

    setObjectName 方法用起来很简单,只要传递对象的名字即可,字符串类型。名字你可以随便取。例如

    QLabel lb ...
    lb.setObjectName("bug");

    这时候,标签对象的名字是“bug”。

    Slot 要支持被自动连接,函数(方法)也是有严格的命名规则的。你必须按照这个规则来,否则不会被识别。槽函数命名规则如下:

    on_XXX_SSS

    1、以“on”开头,每一节用下划线连起来。

    2、XXX 是对象名,注意是对象名,就是用 setObjectName 方法设置的名称,不是你代码中定义的变量名。这个得注意,不能搞错了。

    3、SSS 是信号。

    比如,按钮的 clicked 信号,你让要自己写的槽能够被自动连接,就得这样命名槽函数:on_mybtn_clicked。其中,“mybtn”是对象名。

    ------------------------------------------- 银河分隔线 ------------------------------------------

    下面咱们来动手做个例子,就好理解了。

    一、先弄好 CMake 文件。

    复制代码
    cmake_minimum_required(VERSION 3.0.0)
    project(TestApp VERSION 0.1.0)
    
    find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED YES)
    set(CMAKE_AUTOMOC YES)
    
    add_executable(TestApp WIN32 main.cpp app.h app.cpp)
    target_link_libraries(TestApp PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets)
    复制代码

    这个示例有三个文件。main.cpp 是写 main 函数的地方。app.h 和 app.cpp 中是咱们自定义的窗口类——从 QWidget 类派生。

    二、定义 MyWindow 类,基类是 QWidget。

    复制代码
    /** app.h **/
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    class MyWindow : public QWidget 
    {
        // 这个宏很容易忘了,忘了就不能连接信号和槽了
        Q_OBJECT
    
    public:
        // 构造函数
        MyWindow(QWidget* parent = nullptr);
        // 析构函数
        ~MyWindow();
    
    private:
        // 私有函数
        void initUi(void);
        // 以下是用到的部件(控件)
        QPushButton *btn1;
        QPushButton *btn2;
        QLabel *lb;
        // 布局
        QVBoxLayout *layout;
        QHBoxLayout *sublayout;
    
        // 这几个函数是用于自动绑定的槽
    private slots:
        void on_b1_clicked();
        void on_b2_clicked();
    };
    复制代码

    所有 QObject 的子类,想使用 Signal 和 Slot ,必须调用 Q_OBJECT 宏。这里有两个按钮,on_b1_clicked 和 on_b2_clicked 都是槽。要让两个按钮自动连接,必须分别设置它的 object name 为 “b1” 和 “b2”。

    三、下面是 initUi 函数的实现代码,用于初始化窗体。

    复制代码
    void MyWindow::initUi()
    {
        // 按钮1
        btn1 = new QPushButton(this);
        // 设置按钮1的文本
        btn1 -> setText("左边");
        // 重要:给它个名字
        btn1 -> setObjectName("b1");
    
        // 按钮2
        btn2 = new QPushButton(this);
        // 设置按钮2的文本
        btn2 -> setText("右边");
        // 重要:设置名称
        btn2 -> setObjectName("b2");
    
        // 标签
        lb = new QLabel("请点击下面的按钮", this);
    
        // 布局
        layout = new QVBoxLayout(this);
        layout -> addWidget(lb, 0, Qt::AlignTop);
        sublayout = new QHBoxLayout(this);
        // 添加要布局的组件
        sublayout -> addWidget(btn1);
        sublayout -> addWidget(btn2);
        layout->addLayout(sublayout);
    
        // 窗口
        this -> setWindowTitle("示例王");
        this -> resize(240, 100);
    }
    复制代码

    调用按钮对象的 setObjectName 方法就可以为其分配名称。注意在调用 QPushButton 类的构造函数时,要把当前窗口的指针传递给 parent 参数,使用按钮成为 MyWindow 的子级对象。这样后面才能做信号与槽的自动连接。

    四、在 MyWindow 类构造函数中,先调用 initUi ,再调用 connectSlotsByName 静态方法。

    复制代码
    MyWindow::MyWindow(QWidget *parent)
        : QWidget::QWidget(parent)
    {
        // 调用以下函数,初始化UI
        initUi();
        // 一定要在所有东东都初始化完毕后调用才有效
        QMetaObject::connectSlotsByName(this);
    }
    复制代码

    五、下面是两个槽函数的实现。功能简单,用 QMessageBox 显示弹出框。

    复制代码
    void MyWindow::on_b1_clicked()
    {
        QMessageBox::information(this, "好消息", "左转是男厕", QMessageBox::Ok);
    }
    void MyWindow::on_b2_clicked()
    {
        QMessageBox::information(this, "好消息", "右转是女厕", QMessageBox::Ok);
    }
    复制代码

    六、在 main.cpp 中写 main 函数。

    复制代码
    #include "app.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        // 实例化窗口
        MyWindow wind;
        // 显示窗口
        wind.show();
        // 消息循环
        return app.exec();
    }
    复制代码

     

    运行结果如下面超清动画所示。

    从结果可以看到,名为“b1”的按钮自动将 clicked 信号连接到 on_b1_clicked 函数;名为“b2”的按钮自动将 clicked 信号连接到 on_b2_clicked 函数。

    好了,今天的主题咱们就聊到这儿了。

  • 相关阅读:
    centos 通过rpm包安装mysql5.7
    CPU乘法运算-不再迷惑
    Python Web开发(三):HTTP请求的url路由
    OpenSSL/SSL.py报错:with _from_buffer(buf) as data:
    剑指Java面试:面试官能问到的问题,都被我收集在这份PDF文档里
    python中openpyxl库用法详解
    ManoMano、eMAG等跨境平台如何实现快速出单?测评自养号助你快速突破!
    (论文阅读46-50)图像描述2
    【计算机视觉】Image Feature Extractors方法介绍合集(一)
    直播岗位认知篇
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/16860878.html