IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Qt模仿VS停靠窗口(一) -> 正文阅读

[C++知识库]Qt模仿VS停靠窗口(一)

前言
众所周知,停靠窗口可以实现任意拖动效果,本文重点在于如何利用Qt制作与Visual Studio相似的带有停靠方向标及停靠区域预览的的停靠窗口框架。
效果图
在这里插入图片描述
功能
1、鼠标在中间方向标:叠加窗口
2、鼠标在上下左右方向标:分割目标窗口,并紧挨着目标窗口周边位置添加新窗口
3、鼠标在内部最上下左右方向标:目标窗口所在的最上下左右位置添加新窗口
4、鼠标在外部最上下左右方向标:程序主窗口的最上下左右位置添加新窗口
5、鼠标在Tab位置上:在当前所在tab页位置插入新窗口
6、鼠标在Tab最右侧位置上:在tab页尾部添加新窗口
注释:Dock停靠优先级:某些情况下,外部最上下左右方向的方向标会和目标窗口方向标重叠,此时遵循 中间停靠优于外部停靠、方向标停靠优于tab页停靠的原则。

部分头文件

#pragma once

#include <QWidget>
#include <QPaintEvent>
#include "QWHDockWidget.h"

class QMainWindow;
class QTabWidget;
class QDockWidget;
class QSplitter;

class QWHTabWidgetMask : public QWidget
{
	Q_OBJECT

public:
	enum Area
	{
		None,Top, Right, Bottom, Left, TopMore, RightMore, BottomMore, LeftMore, Center, TopMost, RightMost, BottomMost, LeftMost
	};

	QWHTabWidgetMask();
	~QWHTabWidgetMask();

	static QWHTabWidgetMask *getInstance();
	// 设置程序主窗口
	void setMainWindow(QMainWindow *mainWindow);
	// 创建停靠窗口
	QWHDockWidget *createDockWidget(QWHDockWidget::AreaMode areaMode, const QString &windowTitle = "");
	// 创建分裂器(水平分裂)
	QSplitter *createSplitter();
	// 创建分裂器(由参数orientation决定分裂方向)
	QSplitter *createSplitter(Qt::Orientation orientation);
	// 设置程序主分裂器
	void setMainSplitter(QSplitter *splitter);
	// 设置目标窗口(接收方)
	void setTargetWidget(QTabWidget *widget);
	// 设置当前页索引(鼠标移入当前页 或 鼠标移入中心方向标)
	void setCurTabIndex(int index);
	// 设置鼠标按下的停靠窗口(准备移动的窗口)
	void setMousePressed(QWHDockWidget *moveDockWidget);
	// 设置鼠标释放
	void setMouseReleased();

	// 获取停靠窗口推荐最小尺寸
	QSize minimumSizeHint() const override;
	// 获取鼠标按下的停靠窗口(准备移动或正在移动的窗口)
	QDockWidget *moveDockWidget();
	// 获取程序主分裂器
	QSplitter *mainSplitter();
	// 获取程序主窗口
	QMainWindow *mainWindow();

protected:
	void paintEvent(QPaintEvent *event);

private:
	// 获取指定索引的边界路径
	QPainterPath tabWidgetBorderPath(QTabWidget *tabWidget, int tabIndex);
	// 绘制主停靠窗口的指示器
	void drawMainDockIndicator();
	// 绘制次停靠窗口的指示器
	void drawMinorDockIndicator();
	// 检查鼠标所在方向标区域
	Area checkArea(QPoint globalPos);

signals:
	// 创建停靠窗口
	void dockWidgetAdded(QWHDockWidget *newDockWidget);

private:
	QMainWindow *m_mainWindow;
	QSplitter *m_mainSplitter;
	QWHDockWidget *m_moveDockWidget;
	QTabWidget *m_targetWidget;
	QList<QWHDockWidget *> m_listDockWidgets;

	int m_tabIndex;
	QColor m_borderColor;
	QColor m_bgColor;

	QRect m_centerRect;	// 中心矩形
	QRect m_topRect, m_rightRect, m_bottomRect, m_leftRect;	// 四个方位矩形(紧挨着中心矩形)
	QRect m_topMoreRect, m_rightMoreRect, m_bottomMoreRect, m_leftMoreRect;	// 更加靠边四个方位矩形(紧挨着四个方位矩形)
	QRect m_topMostRect, m_rightMostRect, m_bottomMostRect, m_leftMostRect;	// 最靠边四个方向矩形(紧挨着主窗口四边)

