• qt 怎么实现在子窗体通知mainwindow界面发生改变


    1、信号和槽

    可以通过信号和槽机制实现子窗体通知主窗体(MainWindow)界面发生改变。以下是一个简单的示例,演示了如何在子窗体中定义信号,然后在主窗体中连接这个信号,以便在发生改变时进行响应。

    1. // ChildWindow.h
    2. #ifndef CHILDWINDOW_H
    3. #define CHILDWINDOW_H
    4. #include
    5. class QPushButton;
    6. class ChildWindow : public QWidget {
    7. Q_OBJECT
    8. public:
    9. explicit ChildWindow(QWidget *parent = nullptr);
    10. signals:
    11. void dataChanged(const QString &newData);
    12. private slots:
    13. void emitDataChangedSignal();
    14. private:
    15. QPushButton *changeDataButton;
    16. };
    17. #endif // CHILDWINDOW_H
    1. // ChildWindow.cpp
    2. #include "ChildWindow.h"
    3. #include
    4. ChildWindow::ChildWindow(QWidget *parent)
    5. : QWidget(parent)
    6. {
    7. changeDataButton = new QPushButton("Change Data", this);
    8. connect(changeDataButton, &QPushButton::clicked, this, &ChildWindow::emitDataChangedSignal);
    9. }
    10. void ChildWindow::emitDataChangedSignal() {
    11. // 发射信号,通知数据发生改变
    12. emit dataChanged("New data from ChildWindow");
    13. }

    然后,在 MainWindow 中连接这个信号,以便在数据发生改变时执行相应的槽函数:

    1. // MainWindow.h
    2. #ifndef MAINWINDOW_H
    3. #define MAINWINDOW_H
    4. #include
    5. class QLabel;
    6. class MainWindow : public QMainWindow {
    7. Q_OBJECT
    8. public:
    9. MainWindow(QWidget *parent = nullptr);
    10. public slots:
    11. void handleDataChanged(const QString &newData);
    12. private:
    13. QLabel *statusLabel;
    14. };
    15. #endif // MAINWINDOW_H
    1. // MainWindow.cpp
    2. #include "MainWindow.h"
    3. #include "ChildWindow.h"
    4. #include <QLabel>
    5. MainWindow::MainWindow(QWidget *parent)
    6. : QMainWindow(parent)
    7. {
    8. statusLabel = new QLabel("No data changes", this);
    9. setCentralWidget(statusLabel);
    10. // 创建子窗体
    11. ChildWindow *childWindow = new ChildWindow(this);
    12. setCentralWidget(childWindow);
    13. // 连接子窗体的信号到主窗体的槽函数
    14. connect(childWindow, &ChildWindow::dataChanged, this, &MainWindow::handleDataChanged);
    15. }
    16. void MainWindow::handleDataChanged(const QString &newData) {
    17. // 在数据发生改变时更新主窗体的界面
    18. statusLabel->setText("Data changed: " + newData);
    19. }

    2、保存主窗体指针

    一种可能的方法是使用直接调用主窗体的公共方法。以下是一个简单的例子

    1. // MainWindow.h
    2. #ifndef MAINWINDOW_H
    3. #define MAINWINDOW_H
    4. #include
    5. class QLabel;
    6. class MainWindow : public QMainWindow {
    7. Q_OBJECT
    8. public:
    9. MainWindow(QWidget *parent = nullptr);
    10. public:
    11. void updateStatus(const QString &newStatus);
    12. private:
    13. QLabel *statusLabel;
    14. };
    15. #endif // MAINWINDOW_H
    1. // MainWindow.cpp
    2. #include "MainWindow.h"
    3. #include "ChildWindow.h"
    4. #include
    5. MainWindow::MainWindow(QWidget *parent)
    6. : QMainWindow(parent)
    7. {
    8. statusLabel = new QLabel("No data changes", this);
    9. setCentralWidget(statusLabel);
    10. // 创建子窗体
    11. ChildWindow *childWindow = new ChildWindow(this);
    12. setCentralWidget(childWindow);
    13. // 设置主窗体指针给子窗体,以便子窗体可以直接调用主窗体的方法
    14. childWindow->setMainWindow(this);
    15. }
    16. void MainWindow::updateStatus(const QString &newStatus) {
    17. // 更新主窗体的界面状态
    18. statusLabel->setText(newStatus);
    19. }
    1. // ChildWindow.h
    2. #ifndef CHILDWINDOW_H
    3. #define CHILDWINDOW_H
    4. #include
    5. class QPushButton;
    6. class MainWindow;
    7. class ChildWindow : public QWidget {
    8. Q_OBJECT
    9. public:
    10. explicit ChildWindow(MainWindow *mainWindow, QWidget *parent = nullptr);
    11. private slots:
    12. void changeData();
    13. private:
    14. QPushButton *changeDataButton;
    15. MainWindow *mainWindow; // 保存主窗体指针
    16. };
    17. #endif // CHILDWINDOW_H
    1. // ChildWindow.cpp
    2. #include "ChildWindow.h"
    3. #include "MainWindow.h"
    4. #include <QPushButton>
    5. ChildWindow::ChildWindow(MainWindow *mainWindow, QWidget *parent)
    6. : QWidget(parent), mainWindow(mainWindow)
    7. {
    8. changeDataButton = new QPushButton("Change Data", this);
    9. connect(changeDataButton, &QPushButton::clicked, this, &ChildWindow::changeData);
    10. }
    11. void ChildWindow::changeData() {
    12. // 在子窗体中直接调用主窗体的方法,通知数据发生改变
    13. mainWindow->updateStatus("Data changed from ChildWindow");
    14. }

    3、单例或者全局变量

    4、事件过滤器

    使用事件过滤器是一种在Qt中实现子窗体通知主窗体的方式。在这种方法中,子窗体可以拦截特定类型的事件,然后执行相应的操作。以下是一个简单的示例,演示如何使用事件过滤器实现这一目的:

    1. // MainWindow.h
    2. #ifndef MAINWINDOW_H
    3. #define MAINWINDOW_H
    4. #include
    5. class QLabel;
    6. class QEvent;
    7. class MainWindow : public QMainWindow {
    8. Q_OBJECT
    9. public:
    10. MainWindow(QWidget *parent = nullptr);
    11. public slots:
    12. void updateStatus(const QString &newStatus);
    13. protected:
    14. bool eventFilter(QObject *watched, QEvent *event) override;
    15. private:
    16. QLabel *statusLabel;
    17. };
    18. #endif // MAINWINDOW_H
    1. // MainWindow.cpp
    2. #include "MainWindow.h"
    3. #include <QLabel>
    4. MainWindow::MainWindow(QWidget *parent)
    5. : QMainWindow(parent)
    6. {
    7. statusLabel = new QLabel("No data changes", this);
    8. setCentralWidget(statusLabel);
    9. // 安装事件过滤器
    10. installEventFilter(this);
    11. }
    12. void MainWindow::updateStatus(const QString &newStatus) {
    13. // 更新主窗体的界面状态
    14. statusLabel->setText(newStatus);
    15. }
    16. bool MainWindow::eventFilter(QObject *watched, QEvent *event) {
    17. // 检查是否是特定的事件类型,这里使用了鼠标按钮释放事件作为示例
    18. if (event->type() == QEvent::MouseButtonRelease) {
    19. // 处理事件,例如调用主窗体的槽函数
    20. updateStatus("Data changed from event filter");
    21. return true; // 表示事件已经被处理
    22. }
    23. // 对于其他事件,调用基类的事件过滤器
    24. return QMainWindow::eventFilter(watched, event);
    25. }

    在这个例子中,主窗体继承了QMainWindow并实现了eventFilter方法。在构造函数中,我们通过调用installEventFilter(this)安装了事件过滤器。

    在事件过滤器中,我们检查事件类型是否为QEvent::MouseButtonRelease,如果是,就执行相应的操作,例如调用主窗体的槽函数updateStatus。这只是一个示例,您可以根据实际需求选择不同的事件类型和相应的处理逻辑。

    然后,当子窗体需要通知主窗体发生改变时,它可以在适当的时候触发这些事件,从而被主窗体的事件过滤器捕获。

    5、使用多态来实现

    多态(Polymorphism)是一种面向对象编程的特性,它允许不同类的对象被同一接口调用,从而实现了更灵活的代码组织和扩展。在这个上下文中,如果您想要使用多态来实现子窗体通知主窗体,可以通过定义一个共同的基类,然后在子窗体中重写该基类的虚函数。主窗体则可以通过基类指针调用这个虚函数。

    以下是一个使用多态实现的简单示例:

    1. // MainWindow.h
    2. #ifndef MAINWINDOW_H
    3. #define MAINWINDOW_H
    4. #include
    5. class QLabel;
    6. class BaseNotifier : public QObject {
    7. Q_OBJECT
    8. public:
    9. virtual void notify(const QString &message) = 0;
    10. };
    11. class MainWindow : public QMainWindow, public BaseNotifier {
    12. Q_OBJECT
    13. public:
    14. MainWindow(QWidget *parent = nullptr);
    15. public slots:
    16. void notify(const QString &message) override;
    17. private:
    18. QLabel *statusLabel;
    19. };
    20. #endif // MAINWINDOW_H
    1. // MainWindow.cpp
    2. #include "MainWindow.h"
    3. #include
    4. MainWindow::MainWindow(QWidget *parent)
    5. : QMainWindow(parent)
    6. {
    7. statusLabel = new QLabel("No data changes", this);
    8. setCentralWidget(statusLabel);
    9. }
    10. void MainWindow::notify(const QString &message) {
    11. // 更新主窗体的界面状态
    12. statusLabel->setText(message);
    13. }
    1. // ChildWindow.h
    2. #ifndef CHILDWINDOW_H
    3. #define CHILDWINDOW_H
    4. #include
    5. #include "MainWindow.h"
    6. class QPushButton;
    7. class ChildWindow : public QWidget, public BaseNotifier {
    8. Q_OBJECT
    9. public:
    10. ChildWindow(MainWindow *mainWindow, QWidget *parent = nullptr);
    11. // 实现基类的虚函数
    12. void notify(const QString &message) override;
    13. private slots:
    14. void changeData();
    15. private:
    16. QPushButton *changeDataButton;
    17. MainWindow *mainWindow; // 保存主窗体指针
    18. };
    19. #endif // CHILDWINDOW_H
    1. // ChildWindow.cpp
    2. #include "ChildWindow.h"
    3. #include <QPushButton>
    4. ChildWindow::ChildWindow(MainWindow *mainWindow, QWidget *parent)
    5. : QWidget(parent), mainWindow(mainWindow)
    6. {
    7. changeDataButton = new QPushButton("Change Data", this);
    8. connect(changeDataButton, &QPushButton::clicked, this, &ChildWindow::changeData);
    9. }
    10. void ChildWindow::changeData() {
    11. // 在子窗体中调用主窗体的虚函数,通知数据发生改变
    12. mainWindow->notify("Data changed from ChildWindow");
    13. }
    14. void ChildWindow::notify(const QString &message) {
    15. // 在子窗体中实现基类的虚函数,这里可以进行其他处理
    16. // 例如,如果子窗体自身也需要对通知进行处理
    17. qDebug() << "ChildWindow received notification:" << message;
    18. }

    在这个例子中,BaseNotifier 是一个纯虚基类,它定义了一个纯虚函数 notifyMainWindowChildWindow 都继承自 BaseNotifier,并实现了 notify 函数。子窗体可以通过调用主窗体的虚函数来通知主窗体发生改变。这种方法具有一定的灵活性,因为您可以在子窗体中进行特定的处理,而不仅仅是简单地通知主窗体。

    6、使用消息队列怎么实现呢?

    消息队列来实现子窗体通知主窗体的方式需要在 Qt 中引入一些自定义的信号与槽机制。这种方法会创建一个消息队列,并通过自定义消息类将消息传递给主窗体。以下是一个简单的示例:

    1. // Message.h
    2. #ifndef MESSAGE_H
    3. #define MESSAGE_H
    4. #include <QString>
    5. class Message {
    6. public:
    7. enum MessageType {
    8. DataChanged
    9. };
    10. Message(MessageType type, const QString &data = QString())
    11. : type(type), data(data)
    12. {}
    13. MessageType type;
    14. QString data;
    15. };
    16. #endif // MESSAGE_H
    1. // MainWindow.h
    2. #ifndef MAINWINDOW_H
    3. #define MAINWINDOW_H
    4. #include
    5. class QLabel;
    6. class MainWindow : public QMainWindow {
    7. Q_OBJECT
    8. public:
    9. MainWindow(QWidget *parent = nullptr);
    10. public slots:
    11. void handleMessage(const Message &message);
    12. private:
    13. QLabel *statusLabel;
    14. };
    15. #endif // MAINWINDOW_H
    1. // MainWindow.cpp
    2. #include "MainWindow.h"
    3. #include "Message.h"
    4. #include <QLabel>
    5. MainWindow::MainWindow(QWidget *parent)
    6. : QMainWindow(parent)
    7. {
    8. statusLabel = new QLabel("No data changes", this);
    9. setCentralWidget(statusLabel);
    10. }
    11. void MainWindow::handleMessage(const Message &message) {
    12. // 根据消息类型执行相应操作
    13. if (message.type == Message::DataChanged) {
    14. // 更新主窗体的界面状态
    15. statusLabel->setText(message.data);
    16. }
    17. }
    1. // ChildWindow.h
    2. #ifndef CHILDWINDOW_H
    3. #define CHILDWINDOW_H
    4. #include
    5. #include
    6. #include "Message.h"
    7. class QPushButton;
    8. class ChildWindow : public QWidget {
    9. Q_OBJECT
    10. public:
    11. ChildWindow(QWidget *parent = nullptr);
    12. signals:
    13. void messageReady(const Message &message);
    14. private slots:
    15. void changeData();
    16. private:
    17. QPushButton *changeDataButton;
    18. QQueue messageQueue;
    19. };
    20. #endif // CHILDWINDOW_H
    1. // ChildWindow.cpp
    2. #include "ChildWindow.h"
    3. #include "Message.h"
    4. #include
    5. ChildWindow::ChildWindow(QWidget *parent)
    6. : QWidget(parent)
    7. {
    8. changeDataButton = new QPushButton("Change Data", this);
    9. connect(changeDataButton, &QPushButton::clicked, this, &ChildWindow::changeData);
    10. }
    11. void ChildWindow::changeData() {
    12. // 创建消息并放入消息队列
    13. Message message(Message::DataChanged, "Data changed from ChildWindow");
    14. messageQueue.enqueue(message);
    15. // 发送信号,通知消息已经准备好
    16. emit messageReady(message);
    17. }
    1. // main.cpp
    2. #include
    3. #include "MainWindow.h"
    4. #include "ChildWindow.h"
    5. int main(int argc, char *argv[]) {
    6. QApplication a(argc, argv);
    7. MainWindow mainWindow;
    8. ChildWindow childWindow;
    9. // 连接子窗体的消息信号到主窗体的槽函数
    10. QObject::connect(&childWindow, &ChildWindow::messageReady, &mainWindow, &MainWindow::handleMessage);
    11. mainWindow.show();
    12. childWindow.show();
    13. return a.exec();
    14. }

    在这个例子中,Message 类定义了一个消息结构,其中包含消息类型和数据。MainWindow 中的 handleMessage 槽函数负责处理接收到的消息,根据消息类型执行相应的操作。

    ChildWindow 中的 changeData 槽函数会创建一个消息并将其放入消息队列,然后通过 messageReady 信号发射消息。在 main.cpp 中,使用 QObject::connect 连接了子窗体的 messageReady 信号到主窗体的 handleMessage 槽函数。

    这种方式需要确保在主循环中处理消息队列,以便在 UI 线程中正确处理消息。

  • 相关阅读:
    C语言百钱买百鸡(ZZULIOJ1074:百钱买百鸡)
    创建空List的两种方法
    drools决策表的简单使用
    Centos7 安装和配置 Redis 5 教程
    Delphi版设计模式
    React.js学习(一):设计并实现一个“任务清单列表”
    pytorch、tensorflow对比学习—张量
    清朝皇帝年表及1840年后清朝历史事件
    【我的两周年创作纪念日】
    Hanoi塔问题
  • 原文地址:https://blog.csdn.net/cangqiongxiaoye/article/details/134356087