qt两个类之间自定义信号槽

有时候我们可能遇到一个问题,我们想在A类里面定义一个事件,当这个事件被触发之后,它可以发射一个信号出来,让B,C,D类等其他类去执行一个功能,这些执行功能的类可能是一个QWidget类,或者是一个普通的类,我们可能遇到的问题是怎么让一个信号和槽跨越几个类?

最难的是,如果这些类之间有相互include的关系,比如A中的按钮单击之后,打开了B窗口,因此A类必须include B的头文件。而如果要利用A类发射其他信号来更改B类的一些特性,就需要在B类建立一个信号槽,而且B类要include A类的头文件,以使得信号槽的发送者可以查到。

从一个简单的例子开始讲起:
我们在VS中新建一个基于QMainwindow的工程,名为qt_signal_test,然后在Mainwindow中添加一个按钮,运行后界面为:

///   main.cpp     ///
#include "qt_signal_test.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qt_signal_test w;
    w.show();
    return a.exec();
}
         qt_signal_test.h        /
#ifndef QT_SIGNAL_TEST_H
#define QT_SIGNAL_TEST_H

#include <QtWidgets/QMainWindow>
#include "ui_qt_signal_test.h"
#include "qpushbutton.h"
#include "qlabel.h"

class qt_signal_test : public QMainWindow
{
    Q_OBJECT

public:
    qt_signal_test(QWidget *parent = 0);
    ~qt_signal_test();
    QPushButton *button;
    QLabel *label;

private:
    Ui::qt_signal_testClass ui;
};

#endif // QT_SIGNAL_TEST_H
        qt_signal_test.cpp     /
#include "qt_signal_test.h"

qt_signal_test::qt_signal_test(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    this->setGeometry(200, 200, 400, 400);
    button = new QPushButton(this);
    label = new QLabel(this);
    button->setGeometry(50, 50, 60, 30);
    label->setGeometry(100, 100, 60, 30);
    button->setText(QString::fromLocal8Bit("确定"));
    label->setText(QString::fromLocal8Bit("等待"));
}

qt_signal_test::~qt_signal_test()
{

}

我们新建一个关于button的槽函数,单击一次,label的文本就变化了。

         qt_signal_test.h       //
#ifndef QT_SIGNAL_TEST_H
#define QT_SIGNAL_TEST_H

#include <QtWidgets/QMainWindow>
#include "ui_qt_signal_test.h"
#include "qpushbutton.h"
#include "qlabel.h"

class qt_signal_test : public QMainWindow
{
    Q_OBJECT

public:
    qt_signal_test(QWidget *parent = 0);
    ~qt_signal_test();
    QPushButton *button;
    QLabel *label;

private:
    Ui::qt_signal_testClass ui;

public slots:
    void changeMyText();
};

#endif // QT_SIGNAL_TEST_H


        qt_signal_test.cpp     /
#include "qt_signal_test.h"

qt_signal_test::qt_signal_test(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    this->setGeometry(200, 200, 400, 400);
    button = new QPushButton(this);
    label = new QLabel(this);
    button->setGeometry(50, 50, 60, 30);
    label->setGeometry(100, 100, 60, 30);
    button->setText(QString::fromLocal8Bit("确定"));
    label->setText(QString::fromLocal8Bit("等待"));

    connect(button, &QPushButton::clicked, this, &qt_signal_test::changeMyText);
}

qt_signal_test::~qt_signal_test()
{

}

void qt_signal_test::changeMyText()
{
    label->setText(QString::fromLocal8Bit("您单击了!"));
}

我们新建一个MyWindow类,继承在QMainwindow,修改qt_signal_test的界面,使之包含两个按钮,一个是用于打开新窗体(MyWindow对象),一个用于给MyWindow上的label控件触发的按钮。同时将qt_signal_test上的label控件删去,移至MyWindow上,在qt_signal_test类内新增一个MyWindow窗体对象mywindow,并添加一个槽函数,使得单击打开按钮后,可以让这个对象窗口显示。

         qt_signal_test.h       //
#ifndef QT_SIGNAL_TEST_H
#define QT_SIGNAL_TEST_H

#include <QtWidgets/QMainWindow>
#include "ui_qt_signal_test.h"
#include "qpushbutton.h"
#include "mywindow.hpp"

class qt_signal_test : public QMainWindow
{
    Q_OBJECT

public:
    qt_signal_test(QWidget *parent = 0);
    ~qt_signal_test();
    QPushButton *button;
    QPushButton *button_2;
    MyWindow mywindow;

private:
    Ui::qt_signal_testClass ui;

public slots:
    void openNewWindow();

};

