1. 程式人生 > 實用技巧 >Qt筆記之 訊號和槽

Qt筆記之 訊號和槽

訊號和槽

目錄

概述

示例程式碼

// mywidget.cpp
#include "mywidget.h"

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    QPushButton *btn = new QPushButton;
    btn->setParent(this); // 設定父視窗
    btn->setText("點選按鈕關閉視窗"); // 設定文字

    resize(600,400); // 重置視窗大小

    btn->move(100,100); // 移動按鈕

    this->setWindowTitle("訊號和槽"); // 改變視窗標題

    this->setFixedSize(600,400); // 固定視窗大小

    // 需求:點選按鈕關閉視窗
    // 引數1:指標 引數2:訊號(點選) 引數3:指標(本視窗) 引數4:槽函式(關閉視窗)
    connect(btn,&QPushButton::clicked,this,&MyWidget::close);
}

MyWidget::~MyWidget()
{
    delete btn;
    delete btn2;
}

自定義訊號和槽

專案結構:

程式碼:

// student.h
#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);

signals:

public slots: // 自定義的槽函式寫在public slots,Qt5後,可以寫在public,全域性和lambda表示式
    // 返回值void
    // 可以有引數,可以過載
    // 有宣告,必須有實現
    void treat();
};

#endif // STUDENT_H

// teacher.h
#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);

signals: // 自定義訊號寫在signals
    // 返回值是void
    // 自定義訊號,只需要宣告,不需要實現
    // 可以有引數,可以過載
    void hungry();

public slots:
};

#endif // TEACHER_H

// mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include "student.h"
#include "teacher.h"

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    MyWidget(QWidget *parent = 0);
    ~MyWidget();

    Teacher *t;
    Student *s;

    // 下課函式
    void classIsOver();
};

#endif // MYWIDGET_H

// student.cpp
#include "student.h"
#include <QDebug>

Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::treat() {
    qDebug() << "請老師吃飯";
}

// mywidget.cpp
#include "mywidget.h"

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    // 建立具體物件
    this->t = new Teacher(this);
    this->s = new Student(this);

    // 繫結訊號和槽
    connect(t,&Teacher::hungry,s,&Student::treat);

    classIsOver(); // 下課
}

void MyWidget::classIsOver() {
    // 觸發訊號
    emit this->t->hungry();
}

MyWidget::~MyWidget()
{
    delete t;
    delete s;
}

效果:

過載

程式碼:

// teacher.h
#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);

signals:
    void hungry();

    void hungry(QString foodName);

public slots:
};

#endif // TEACHER_H

// student.h
#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);

signals:

public slots:
    void treat();

    void treat(QString foodName);
};

#endif // STUDENT_H

// student.cpp
#include "student.h"
#include <QDebug>

Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::treat() {
    qDebug() << "請老師吃飯";
}

void Student::treat(QString foodName) {
    qDebug() << "請老師吃" << foodName.toUtf8().data(); // 呼叫toUtf8轉為QBtyeArray,再呼叫data轉為char *
}

// mywidget.cpp
#include "mywidget.h"

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    // 建立具體物件
    this->t = new Teacher(this);
    this->s = new Student(this);

    // 繫結訊號和槽
    // connect(t,&Teacher::hungry,s,&Student::treat);

    // 建立有引數的自定義訊號和槽
    // 函式指標 -> 函式地址
    void(Teacher::*teacherSignal)(QString) = &Teacher::hungry;
    void(Student::*studentSignal)(QString) = &Student::treat;

    connect(t,teacherSignal,s,studentSignal);

    classIsOver(); // 下課
}

void MyWidget::classIsOver() {
    // 觸發訊號
    emit this->t->hungry();
    emit this->t->hungry("臭豆腐");
}

MyWidget::~MyWidget()
{
    delete t;
    delete s;
}

效果:

拓展

#include "mywidget.h"

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    // 建立具體物件
    this->t = new Teacher(this);
    this->s = new Student(this);

    // 繫結訊號和槽
    // 無參訊號和槽函式
    void(Teacher::*teacherNoSignal)() = &Teacher::hungry;
    void(Student::*studentNoSignal)() = &Student::treat;

    connect(t,teacherNoSignal,s,studentNoSignal);

    // 建立有引數的自定義訊號和槽
    // 函式指標 -> 函式地址
    void(Teacher::*teacherSignal)(QString) = &Teacher::hungry;
    void(Student::*studentSignal)(QString) = &Student::treat;

    connect(t,teacherSignal,s,studentSignal);

    // 點選按鈕下課
    QPushButton *btn = new QPushButton;
    btn->setParent(this);
    btn->setText("下課!");

    // 訊號連線訊號
    connect(btn,&QPushButton::clicked,s,studentNoSignal);

    // 拓展
    // 1. 訊號可以連線訊號
    // 2. 訊號和槽可以斷開連線disconnect
    // 3. 多個訊號可以連線同一個槽函式
    // 4. 一個訊號可以連線多個槽函式
    // 5. 訊號和槽的引數型別必須一一對應
    // 6. 訊號引數的個數可以多於槽函式,反之不可以(很重要)
}

void MyWidget::classIsOver() {
    // 觸發訊號
    emit this->t->hungry();
    emit this->t->hungry("臭豆腐");
}

MyWidget::~MyWidget()
{
    delete t;
    delete s;
    delete btn;
}