简易CAD程序: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/bicheng/13728.shtml

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

相关文章

以太坊(3)——智能合约

智能合约 首先明确一下几个说法&#xff08;说法不严谨&#xff0c;为了介绍清晰才说的&#xff09;&#xff1a; 全节点矿工 节点账户 智能合约是基于Solidity语言编写的 学习Solidity语言可以到WFT学院官网&#xff08;Hello from WTF Academy | WTF Academy&#xff09;…

以x为界,分隔链表为两个分区,各分区内元素相对位置不变

题目描述&#xff1a; 题目思路&#xff1a; 1.设置两个头指针表示两个分区&#xff0c;并对每个分区设置相对于的遍历指针&#xff0c;指向分区链表链尾 2.设置原链表的遍历指针&#xff0c;判断指针所指元素是否小于目标值x&#xff0c;小于的话将结点添加到第一个分区末尾…

C# 中combobox 控件初始化

怎么获取绑定数据的combobox的选中值及选中text 1、绑定combobox的代码如下&#xff1a; DataTable LDT_CodeType Models.MoCodefile.GetCodeType(); if (LDT_CodeType ! null) { cboxCtype.DataSource LDT_CodeType; cboxCtype.DisplayMember codetypename; cboxCtype.Val…

搭建电商电子商务平台有哪些好用的电商API数据采集接口?

电商API接口主要用于帮助开发者将电商功能集成到自己的应用程序中&#xff0c;实现诸如商品检索、商品价格数据获取、订单处理、支付、物流跟踪等功能。以下是一些常用的电商API接口提供商&#xff1a; 主流电商平台API&#xff1a; 淘宝开放平台&#xff1a;提供淘宝、天猫、…

探索Ollama——入门:如何在本地环境中搭建和自定义大型语言模型

探索Ollama——入门&#xff1a;如何在本地环境中搭建和自定义大型语言模型 介绍Ollama 在当今快速发展的人工智能时代&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已经成为技术前沿的热点话题。Ollama&#xff0c;作为一个开创性的工具&#xff0c;使得开发者能够…

ngnix 入门 二,docker启动nginx, 安装ssl 证书,使用配置文件,映射后端服务 ,提供给前端项目访问

搭建生产环境真不是人做的事&#xff0c;特别是对于一知半解的人。仅以此文献给各位技术人 说一下背景&#xff1a;项目前后端分离&#xff0c;前端 vue3 、小程序端 &#xff0c;后端 go 提供服务。 微信小程序需要使用 https 请求。 这就必须让我们想到nginx 了 想要达到的…

MySQL学习之DQL语句(数据查询语言)

准备SQL CREATE TABLE student ( id int, -- 编号 name varchar(20), -- 姓名 age int, -- 年龄 sex varchar(5), -- 性别 address varchar(100), -- 地址 math int, -- 数学 english int -- 英语 );INSERT INTO student(id,NAME,age,sex,address,math,english) VALUES (1,…

LeetCode88.合并两个有序数组

题目链接&#xff1a; 88. 合并两个有序数组 - 力扣&#xff08;LeetCode&#xff09; 分析&#xff1a;普通的数组合并&#xff0c;这里还可以提供两个其它思路。可以用最笨的办法&#xff0c;把nums2的每个元素都移动到nums1里面&#xff0c;然后做排序&#xff0c;直接用s…

【UE5.1 角色练习】02-添加慢走、快速跑、蹲伏功能

目录 前言 步骤 一、慢走 二、快速跑 三、蹲伏 前言 在上一篇文章基础上&#xff08;【UE5.1 角色练习】01-使用小白人蓝图控制商城角色移动&#xff09;继续实现角色的慢走、快速跑以及蹲伏功能 步骤 一、慢走 1. 打开项目设置&#xff0c;添加一个操作映射&#x…

思维导图-VPN

浏览器集成了受信任的机构的证书

linux---信号的捕捉和处理

提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、信号 可以简单理解为信号是一个进程给另一个信号发消息&#xff0c;进程收到对应的信号就执行对应的方法&#xff0c;linux信号可以分为实时信号和非实时信号 1-31为非实时信号&#xff0c;34-64为…

猫狗分类识别④滤波去噪

一、依赖库 pip install opencv-python 二、滤波去噪说明 中值滤波和高斯滤波各有优缺点&#xff0c;哪种滤波方法更好取决于具体的应用场景和图像中的噪声类型。中值滤波对于去除椒盐噪声&#xff08;即黑白点噪声&#xff09;特别有效&#xff0c;因为它通过取邻域像素的中…

php抖音详情和关键词搜索api

抖音详情和关键词搜索的 API 可以通过抖音提供的开放平台来获取。以下是使用 PHP 实现的示例代码&#xff1a; 获取抖音视频详情 API&#xff1a; 获取Key和secret请移步 <?php$accessToken YOUR_ACCESS_TOKEN; // 替换为自己的 access_token $itemId YOUR_ITEM_ID; /…

TCP为什么要三次握手,为什么?

TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议。为了实现可靠数据传输&#xff0c;TCP 协议的通信双方&#xff0c;都必须维护一个序列号&#xff0c;以标识发送出去的数据包中&…

Typescript高级: 深入理解工厂函数类型

工厂函数类型 代表任意一个类的构造函数【等价JS的构造函数】的函数类型在TS中无法使用 new 来直接实例化一个 function现在通过几个小case来测试下这种类型 1 &#xff09;模拟一个动物的行为接口(简单) 创建几个实现了这个接口的类来展示接口的用途和如何使用它 下面是一个…

计算机精选期刊特辑

文章目录 一、征稿简介二、合作期刊三、投稿咨询四、咨询 一、征稿简介 艾思科蓝依托互联网信息与数据库技术、整合渠道与合作资源&#xff0c;提供EI/SCI/SCIE/SSCI期刊论文的内容审查、发表支持等服务。艾思科蓝与多所知名出版社达成战略合作关系&#xff0c;持续开展合作征…

利用神经网络学习语言(一)——自然语言处理的基本要素

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文涉及到的代码链接如下&#xff1a;regression2chatgpt/ch10_rnn/tokenizer.ipynb 本系列文章将深入探讨一种应用广泛的神经…

syncthing文件夹同步与版本管理

1 前言 syncthing可以用来同步文件夹里的所有文件&#xff0c;并且有不错的版本管理&#xff0c;基本每次更改文件&#xff0c;20-40秒就被扫描到了&#xff0c;非常丝滑&#xff1b;这次以此来同步obsidian的插件和文件&#xff0c;达到多端同步&#xff1b; 我家里有一台台…

Android HAL到Framework

一、为什么需要Framwork? Framework实际上是⼀个应⽤程序的框架&#xff0c;提供了很多服务&#xff1a; 1、丰富⽽⼜可扩展的视图&#xff08;Views&#xff09;&#xff0c; 可以⽤来构建应⽤程序&#xff0c;它包括列表&#xff08;lists&#xff09;&#xff0c;⽹格&am…

闲话 .NET(4):为什么要跨平台?

前言 .NET Core 有一个关键词就是跨平台&#xff0c;为什么要跨平台呢&#xff1f;Windows 操作系统不香吗&#xff1f;今天我们来聊聊这个 原因一&#xff1a;安全考虑 Windows OS 是闭源的&#xff0c;而 Linux 是开源的&#xff0c;因此有些公司的技术负责人就认为 Linux…