Chinaunix首页 | 论坛 | 博客
  • 博客访问: 371923
  • 博文数量: 50
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 641
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-09 22:35
个人简介

不怕你失败,就怕你爬不起来。

文章分类

全部博文(50)

文章存档

2014年(50)

我的朋友

分类: 嵌入式

2014-10-08 11:43:15

    当涉及到Qt的多窗口项目的时候,难免遇到多窗口的通信和管理,比如说,在主窗口创建一个子窗口,子窗口能够发消息给主窗口,并且要求同一时间只能打开一个子窗口;此外,当子窗口关闭时应该通知父窗口,此时父窗口才可以再次创建子窗口。类似的实现就像是QQ聊天窗口一样,当打开一个用户聊天窗口时,不能再次打开重复的用户窗口;当关闭此用户的聊天窗口时,才能再次打开。

    那么要怎么实现呢?

    还是新手的时候(尽管现在也还是半个菜鸟),我用了父子关系来管理,但是这样会造成子窗口不是顶级窗口的状况,这样当窗口很多的时候,就会很难看。

    后来学习了数据库,想想能不能用数据库来记录窗口的状态,根据数据库的值的变化来管理窗口。答案是可以的,但是工作量很大,不得已,又继续挖掘其他的办法。

    终于,在论坛上问了一些大神之后,才知道Qt的信号和槽同样可以在多窗口中应用,这也是Qt信号和槽的灵活便利的地方之一吧。
下面来介绍一下代码:

父窗口:

parent.h

  1. #ifndef PARENT_H
  2. #define PARENT_H

  3. #include <QDialog>
  4. #include <QtWidgets>
  5. #include <child.h>

  6. class Parent : public QDialog
  7. {
  8.     Q_OBJECT
  9. public:
  10.     Parent();
  11.     QLineEdit *lineEdit;
  12.     QLabel *pLabel;
  13.     QPushButton *childBtn;
  14.     QPushButton *qBtn;
  15.     Child *child; //子窗体
  16.     QHash<QString, Child*> hashChildWindow;//记录子窗口句柄的数据结构

  17. public slots:
  18.     void infoRecv(const QString &);  //消息接收槽函数
  19.     void childCreate();              //创建子窗体槽函数
  20.     void recvQuit(const QString &)//接收子窗口关闭槽函数
  21. };

  22. #endif //PARENT_H

parent.cpp

  1. #include "parent.h"

  2. Parent::Parent()
  3. {
  4.     setWindowTitle("Parent");

  5.     lineEdit = new QLineEdit;
  6.     pLabel = new QLabel("infoRecv: ");
  7.     childBtn = new QPushButton("childUi");
  8.     qBtn = new QPushButton("Quit");

  9.     QGridLayout *layout = new QGridLayout(this);
  10.     layout->addWidget(pLabel,0,0);
  11.     layout->addWidget(lineEdit,0,1);
  12.     layout->addWidget(childBtn,1,0);
  13.     layout->addWidget(qBtn,1,1);
  14.     this->resize(300,200);
  15.     connect(qBtn,SIGNAL(clicked()),this,SLOT(reject())); //关闭主窗体
  16.     connect(childBtn,SIGNAL(clicked()),this,SLOT(childCreate())); //创建子窗体

  17. }

  18. void Parent::childCreate()
  19. {
  20.     if(hashChildWindow.contains("child"))
  21.     {
  22.         qDebug() << "already open ... ...";
  23.     }
  24.     else
  25.     {
  26.         child = new Child();
  27.         hashChildWindow.insert("child", child);
  28.         connect(child,SIGNAL(infoSend(const QString &)),
  29.                 this,SLOT(infoRecv(const QString &))); //消息发送与接收
  30.         connect(child, SIGNAL(sendQuit(const QString &)),
  31.                 this, SLOT(recvQuit(const QString &)));//子窗口关闭接收
  32.         child->show();
  33.     }
  34. }

  35. void Parent::infoRecv(const QString &str)
  36. {
  37.     lineEdit->setText(str);
  38. }

  39. void Parent::recvQuit(const QString &str)
  40. {
  41.     if(hashChildWindow.contains(str))
  42.     {
  43.         hashChildWindow.remove(str);
  44.     }
  45. }

子窗口:

child.h

  1. #ifndef CHILD_H
  2. #define CHILD_H

  3. #include <QDialog>
  4. #include <QtWidgets>

  5. class Child : public QWidget
  6. {
  7.     Q_OBJECT
  8. public:
  9.     Child();
  10.     QLineEdit *lineEdit;
  11.     QLabel *pLabel;
  12.     QPushButton *tBtn;
  13.     QPushButton *qBtn;

  14. signals:
  15.     void infoSend(const QString &); //定义消息发送信号
  16.     void sendQuit(const QString &); //定义窗口关闭信号

  17. public slots:
  18.     void emit_signal_infosend();//Send按钮单击事件连接的槽函数,目的为发射infoSend信号
  19.     void emit_signal_sendQuit();//Quit按钮单击事件连接的槽函数,目的为发射sendQuit信号
  20. };


  21. #endif // CHILD_H

child.cpp

  1. #include "child.h"

  2. Child::Child()
  3. {
  4.     setWindowTitle("Child");

  5.     lineEdit = new QLineEdit;
  6.     pLabel = new QLabel("infoSend: ");
  7.     tBtn = new QPushButton("Send");
  8.     qBtn = new QPushButton("Quit");

  9.     QGridLayout *layout = new QGridLayout(this);
  10.     layout->addWidget(pLabel,0,0);
  11.     layout->addWidget(lineEdit,0,1);
  12.     layout->addWidget(tBtn,1,0);
  13.     layout->addWidget(qBtn,1,1);

  14.     this->resize(300,200);

  15.     connect(qBtn,SIGNAL(clicked()),this,SLOT(emit_signal_sendQuit()));
  16.     connect(tBtn,SIGNAL(clicked()),this,SLOT(emit_signal_infosend()));
  17. }

  18. void Child::emit_signal_infosend()
  19. {
  20.     const QString txt = lineEdit->text();
  21.     emit infoSend(txt);
  22. }

  23. void Child::emit_signal_sendQuit()
  24. {
  25.     emit sendQuit("child");
  26.     close();
  27. }

 
PS:
  以上代码仅供参考,最好为子窗口添加一个closeEvent来控制子窗口的关闭事件:

closeEvent

  1. void Child::closeEvent(QCloseEvent *event)
  2. {
  3.  emit sendQuit("child");
  4.  event->accept();
  5. }
阅读(8424) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~