#endif // QT_SIGNAL_TEST_H


        qt_signal_test.cpp     /
#include "qt_signal_test.h"

qt_signal_test::qt_signal_test(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    this->setGeometry(200, 200, 400, 400);
    button = new QPushButton(this);
    button->setGeometry(50, 50, 60, 30);
    button->setText(QString::fromLocal8Bit("确定"));
    button_2 = new QPushButton(this);
    button_2->setGeometry(130, 50, 60, 30);
    button_2->setText(QString::fromLocal8Bit("打开"));
    connect(button_2, &QPushButton::clicked, this, &qt_signal_test::openNewWindow);
}

qt_signal_test::~qt_signal_test()
{

}

void qt_signal_test::openNewWindow()
{
    mywindow.show();
}

//      mywindow.hpp     ///
#pragma once
#include <QMainWindow>
#include "ui_mywindow.h"
#include "qlabel.h"

class MyWindow : public QMainWindow {
    Q_OBJECT

public:
    MyWindow(QWidget * parent = Q_NULLPTR);
    ~MyWindow();
    QLabel *label;

private:
    Ui::MyWindow ui;

public slots:
    void changeMyText();
};

//      mywindow.cpp     ///
#include "mywindow.hpp"

MyWindow::MyWindow(QWidget * parent) : QMainWindow(parent) {
    ui.setupUi(this);
    this->setGeometry(700, 200, 400, 400);
    label = new QLabel(this);
    label->setGeometry(100, 100, 60, 30);
    label->setText(QString::fromLocal8Bit("等待"));
    //connect(button, &QPushButton::clicked, this, &MyWindow::changeMyText);
}

MyWindow::~MyWindow() {

}

void MyWindow::changeMyText()
{
    label->setText(QString::fromLocal8Bit("您单击了!"));
}

我希望实现的功能就是我在第一个窗体上单击“确定”,可以让第二个窗体上的控件上的文字改变。
我们试着把mywindow.cpp的第9行的注释去掉,发现它报错。
我们要将第一个qt_signal_test类的对象做成一个全局变量,怎么做呢?

          main.cpp     //
#include "qt_signal_test.h"
#include <QtWidgets/QApplication>
qt_signal_test *singal_test;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    singal_test = new qt_signal_test;
    singal_test->show();
    return a.exec();
}


         qt_signal_test.h       //
#ifndef QT_SIGNAL_TEST_H
#define QT_SIGNAL_TEST_H

#include <QtWidgets/QMainWindow>
#include "ui_qt_signal_test.h"
#include "qpushbutton.h"
#include "mywindow.hpp"

class qt_signal_test : public QMainWindow
{
    Q_OBJECT

public:
    qt_signal_test(QWidget *parent = 0);
    ~qt_signal_test();
    QPushButton *button;
    QPushButton *button_2;
    MyWindow mywindow;

private:
    Ui::qt_signal_testClass ui;

public slots:
    void openNewWindow();

};

extern qt_signal_test *singal_test;

#endif // QT_SIGNAL_TEST_H

//      mywindow.hpp     ///
#pragma once
#include <QMainWindow>
#include "ui_mywindow.h"
#include "qlabel.h"

class MyWindow : public QMainWindow {
    Q_OBJECT

public:
    MyWindow(QWidget * parent = Q_NULLPTR);
    ~MyWindow();
    QLabel *label;

private:
    Ui::MyWindow ui;

public slots:
    void changeMyText();
};


//      mywindow.cpp     ///
#include "mywindow.hpp"
#include "qt_signal_test.h"

MyWindow::MyWindow(QWidget * parent) : QMainWindow(parent) {
    ui.setupUi(this);
    this->setGeometry(700, 200, 400, 400);
    label = new QLabel(this);
    label->setGeometry(100, 100, 60, 30);
    label->setText(QString::fromLocal8Bit("等待"));
    connect(singal_test->button, &QPushButton::clicked, this, &MyWindow::changeMyText);
}

MyWindow::~MyWindow() {

}

void MyWindow::changeMyText()
{
    label->setText(QString::fromLocal8Bit("您单击了!"));
}

我们发现,程序运行报错,为什么呢?

这是因为mywindow和qt_signal_test两个类的头文件相互包含了。
怎么解决的?

          main.cpp     //
#include "qt_signal_test.h"
#include "mywindow.hpp"
#include <QtWidgets/QApplication>
qt_signal_test *singal_test;
MyWindow *mywindow;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    singal_test = new qt_signal_test;
    mywindow = new MyWindow;
    singal_test->show();
    return a.exec();
}

         qt_signal_test.h       //
