场景:点击父窗口按钮1,弹出子窗口。点击子窗口查询按钮,隐藏子窗口并把查询结果显示在父窗口上。
参考文献Qt实例–主窗口和子窗口互发信号
简化需求为:子窗口点击按钮,向父窗口发送消息,并显示在子窗口上:
子窗口 DatasetQueryConditionWgt.h
要定义两个函数:
- 点击按钮,发送信号的槽函数SlotQueryBtnClicked(),注意带上slots
- 发送信息的函数 SignalQueryConditionBtnClicked(QVariantMap m_queryCondition),注意带上signals关键字
signals:
void SignalQueryConditionBtnClicked(QVariantMap m_queryCondition);
protected slots:
void SlotQueryBtnClicked();
子窗口 DatasetQueryConditionWgt.cpp
connect(ui.queryBtn, SIGNAL(clicked()), this, SLOT(SlotQueryBtnClicked()));//在子窗口的构造函数中写connect函数
...
void DatasetQueryConditionWgt::SlotQueryBtnClicked()
{
...//其他操作
emit SignalQueryConditionBtnClicked( m_queryCondition);
}
父窗口 DataSetQueryWidget.h
申明槽函数,接受子窗口发送的信号
protected slots:
void DatasetQueryConditionWgtReceiveSignals(QVariantMap queryCondition);
父窗口 DataSetQueryWidget.cpp
connect(m_pWindow, &DatasetQueryConditionWgt::SignalQueryConditionBtnClicked, this, &DataSetQueryWidget::DatasetQueryConditionWgtReceiveSignals);
//参数分别是:子窗口实例化的对象指针,子窗口的信号函数,父窗口的对象指针,父窗口的槽函数
//一般在子窗口实例化,也就是new完之后 写connect
void DataSetQueryWidget::DatasetQueryConditionWgtReceiveSignals(QVariantMap queryCondition)
{
m_pWindow->hide();
queryCondition ···
}
坑一:
一开始我在父窗口的构造函数中写 connect,点击按钮没反应,因为构造函数运行时,子窗口还没有实例化,connect不起作用
new完之后再写就好了!!!
if(!m_pWindow)
m_pWindow = new DatasetQueryConditionWgt(this);
connect(m_pWindow, &DatasetQueryConditionWgt::SignalQueryConditionBtnClicked, this, &DataSetQueryWidget::DatasetQueryConditionWgtReceiveSignals);
坑二:
本来不打算用这个方法的,本来是打算直接在父窗口写子窗口的槽函数,但是在写connect时,发现 子窗口.ui 无法使用。这个是子窗口私有化的对象,所以connect无法奏效。
同事给了一种解决方案:在子窗口中设置getui函数获取ui,应该也可以,但是我没试。当然这个发送消息的方式也时同时告诉我的
父窗口向子窗口发送信息
父界面.h
signals:
void SignalAddDataset(QString datasetName);
父界面.cpp
#include "子界面.h"
//构造函数
父界面::父界面(QWidget *parent)
: QWidget(parent)
{
connect(this, &DataSetManageTab::SignalAddDataset, ui.dataSetManageWgt, &DataSetManagementWidget::ShowDatasetInfo);
//connect(this, SIGNAL(SignalAddDataset(QString)), ui.dataSetManageWgt, SLOT(ShowDatasetInfo(const QString & )));
}
某某函数()
{
emit SignalAddDataset(selectedDatasets[0]);
}
注:被注释掉的connect不好用,它能发送信号,但是子界面收不到
子界面.h
public:
void ShowDatasetInfo(const QString& strDatasetName);
子界面.cpp
void dataSetManageWgt::ShowDatasetInfo(const QString& strDatasetName)
{
......
}
完整代码:
主界面
点击 show child
父界面给子界面发消息
子给父发
parentWidget.h
#pragma once
#include <QMainWindow>
#include "childWidget.h"
#include<QPushButton>
#include<QLabel>
#include "ui_parentWidget.h"
class parentWidget :
public QMainWindow
{
Q_OBJECT
public:
parentWidget(QWidget *parent = Q_NULLPTR);
~parentWidget();
signals:
void sendTextToChild(QString);
protected slots:
void showChildWidget();
void showChildSay(QString);
void sendChildWidget();
private:
childWidget* m_childWidget =nullptr;
QPushButton *button = nullptr, *button2 = nullptr;
QLabel *label = nullptr;
private:
Ui::MainWindow *ui;
};
parentWidget .cpp
#include "parentWidget.h"
#include<QGridLayout>
parentWidget::parentWidget(QWidget *parent ):QMainWindow(parent)
{
ui->setupUi(this);
button = new QPushButton(this);
button->setText("talk to child");
label = new QLabel(this);
label->setText("show child say");
button2 = new QPushButton(this);
button2->setText("show child widget");
QGridLayout* glayReview = new QGridLayout(parent);
glayReview->addWidget(button,0,0,1,1);
glayReview->addWidget(label,1,0, 1, 1);
glayReview->addWidget(button2,2,0, 1, 1);
ui->centralwidget->setLayout(glayReview);
connect(button2, SIGNAL(clicked()), this, SLOT(showChildWidget()));
connect(button, SIGNAL(clicked()), this, SLOT(sendChildWidget()));
}
parentWidget::~parentWidget()
{
}
void parentWidget::showChildWidget()
{
if (!m_childWidget)
{
m_childWidget = new childWidget();
}
connect(this, &parentWidget::sendTextToChild, m_childWidget, &childWidget::showParentSay);
connect(m_childWidget, &childWidget::sendTextToParent, this, &parentWidget::showChildSay);
m_childWidget->show();
}
void parentWidget::sendChildWidget()
{
emit sendTextToChild("Hello child");
}
void parentWidget::showChildSay(QString str)
{
label->setText(str);
}
子界面childWidget.h
#pragma once
#include <qwidget.h>
#include<QPushButton>
#include<QLabel>
#include"ui_childWidget.h"
class childWidget :public QWidget
{
Q_OBJECT
public:
childWidget(QWidget *parent = Q_NULLPTR);
~childWidget();
signals:
void sendTextToParent(QString);
public slots:
void showParentSay(QString);
void sendToParentWidget();
private:
QPushButton *button=nullptr;
QLabel *label = nullptr;
private:
Ui::childWidget *ui;
};
childWidget .cpp
#include "childWidget.h"
#include<QPushButton>
#include<QLabel>
#include<QGridLayout>
childWidget::childWidget(QWidget *parent):QWidget(parent)
{
ui->setupUi(this);
button = new QPushButton();
button->setText("talk to Parent");
label = new QLabel();
label->setText("show parent say");
QGridLayout* glayReview = new QGridLayout(parent);
glayReview->setContentsMargins(10, 10, 10, 10);
glayReview->addWidget(button,0,0, 1, 1);
glayReview->addWidget(label,1,0, 1, 1);
setLayout(glayReview);
connect(button, SIGNAL(clicked()), this, SLOT(sendToParentWidget()));
}
childWidget::~childWidget()
{
}
void childWidget::showParentSay(QString str)
{
label->setText(str);
}
void childWidget::sendToParentWidget()
{
emit sendTextToParent("Hello parent");
}