	QPixmap m_centerPixmap;
	QPixmap m_topPixmap, m_rightPixmap, m_bottomPixmap, m_leftPixmap;
	QPixmap m_topMostPixmap, m_rightMostPixmap, m_bottomMostPixmap, m_leftMostPixmap;

	QPixmap m_centerPixmapHover;
	QPixmap m_topPixmapHover, m_rightPixmapHover, m_bottomPixmapHover, m_leftPixmapHover;
	QPixmap m_topMostPixmapHover, m_rightMostPixmapHover, m_bottomMostPixmapHover, m_leftMostPixmapHover;
};

测试代码

TestVSWindow::TestVSWindow(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
	QWHTabWidgetMask::getInstance()->setMainWindow(this);
	
	// 测试左侧停靠窗体
	QWHDockWidget *dockWidget = QWHTabWidgetMask::getInstance()->createDockWidget(QWHDockWidget::Mode_Minor, "总tab");
	QSplitter *splitter = QWHTabWidgetMask::getInstance()->createSplitter();
	splitter->addWidget(dockWidget);
	dockWidget->setFloating(false);
	
	QWidget *widget1 = new QWidget();
	widget1->setMinimumSize(200, 100);
	widget1->setStyleSheet("background-color: green;");
	dockWidget->tabWidget()->addTab(widget1, "第一页");
	QWidget *widget2 = new QWidget();
	widget2->setMinimumSize(200, 100);
	widget2->setStyleSheet("background-color: green;");
	dockWidget->tabWidget()->addTab(widget2, "第二页");
	QWidget *widget3 = new QWidget();
	widget3->setMinimumSize(200, 100);
	widget3->setStyleSheet("background-color: green;");
	dockWidget->tabWidget()->addTab(widget3, "第三页");

	// 测试中间停靠窗体
	QWHDockWidget *dockWidgetCenter = QWHTabWidgetMask::getInstance()->createDockWidget(QWHDockWidget::Mode_Main, "总tabCenter");
	splitter->addWidget(dockWidgetCenter);
	dockWidgetCenter->setFloating(false);
	
	QWidget *widgetCenter1 = new QWidget();
	widgetCenter1->setMinimumSize(200, 100);
	widgetCenter1->setStyleSheet("background-color: rgb(255, 174, 201);");
	dockWidgetCenter->tabWidget()->addTab(widgetCenter1, "第一页Center");
	QWidget *widgetCenter2 = new QWidget();
	widgetCenter2->setMinimumSize(200, 100);
	widgetCenter2->setStyleSheet("background-color: rgb(255, 174, 201);");
	dockWidgetCenter->tabWidget()->addTab(widgetCenter2, "第二页Center");
	QWidget *widgetCenter3 = new QWidget();
	widgetCenter3->setMinimumSize(200, 100);
	widgetCenter3->setStyleSheet("background-color: rgb(255, 174, 201);");
	dockWidgetCenter->tabWidget()->addTab(widgetCenter3, "第三页Center");

	// 测试右侧停靠窗体
	QWHDockWidget *dockWidget2 = QWHTabWidgetMask::getInstance()->createDockWidget(QWHDockWidget::Mode_Minor, "总tab2");
	splitter->addWidget(dockWidget2);
	dockWidget2->setFloating(false);

	QWidget *widget12 = new QWidget();
	widget12->setMinimumSize(200, 100);
	widget12->setStyleSheet("background-color: gray;");
	dockWidget2->tabWidget()->addTab(widget12, "第一页2");
	QWidget *widget22 = new QWidget();
	widget22->setMinimumSize(200, 100);
	widget22->setStyleSheet("background-color: gray;");
	dockWidget2->tabWidget()->addTab(widget22, "第二页2");
	QWidget *widget32 = new QWidget();
	widget32->setMinimumSize(200, 100);
	widget32->setStyleSheet("background-color: gray;");
	dockWidget2->tabWidget()->addTab(widget32, "第三页2");

	QWHTabWidgetMask::getInstance()->setMainSplitter(splitter);
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-16 12:51:59  更:2022-01-16 12:52:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:34:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码