#ifndef QT_SIGNAL_TEST_H
#define QT_SIGNAL_TEST_H

#include <QtWidgets/QMainWindow>
#include "ui_qt_signal_test.h"
#include "qpushbutton.h"
#include "mywindow.hpp"

class qt_signal_test : public QMainWindow
{
    Q_OBJECT

public:
    qt_signal_test(QWidget *parent = 0);
    ~qt_signal_test();
    QPushButton *button;
    QPushButton *button_2;

private:
    Ui::qt_signal_testClass ui;

public slots:
    void openNewWindow();

};

extern qt_signal_test *singal_test;

#endif // QT_SIGNAL_TEST_H

         qt_signal_test.cpp       //
#include "qt_signal_test.h"

qt_signal_test::qt_signal_test(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    this->setGeometry(200, 200, 400, 400);
    button = new QPushButton(this);
    button->setGeometry(50, 50, 60, 30);
    button->setText(QString::fromLocal8Bit("确定"));
    button_2 = new QPushButton(this);
    button_2->setGeometry(130, 50, 60, 30);
    button_2->setText(QString::fromLocal8Bit("打开"));
    connect(button_2, &QPushButton::clicked, this, &qt_signal_test::openNewWindow);
}

qt_signal_test::~qt_signal_test()
{

}

void qt_signal_test::openNewWindow()
{
    mywindow->show();
}


//      mywindow.hpp     ///
#pragma once
#include <QMainWindow>
#include "ui_mywindow.h"
#include "qlabel.h"
#include "qpushbutton.h"
#include "qt_signal_test.h"

class MyWindow : public QMainWindow {
    Q_OBJECT

public:
    MyWindow(QWidget * parent = Q_NULLPTR);
    ~MyWindow();
    QLabel *label;


private:
    Ui::MyWindow ui;

public slots:
    void changeMyText();
};

extern MyWindow *mywindow;

//      mywindow.cpp     ///
#include "mywindow.hpp"

MyWindow::MyWindow(QWidget * parent) : QMainWindow(parent) {
    ui.setupUi(this);
    this->setGeometry(700, 200, 400, 400);
    label = new QLabel(this);
    label->setGeometry(100, 100, 60, 30);
    label->setText(QString::fromLocal8Bit("等待"));
    connect(singal_test->button, &QPushButton::clicked, this, &MyWindow::changeMyText);
}

MyWindow::~MyWindow() {

}

void MyWindow::changeMyText()
{
    label->setText(QString::fromLocal8Bit("您单击了!"));
}

我们也可以自己定义信号,比如

         qt_signal_test.h       //
#ifndef QT_SIGNAL_TEST_H
#define QT_SIGNAL_TEST_H

#include <QtWidgets/QMainWindow>
#include "ui_qt_signal_test.h"
#include "qpushbutton.h"
#include "mywindow.hpp"

class qt_signal_test : public QMainWindow
{
    Q_OBJECT

public:
    qt_signal_test(QWidget *parent = 0);
    ~qt_signal_test();
    QPushButton *button;
    QPushButton *button_2;

private:
    Ui::qt_signal_testClass ui;

public slots:
    void jifa();

signals:
    void xianshi();

};

extern qt_signal_test *singal_test;

#endif // QT_SIGNAL_TEST_H

         qt_signal_test.cpp       //
#include "qt_signal_test.h"

qt_signal_test::qt_signal_test(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    this->setGeometry(200, 200, 400, 400);
    button = new QPushButton(this);
    button->setGeometry(50, 50, 60, 30);
    button->setText(QString::fromLocal8Bit("确定"));
    button_2 = new QPushButton(this);
    button_2->setGeometry(130, 50, 60, 30);
    button_2->setText(QString::fromLocal8Bit("打开"));
    connect(button_2, &QPushButton::clicked, this, &qt_signal_test::jifa);
}

qt_signal_test::~qt_signal_test()
{

}

void qt_signal_test::jifa()
{
    emit xianshi();
}

//      mywindow.cpp     ///
#include "mywindow.hpp"

MyWindow::MyWindow(QWidget * parent) : QMainWindow(parent) {
    ui.setupUi(this);
    this->setGeometry(700, 200, 400, 400);
    label = new QLabel(this);
    label->setGeometry(100, 100, 60, 30);
    label->setText(QString::fromLocal8Bit("等待"));
    connect(singal_test, &qt_signal_test::xianshi, this, &MyWindow::changeMyText);
}

MyWindow::~MyWindow() {

}

void MyWindow::changeMyText()
{
    mywindow->show();
    label->setText(QString::fromLocal8Bit("您单击了!"));
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值