简易CAD程序:Qt多文档程序的一种实现

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

实现思路说明

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

    #pragma once
    
    #include <QtWidgets/QApplication>
    
    
    //相当于MFC中CWinAppEx的派生类,
    class DemoApplication : public QApplication
    {
    	Q_OBJECT
    
    public:
    	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_OBJECT
    
    public:
    	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_OBJECT
    
    public:
    	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_OBJECT
    
    public:
    	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_OBJECT
    
    public:
    	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();
    }
    
    

运行演示

在这里插入图片描述

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt是一款跨平台的应用程序开发框架,可以用于实现多人视频会议功能并支持文档演示。 实现多人视频会议的关键是实时音视频传输和会议管理。Qt提供了一系列的多媒体以及网络通信的类库,可以很方便地实现音视频数据的采集、编码、传输和解码。通过使用Qt的音视频相关类,我们可以建立起多个参与者之间的音视频通信通道,实现多人视频会议的功能。 对于文档演示的支持,我们可以利用Qt的图形界面和文档处理类库来实现。可以将文档文件进行解析和显示,并在会议过程中进行同步显示。参与者可以通过Qt提供的界面控件和操作交互功能,对文档进行翻页、缩放、批注等操作。同时,Qt也提供了网络通信类库,可以将文档操作的数据进行实时传输和同步。 在会议管理方面,Qt的网络通信类库可以用于实现与服务器的通信,实现会议的创建、参与者的加入、离开以及会议状态的管理等功能。通过与服务器的通信,各个参与者的状态可以进行同步,保证会议的正常进行。 总的来说,Qt作为一款强大的跨平台应用程序开发框架,可以很好地支持多人视频会议功能的实现,并且可以辅助实现文档演示的功能。使用Qt可以使开发者快速地构建出稳定、高效的多人视频会议应用程序。 ### 回答2: Qt一种跨平台的应用程序开发框架,具有丰富的图形界面和多媒体功能。要实现多人视频会议并支持文档演示,可以借助Qt的网络和多媒体模块。 首先,需要建立一个服务器来管理多人视频会议的连接和数据传输。可以使用Qt的网络模块创建一个TCP或UDP服务器,监听来自多个客户端的连接请求。 当客户端连接到服务器时,服务器会为每个客户端创建一个视频流和音频流。可以使用Qt的多媒体模块来获取客户端的摄像头和麦克风数据,并将其编码为视频和音频流。 服务器需要将接收到的视频和音频流广播给其他客户端。可以使用Qt的网络模块将流数据发送给其他客户端,每个客户端可以使用Qt的多媒体模块来解码和播放接收到的流数据,实现多人视频会议。 同时,为了支持文档演示,可以使用Qt的图形界面模块创建一个文档展示窗口。该窗口可以显示当前演示的文档,并将其广播给其他客户端。服务器可以使用网络模块将文档数据发送给其他客户端,每个客户端可以使用Qt的图形界面模块来显示接收到的文档。 为了实现实时的多人视频会议和文档演示,需要注意网络延迟和带宽的限制。可以使用Qt的网络模块提供的相关接口来优化数据传输和处理,确保视频和音频的实时性和质量。 总之,通过使用Qt的网络和多媒体模块,可以实现一个支持多人视频会议和文档演示的应用程序。这个应用程序能够让多个用户在同一个会议中进行实时的视频和音频交流,并且可以共享和展示文档

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值