Qt多文档程序的一种实现

注:文中所列代码质量不高,但不影响演示我的思路

实现思路说明

  1. 实现DemoApplication
    相当于MFC中CWinAppEx的派生类,暂时没加什么功能。
    DemoApplication.h

    #pragma once#include <QtWidgets/QApplication>//相当于MFC中CWinAppEx的派生类,
    class DemoApplication : public QApplication
    {Q_OBJECTpublic:DemoApplication(int &argc, char **argv);~DemoApplication();};
    

    DemoApplication.cpp

    #include "DemoApplication.h"DemoApplication::DemoApplication(int &argc, char **argv): QApplication(argc, argv)
    {
    }DemoApplication::~DemoApplication()
    {
    }
  2. 实现DemoDocument
    相当与MFC的CDocument。DemoDocument保存了当前所有视图的指针(此处实际是DeomChildWindow*,因为DeomChildWindow与DeomView时1对1关系,根据DeomChildWindow可以获得DemoView指针,简化设计,就这样处理了),实现了增加视图addView、移除视图removeView、获取视图数量getViewCount等函数。
    DemoDocument.h

    #pragma once#include <QObject>
    #include <list>class DemoChildWindow;//相当与MFC的CDocument
    class DemoDocument : public QObject
    {Q_OBJECTpublic:DemoDocument(QObject *parent = 0);~DemoDocument();void addView(DemoChildWindow* pChildWindow);void removeView(DemoChildWindow* pChildWindow);int getViewCount() const;unsigned int getId() { return m_nId; }signals:void closedDocument(DemoDocument* pDocument);private:static unsigned int allocId();private:static unsigned int s_NextId;unsigned int m_nId = 0;std::list<DemoChildWindow*> m_viewList; //视图列表
    };

    DemoDocument.cpp

    #include "DemoDocument.h"unsigned int DemoDocument::s_NextId = 0;DemoDocument::DemoDocument(QObject *parent): QObject(parent)
    {m_nId = allocId();
    }DemoDocument::~DemoDocument()
    {
    }unsigned int DemoDocument::allocId()
    {if (DemoDocument::s_NextId == std::numeric_limits<unsigned int>::max()){DemoDocument::s_NextId = 0;}return ++DemoDocument::s_NextId;
    }void DemoDocument::addView(DemoChildWindow* pChildWindow)
    {m_viewList.push_back(pChildWindow);
    }void DemoDocument::removeView(DemoChildWindow* pChildWindow)
    {auto it = std::find(m_viewList.begin(), m_viewList.end(), pChildWindow);if (it != m_viewList.end() ){m_viewList.erase(it);}if (m_viewList.size() == 0){emit closedDocument(this);}
    }int DemoDocument::getViewCount() const
    {return int(m_viewList.size());
    }
  3. 实现DemoMainWindow
    相当于MFC中的CMainFrame,派生自CMDIFrameWndEx。此类new了一个QMdiArea对象,通过此对象实现多文档程序的通用功能,如切换窗口、层叠窗口、平铺窗口等。类DemoMainWindow直接管理了所有打开的文档,这点同MFC不一样,MFC是通过文档管理器、文档模版处理的,此处简化下,直接在DemoMainWindow中管理。此处我让DemoMainWindow负责新建、打开、关闭文档。
    DemoMainWindow.h

    #pragma once#include <QtWidgets/QMainWindow>
    #include <QMdiArea>
    #include <list>
    #include <memory>class DemoDocument;//相当于MFC中的CMainFrame,派生自CMDIFrameWndEx
    class DemoMainWindow : public QMainWindow
    {Q_OBJECTpublic:DemoMainWindow(QWidget *parent = Q_NULLPTR);virtual ~DemoMainWindow();DemoDocument* getActiveDocument() const;protected slots:void onSlotNewDocument();void onSlotClosedDocument(DemoDocument* pDocument );void onSlotNewWindow();private://创建文档的一个视图(DemoChildWindow-DeomView)void createNewWindow(DemoDocument* pDocument );private:QMdiArea* m_pMDIArea = nullptr;std::list<DemoDocument*> m_DocList; //文档列表
    };

    DemoMainWindow.cpp

    #include "DemoMainWindow.h"
    #include "DemoDocument.h"
    #include "DemoChildWindow.h"#include <QMdiSubWindow>
    #include <QMenuBar>DemoMainWindow::DemoMainWindow(QWidget *parent): QMainWindow(parent)
    {m_pMDIArea = new QMdiArea();this->setCentralWidget(m_pMDIArea);//void subWindowActivated(QMdiSubWindow * window)//菜单QMenu* pFileMenu = menuBar()->addMenu(QStringLiteral("文件"));QAction* pNewDocAction = new QAction(QStringLiteral("新建"), this);connect(pNewDocAction, SIGNAL(triggered()), this, SLOT(onSlotNewDocument()));pFileMenu->addAction(pNewDocAction);//窗口(实际需要动态添加到菜单栏中,即有视图窗口打开,就加入,否则就移除,此处暂未实现)QMenu* pWinMenu = menuBar()->addMenu(QStringLiteral("窗口"));QAction* pNewWinAction = new QAction(QStringLiteral("新建"), this);connect(pNewWinAction, SIGNAL(triggered()), this, SLOT(onSlotNewWindow()));pWinMenu->addAction(pNewWinAction);}DemoMainWindow::~DemoMainWindow()
    {for (auto pDoc : m_DocList){delete pDoc;}m_DocList.clear();
    }void DemoMainWindow::onSlotNewDocument()
    {auto pNewDoc = new DemoDocument();m_DocList.push_back(pNewDoc);createNewWindow(pNewDoc);connect(pNewDoc, SIGNAL(closedDocument(DemoDocument*)), this, SLOT(onSlotClosedDocument(DemoDocument*)));
    }void DemoMainWindow::onSlotClosedDocument(DemoDocument* pDocument)
    {auto it = std::find(m_DocList.begin(), m_DocList.end(), pDocument);if (it != m_DocList.end()){auto pDoc = *it;delete pDoc;m_DocList.erase(it);}
    }void DemoMainWindow::onSlotNewWindow()
    {auto pDocument = getActiveDocument();createNewWindow(pDocument);
    }//创建文档的一个视图(DemoChildWindow-DeomView)
    void DemoMainWindow::createNewWindow(DemoDocument* pDocument)
    {if (!pDocument){Q_ASSERT(false);return;}auto pChildWnd = new DemoChildWindow(pDocument);//自己new QMdiSubWindow时,必须设置Qt::WA_DeleteOnClose,参看文档//When you create your own subwindow, you must set the Qt::WA_DeleteOnClose widget //attribute if you want the window to be deleted when closed in the MDI area. //If not, the window will be hidden and the MDI area will not activate the next subwindow.//添加方式如下:
    //	QMdiSubWindow *pMdiSubWindow = new QMdiSubWindow;
    //	pMdiSubWindow->setWidget(pChildWnd);
    //	pMdiSubWindow->setAttribute(Qt::WA_DeleteOnClose);
    //	m_pMDIArea->addSubWindow(pMdiSubWindow);
    //	pMdiSubWindow->show();//这中方法更简单auto pMdiSubWindow = m_pMDIArea->addSubWindow(pChildWnd);pMdiSubWindow->setWindowTitle(QStringLiteral("文档%1:%2").arg(pDocument->getId()).arg(pDocument->getViewCount()));pMdiSubWindow->show();
    }DemoDocument* DemoMainWindow::getActiveDocument() const
    {auto pCurMdiSubWindow = m_pMDIArea->currentSubWindow();if (!pCurMdiSubWindow){return nullptr;}auto pChildWnd = dynamic_cast<DemoChildWindow*>(pCurMdiSubWindow->widget());if (!pChildWnd){Q_ASSERT(false);return nullptr;}return pChildWnd->GetDocument();
    }
  4. 实现DemoChildWindow
    相当于MFC中的ChildFrm,派生自CMDIChildWndEx, 与文档是n-1关系, 与DemoView时1-1关系。此类负责创建DemoView,并且包含了文档对象的指针。MFC中创建ChildFrm以及CView没那么直接,通过消息触发创建了CView,具体参看MFC即可,我此处就简化处理创建的过程。
    DemoChildWindow.h

    #pragma once#include <QWidget>class DemoDocument;
    class DemoView;//相当于MFC中的ChildFrm,派生自CMDIChildWndEx, 与文档是n-1关系, 与DemoView时1-1关系,
    class DemoChildWindow : public QWidget
    {Q_OBJECTpublic:DemoChildWindow(DemoDocument* pDoc, QWidget* parent = 0, Qt::WindowFlags f = 0);~DemoChildWindow();DemoDocument* GetDocument() const;protected:virtual void closeEvent(QCloseEvent * event) override;private:DemoDocument* m_pDoc;DemoView* m_pView;
    };

    DemoChildWindow.cpp

    #include "DemoChildWindow.h"
    #include "DemoView.h"
    #include "DemoDocument.h"
    #include <QVBoxLayout>DemoChildWindow::DemoChildWindow(DemoDocument* pDoc, QWidget *parent, Qt::WindowFlags flags): QWidget(parent, flags)
    {m_pDoc = pDoc;m_pView = new DemoView();m_pDoc->addView(this);auto pVBoxLayout = new QVBoxLayout();pVBoxLayout->addWidget(m_pView);this->setLayout(pVBoxLayout);
    }DemoChildWindow::~DemoChildWindow()
    {
    }DemoDocument* DemoChildWindow::GetDocument() const
    {return m_pDoc;
    }void DemoChildWindow::closeEvent(QCloseEvent * event)
    {m_pDoc->removeView(this);return QWidget::closeEvent(event);
    }
    
  5. 实现DemoView
    相当与MFC中的CView,在DemoView中仅显示了硬编码的文本字符串。
    DemoView.h

    #pragma once#include <QWidget>//相当与MFC中的CView
    class DemoView : public QWidget
    {Q_OBJECTpublic:DemoView(QWidget *parent = Q_NULLPTR);~DemoView();private://Ui::DemoView ui;
    };

    DemoView.cpp

    #include "DemoView.h"
    #include <QVBoxLayout>
    #include <QLabel>DemoView::DemoView(QWidget *parent): QWidget(parent)
    {auto pVBoxLayout = new QVBoxLayout();pVBoxLayout->addWidget(new QLabel(QStringLiteral("视图测试")));this->setLayout(pVBoxLayout);this->setMinimumSize(300, 200);
    }DemoView::~DemoView()
    {
    }
  6. main函数

    #include "DemoApplication.h"
    #include "DemoMainWindow.h"int main(int argc, char *argv[])
    {DemoApplication a(argc, argv);DemoMainWindow w;w.show();return a.exec();
    }

运行演示

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/12964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

医院预约挂号|基于Springboot+vue的医院预约挂号系统小程序的设计与实现(源码+数据库+文档)

医院预约挂号系统小程序 目录 基于Springboot&#xff0b;vue的医院预约挂号系统小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1小程序端 后台功能模块 4.2.1管理员功能 4.2.2医生功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选…

CCF-Csp算法能力认证, 202309-1坐标变换(其一)(C++)含解析

前言 推荐书目&#xff0c;在这里推荐那一本《算法笔记》&#xff08;胡明&#xff09;&#xff0c;需要PDF的话&#xff0c;链接如下 「链接&#xff1a;https://pan.xunlei.com/s/VNvz4BUFYqnx8kJ4BI4v1ywPA1?pwd6vdq# 提取码&#xff1a;6vdq”复制这段内容后打开手机迅雷…

音乐的力量

常听音乐的好处可以让人消除工作紧张、减轻生活压力、避免各类慢性疾病等等&#xff0c;其实这些都是有医学根据的。‍ 在医学研究中发现&#xff0c;经常的接触音乐节 奏、旋律会对人体的脑波、心跳、肠胃蠕动、神经感应等等&#xff0c;产生某些作用&#xff0c;进而促进身心…

2024护网在即,今年的护网招聘着实有点离谱了!

最近刷到条护网招聘的朋友圈&#xff0c;今年的护网待遇着实有点离谱了&#xff0c;日薪提到了1w&#xff0c;还是全款垫付&#xff1f;&#xff1f;&#xff1f;&#xff01;&#xff01; 我算是理解了“我们当年可没你现在这个条件”这句话。 先给大家科普下护网行动&#x…

景源畅信数字:做抖音切片的方法分享?

一提起抖音切片&#xff0c;很多人可能会想到那些让人眼前一亮的短视频。它们通常短小精悍&#xff0c;内容丰富多彩&#xff0c;能够迅速吸引观众的注意力。但是&#xff0c;如何制作出这样的切片视频呢?这就是我们今天要探讨的问题。 一、选材与剪辑 制作抖音切片&#xff0…

软考中级-软件设计师 (十一)标准化和软件知识产权基础知识

一、标准化基础知识 1.1标准的分类 根据适用的范围分类&#xff1a; 国际标准指国际化标准组织&#xff08;ISO&#xff09;、国际电工委员会&#xff08;IEC&#xff09;所制定的标准&#xff0c;以及ISO所收录的其他国际组织制定的标准。 国家标准&#xff1a;中华人民共和…

C++学习一(主要对cin的理解)

#include<iostream> int main() {int sum 0, value 0;//读取数据直到遇到文件尾&#xff0c;计算所有读入的值的和while (std::cin >> value){ //等价于sumsumvaluesum value;}std::cout << "Sum is :" << sum << std::endl;sum …

2023年国赛高教杯数学建模B题多波束测线问题解题全过程文档及程序

2023年国赛高教杯数学建模 B题 多波束测线问题 原题再现 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀速直线传播&#xff0c;在不同界面上产生反射&#xff0c;利用这一原理&#xff0c;从测量船换能器垂直向海底发射声波信号&#xff…

软件设计师笔记和错题

笔记截图 数据库 模式是概念模式 模式/内模式 存在概念级和内部级之间&#xff0c;实现了概念模式和内模式的互相转换 外模式/模式映像 存在外部级和概念级之间&#xff0c;实现了外模式和概念模式的互相转换。 数据的物理独立性&#xff0c; 概念模式和内模式之间的映像…

字符串_字符函数和字符串函数

C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组中。 字符串常量适用于那些对它不做修改的字符串函数。 目录 1.函数介绍 1.1strlen 1.1.1strlen函数的模拟实现 1.2strcpy 1.2.1st…

2024年5月16日 十二生肖 今日运势

小运播报&#xff1a;2024年5月16日&#xff0c;星期四&#xff0c;农历四月初九 &#xff08;甲辰年己巳月庚辰日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;猴、鼠、鸡 需要注意&#xff1a;牛、兔、狗 喜神方位&#xff1a;西北方 财神方位&#xff1a;…

英飞凌SiC模块为小米电动车提供动力

至2027年之际&#xff0c;SiC功率模块与裸片产品将荣耀登场&#xff0c;助力小米电动汽车新品SU7璀璨问世。英飞凌&#xff0c;这家业界翘楚&#xff0c;将倾其所能&#xff0c;为小米SU7 Max提供两颗HybridPACK Drive G2 CoolSiC 1200 V模块&#xff0c;如同给电动汽车的心脏注…

算法练习第22天|39. 组合总和、40.组合总和II

39. 组合总和 39. 组合总和 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/combination-sum/description/ 题目描述&#xff1a; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数…

char x[]---char*---string---sizeof

字符串数组 #include <iostream>int main(){char c_str[]"abcd";char c_str1[]{a,b,c,d};std::cout<<sizeof(c_str)<<std::endl;std::cout<<sizeof(c_str1)<<std::endl;return 0; } char*存储的字符串个数 char*字符串所占字节大小 c…

信创电脑|暴雨新增兆芯KX-7000处理器版本

IT世界 5 月 15 日消息&#xff0c;暴雨公司信创家族新上架了一款搭载兆芯KX-7000系列处理器、摩尔线程8GB 显卡、16G DDR5 内存以及 512G SSD 的新配置台式电脑主机。 兆芯 KX-7000 处理器采用开先的 8 核 Chiplet互联架构&#xff0c;最高频率3.7 GHz&#xff0c;拥有 32MB 的…

后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解

JDBC 简化JDBC的开发 JDBC仅仅是一套接口 是一套规范 Mybatis是持久层框架 用于简化JDBC的开发 使用Java语言操作关系型数据库的一套API 原始的JDBC程序 package com.bigdate.mybatis;import com.bigdate.mybatis.mapper.UserMapper; import com.bigdate.mybatis.pojo.Use…

容联云零代码平台容犀desk:重新定义坐席工作台

在数智化浪潮的推动下&#xff0c;企业亟待灵活适应市场变化、快速响应客户需求&#xff0c;同时还要控制成本并提升效率&#xff0c;传统的软件开发模式因开发周期长、成本高、更新迭代慢等问题&#xff0c;逐渐难以满足企业灵活多变的业务需求。 容犀Desk&#xff0c;观察到…

Vue.js的发展史(一)

Vue.js的发展史&#xff08;一&#xff09; 什么是Vue? Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发…

Spring Security实现用户认证二:前后端分离时自定义返回Json内容

Spring Security实现用户认证二&#xff1a;前后端分离时自定义返回Json内容 1 前后端分离2 准备工作依赖WebSecurityConfig配置类 2 自定义登录页面2.1 Spring Security的默认登录页面2.2 自定义配置formLogin 3 自定义登录成功处理器4 自定义登录失败处理器5 自定义登出处理器…

经济寒冬 | 品牌策划人还可以去哪些行业发展?

在这个经济寒冬下&#xff0c;咱们品牌策划人也需要考虑后路问题了。 随着市场竞争的加剧和消费者需求的不断变化&#xff0c;品牌策划人的工作不再只是简单的广告宣传和市场推广。 咱们需要重新思考自己的角色&#xff0c;寻找新的生存和发展之道。 当然&#xff0c;品牌策…