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.hqwc.cn/news/704688.html

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

相关文章

详细分析Vue3中的reactive(附Demo)

目录 1. 基本知识2. 用法3. Demo 1. 基本知识 reactive 是一个函数&#xff0c;用于将一个普通的 JavaScript 对象转换为响应式对象 当对象的属性发生变化时&#xff0c;Vue 会自动追踪这些变化&#xff0c;并触发相应的更新 Vue2没有&#xff0c;而Vue3中有&#xff0c;为啥…

Springboot+MybatisPlus如何实现带验证码的登录功能

实现带验证码的登录功能由两部分组成&#xff1a;&#xff1a;1、验证码的获取 2、登录&#xff08;进行用户名、密码和验证码的判断&#xff09; 获取验证码 获取验证码需要使用HuTool中的CaptchaUtil.createLineCaptcha()来定义验证码的长度、宽度、验证码位数以及干扰线…

【2024华为HCIP831 | 高级网络工程师之路】刷题日记(18)

个人名片&#xff1a;&#x1faaa; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&a…

uniapp获取当前位置及检测授权状态——支持App、微信小程序

uniapp获取当前位置检测及定位权限——支持App、微信小程序 首先&#xff0c;祝天下母亲&#xff0c;节日快乐~ 文章目录 uniapp获取当前位置检测及定位权限——支持App、微信小程序效果图新增 兼容小程序方法manifest Tips&#xff1a; 上一篇介绍 App端 uniapp获取当前位置及…

C++ requires关键字简介

requires 是 C20 中引入的一个新关键字&#xff0c;用于在函数模板或类模板中声明所需的一组语义要求&#xff0c;它可以用来限制模板参数&#xff0c;类似于 typename 和 class 关键字。 requires关键字常与type_traits头文件下类型检查函数匹配使用&#xff0c;当requires后…

React渲染流程

在 React 渲染分为两个阶段&#xff0c;Render 和 Commit&#xff0c;Render 是修改 React 组件的状态&#xff0c;把需要更新的组件标记为待更新&#xff0c;在 Commit 阶段将待更新的组件进行渲染并最终更新到浏览器的 Dom 树中。 Render 阶段是可以并执行操作的&#xff0c…

【Image captioning】基于检测模型网格特征提取——以Sydeny为例

【Image captioning】基于检测模型网格特征提取——以Sydeny为例 今天,我们将重点探讨如何利用Faster R-CNN检测模型来提取Sydeny数据集的网格特征。具体而言,这一过程涉及通过Faster R-CNN模型对图像进行分析,进而抽取出关键区域的特征信息,这些特征在网格结构中被系统地…

【考研数学】准备开强化,更「张宇」还是「武忠祥」?

数一125学长前来回答&#xff0c;选择哪位老师的课程&#xff0c;这通常取决于你的个人偏好和学习风格&#xff01; 张宇老师和武忠祥老师都是非常有经验的数学老师&#xff0c;他们的教学方法各有特点。 张宇老师的教学风格通常被认为是通俗易懂&#xff0c;善于将复杂的概念…

国际化日期(inti)

我们可以使用国际化API自动的格式化数字或者日期&#xff0c;并且格式化日期或数字的时候是按照各个国家的习惯来进行格式化的&#xff0c;非常的简单&#xff1b; const now new Date(); labelDate.textContent new Intl.DateTimeFormat(zh-CN).format(now);比如说这是按照…

使用RN的kitten框架的日历组件的修改

官方网页地址 下面就是我参考官方封装的时间日期组件&#xff08;主要是功能和使用方法&#xff0c;页面粗略做了下&#xff0c;不好看勿怪&#xff09; import React, {useState} from react; import {StyleSheet, View, TouchableOpacity, SafeAreaView} from react-native; …

5 个免费使用 GPT-4o 的方法

5 个免费使用 GPT-4o 的方法 虽然距离 OpenAI 发布 GPT-4o 已过去一天&#xff0c;我仍然对 GPT-4o 感到震撼。Demo 中语音助手功能实在是太令人惊叹了——它咯咯的笑声、准确的语气感叹和歌唱方式让 Siri 和 Google Assistant 显得相形见绌。 虽然备受期待的语音助手功能还要…

【计算机毕业设计】springboot分类信息服务平台移动端的设计与实现

分类信息 服务平台设计的目的是为用户提供活动信息、活动记录等方面的平台。 与PC端应用程序相比&#xff0c;分类信息服务平台的设计主要面向于移动端&#xff0c;旨在为管理员和用户、商铺提供一个分类信息服务平台。用户可以通过Android及时查看活动信息等。 分类信息服务平…