当涉及到Qt的多窗口项目的时候,难免遇到多窗口的通信和管理,比如说,在主窗口创建一个子窗口,子窗口能够发消息给主窗口,并且要求同一时间只能打开一个子窗口;此外,当子窗口关闭时应该通知父窗口,此时父窗口才可以再次创建子窗口。类似的实现就像是QQ聊天窗口一样,当打开一个用户聊天窗口时,不能再次打开重复的用户窗口;当关闭此用户的聊天窗口时,才能再次打开。
那么要怎么实现呢?
还是新手的时候(尽管现在也还是半个菜鸟),我用了父子关系来管理,但是这样会造成子窗口不是顶级窗口的状况,这样当窗口很多的时候,就会很难看。
后来学习了数据库,想想能不能用数据库来记录窗口的状态,根据数据库的值的变化来管理窗口。答案是可以的,但是工作量很大,不得已,又继续挖掘其他的办法。
终于,在论坛上问了一些大神之后,才知道Qt的信号和槽同样可以在多窗口中应用,这也是Qt信号和槽的灵活便利的地方之一吧。
下面来介绍一下代码:
父窗口:
-
#ifndef PARENT_H
-
#define PARENT_H
-
-
#include <QDialog>
-
#include <QtWidgets>
-
#include <child.h>
-
-
class Parent : public QDialog
-
{
-
Q_OBJECT
-
public:
-
Parent();
-
QLineEdit *lineEdit;
-
QLabel *pLabel;
-
QPushButton *childBtn;
-
QPushButton *qBtn;
-
Child *child; //子窗体
-
QHash<QString, Child*> hashChildWindow;//记录子窗口句柄的数据结构
-
-
public slots:
-
void infoRecv(const QString &); //消息接收槽函数
-
void childCreate(); //创建子窗体槽函数
-
void recvQuit(const QString &); //接收子窗口关闭槽函数
-
};
-
-
#endif //PARENT_H
-
#include "parent.h"
-
-
Parent::Parent()
-
{
-
setWindowTitle("Parent");
-
-
lineEdit = new QLineEdit;
-
pLabel = new QLabel("infoRecv: ");
-
childBtn = new QPushButton("childUi");
-
qBtn = new QPushButton("Quit");
-
-
QGridLayout *layout = new QGridLayout(this);
-
layout->addWidget(pLabel,0,0);
-
layout->addWidget(lineEdit,0,1);
-
layout->addWidget(childBtn,1,0);
-
layout->addWidget(qBtn,1,1);
-
this->resize(300,200);
-
connect(qBtn,SIGNAL(clicked()),this,SLOT(reject())); //关闭主窗体
-
connect(childBtn,SIGNAL(clicked()),this,SLOT(childCreate())); //创建子窗体
-
-
}
-
-
void Parent::childCreate()
-
{
-
if(hashChildWindow.contains("child"))
-
{
-
qDebug() << "already open ... ...";
-
}
-
else
-
{
-
child = new Child();
-
hashChildWindow.insert("child", child);
-
connect(child,SIGNAL(infoSend(const QString &)),
-
this,SLOT(infoRecv(const QString &))); //消息发送与接收
-
connect(child, SIGNAL(sendQuit(const QString &)),
-
this, SLOT(recvQuit(const QString &)));//子窗口关闭接收
-
child->show();
-
}
-
}
-
-
void Parent::infoRecv(const QString &str)
-
{
-
lineEdit->setText(str);
-
}
-
-
void Parent::recvQuit(const QString &str)
-
{
-
if(hashChildWindow.contains(str))
-
{
-
hashChildWindow.remove(str);
-
}
-
}
子窗口:
-
#ifndef CHILD_H
-
#define CHILD_H
-
-
#include <QDialog>
-
#include <QtWidgets>
-
-
class Child : public QWidget
-
{
-
Q_OBJECT
-
public:
-
Child();
-
QLineEdit *lineEdit;
-
QLabel *pLabel;
-
QPushButton *tBtn;
-
QPushButton *qBtn;
-
-
signals:
-
void infoSend(const QString &); //定义消息发送信号
-
void sendQuit(const QString &); //定义窗口关闭信号
-
-
public slots:
-
void emit_signal_infosend();//Send按钮单击事件连接的槽函数,目的为发射infoSend信号
-
void emit_signal_sendQuit();//Quit按钮单击事件连接的槽函数,目的为发射sendQuit信号
-
};
-
-
-
#endif // CHILD_H
-
#include "child.h"
-
-
Child::Child()
-
{
-
setWindowTitle("Child");
-
-
lineEdit = new QLineEdit;
-
pLabel = new QLabel("infoSend: ");
-
tBtn = new QPushButton("Send");
-
qBtn = new QPushButton("Quit");
-
-
QGridLayout *layout = new QGridLayout(this);
-
layout->addWidget(pLabel,0,0);
-
layout->addWidget(lineEdit,0,1);
-
layout->addWidget(tBtn,1,0);
-
layout->addWidget(qBtn,1,1);
-
-
this->resize(300,200);
-
-
connect(qBtn,SIGNAL(clicked()),this,SLOT(emit_signal_sendQuit()));
-
connect(tBtn,SIGNAL(clicked()),this,SLOT(emit_signal_infosend()));
-
}
-
-
void Child::emit_signal_infosend()
-
{
-
const QString txt = lineEdit->text();
-
emit infoSend(txt);
-
}
-
-
void Child::emit_signal_sendQuit()
-
{
-
emit sendQuit("child");
-
close();
-
}
PS:
以上代码仅供参考,最好为子窗口添加一个closeEvent来控制子窗口的关闭事件:
-
void Child::closeEvent(QCloseEvent *event)
-
{
-
emit sendQuit("child");
-
event->accept();
-
}
阅读(8424) | 评论(0) | 转发(0) |