Qt|QWidget窗口支持旋转

功能实现:使用QWidget创建的窗口支持窗口旋转功能。

展示的示例中支持由水平方向旋转至垂直方向。至于其它角度旋转的问题,看完这篇文章后应该会很简单能实现的!

开发环境:win VS2019 + Qt 5.15.2

在实现之前也有想用使用 QPropertyAnimation类,用动画的方式实现,经过验证发现,动画类不支持在object中进行旋转操作,所以放弃!

所以,采用广大博友推荐的方式:QGraphicsView控制场景中的子窗口进行旋转。

那么重点:如何让QWidget嵌入到QGraphicsView中并进行旋转。

首先,分享下实现出来的效果,如果需要这样的功能,大家可以继续看下去了~

当前的GIF效果只是展示了旋转功能的使用,具体项目中的业务,大家可以根据自己的情况进行修改,但是核心不变。

功能实现

开发环境:windows环境下 VS2019+5.15.2

当前窗口已经使用QWidget开发完成,此时,使用QGraphicsScene类将所有的窗口添加进去,能够快速进行旋转。

在当前demo中旋转父窗口是:QtRotateWidget,并且在该类中所有的子窗口需要使用QWidget继承实现,不要使用QDialog作为父类,否则无法进行控制!

demo涉及的子类包括:

QParentContentWidget:当前类属于父类,承载所有子窗口,相当于画布,每次旋转的时候,只是旋转的是子窗口的位置。

1:创建旋转画布

在QParentContentWidget窗口中Qt Designer中拖出来"graphicsView"控件,用于承载旋转画布。

1.1:设置视图区域

下面代码表示视图的大小与窗口大小一致。

cpp 复制代码
int nWidgetW = this->rect().width();
int nWidgetH = this->rect().height();
ui.graphicsView->setGeometry(0, 0, nWidgetW, nWidgetH);
ui.graphicsView->setFixedSize(nWidgetW, nWidgetH);

1.2:视图绑定场景

为了方便查看,给场景设置了一个背景色

cpp 复制代码
//创建视图
QSize sizeView = ui.graphicsView->size();
m_pScene = new QGraphicsScene(this);
m_pScene->setSceneRect(0, 0, sizeView.width(), sizeView.height());
m_pScene->setBackgroundBrush(QColor(255, 0, 0));
ui.graphicsView->setScene(m_pScene);

到这里,会有一个这样的问题:设置了视图与窗口大小相同时,为什么视图会出现滚动条

该如何解决这个问题呢?

我们需要给视图graphicsView隐藏垂直和水平滚动条,并且禁用滚动条,就好了

cpp 复制代码
//禁用滚动条
ui.graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui.graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui.graphicsView->horizontalScrollBar()->blockSignals(true);
ui.graphicsView->verticalScrollBar()->blockSignals(true);

此时,运行代码就会发现,不会再出现滚动条了!

2:创建子窗口

在前面我已经提到过,想要让窗口同步旋转,必须在创建窗口时,使其父类是:QWidget。因为QDialog窗口时阻塞的,对于一些实时弹出的窗口,每次在exe()之前都需要计算位置,很麻烦,不如QWidget的子类好控制。

下面,就以QChildWidget_Title类为例子,进行讲解。

创建出子类后,想要让子窗口随着父窗口的变化而变化,就需要在子类中响应"resizeEvent"函数。

cpp 复制代码
virtual void resizeEvent(QResizeEvent* event);


//实现
void QChildWidget_Title::resizeEvent(QResizeEvent* event)
{
	QWidget::resizeEvent(event);
    //根据新的窗口的宽度、高度,修改当前窗口中的控件
	this->UpdateControlRect(event->size().width(), event->size().height());
}

3:子窗口绑定旋转

子窗口被创建后,接下来就需要在视图中进行绑定。

3.1:添加需要展示的子窗口

在QParentContentWidget类中添加需要展示的子窗口。

cpp 复制代码
//创建,标题窗口
m_pTitleWidget = new QChildWidget_Title;

注意:在平时创建子窗口时,都会将父指针传入到构造中,此时,需要注意了,想要将子窗口绑定场景中,在创建子窗口时,不需要传入父指针。

3.2:将子窗口添加到场景中

cpp 复制代码
m_pProxyTitle = m_pScene->addWidget(m_pTitleWidget); //设置:标题栏

3.3:父窗口旋转

cpp 复制代码
void QParentContentWidget::ChangeScreenRotationStyle(bool bUseRotate)
{
	QSize sizeView = ui.graphicsView->size();
	int nNewWidth = 0, nNewHeight = 0;
	switch (m_enumWidgetStyle)
	{
	case WidgetStyle_Horizontal: //水平风格
	{
		if (bUseRotate == true)
		{
			ui.graphicsView->rotate(90);
		}
		nNewWidth = sizeView.width();
		nNewHeight = sizeView.height();
	}
		break;
	case WidgetStyle_Vertical: //垂直风格
	{
		if (bUseRotate == true)
		{
			ui.graphicsView->rotate(-90);
		}
		nNewWidth = sizeView.height();
		nNewHeight = sizeView.width();
	}
		break;
	}

	m_pScene->setSceneRect(0, 0, nNewWidth, nNewHeight);//设置原点和scene大小
	//设置:标题栏
	m_pProxyTitle->setGeometry(QRectF(0, 0, nNewWidth, 50));
	//设置:详情按钮
	int nBtnDetailsLeft = nNewWidth - 60 - 40;
	m_pProxyBtnDetails->setGeometry(QRectF(nBtnDetailsLeft, 100, 60, 60));
	//设置:提示窗口(窗口固定大小是:400*200)
	int nTipsLeft = (nNewWidth - 400) / 2;
	int nTipsTop = (nNewHeight - 200) / 2;
	m_pProxyTips->setGeometry(QRectF(nTipsLeft, nTipsTop, 400, 200));
	//设置:编辑内容窗口(窗口固定大小是:600*500)
	int nEditLeft = (nNewWidth - 600) / 2;
	int nEditTop = (nNewHeight - 500) / 2;
	m_pProxyEdit->setGeometry(QRectF(nEditLeft, nEditTop, 600, 500));
}

3.4:销毁移出

在析构父窗口时,需要删除场景,此时应该先将子窗口进行移出,再进行销毁

cpp 复制代码
QParentContentWidget::~QParentContentWidget()
{
	//将所有的视图移出Scene中
	m_pScene->removeItem(m_pProxyBtnDetails); //按钮详情
	m_pScene->removeItem(m_pProxyTitle); //标题栏
	m_pScene->removeItem(m_pProxyTips); //错误提示框
	m_pScene->removeItem(m_pProxyEdit); //编辑窗口

	//删除所有子控件
	if (m_pTipsWidget)
	{
		delete m_pTipsWidget;
		m_pTipsWidget = nullptr;
	}
	if (m_pTitleWidget)
	{
		delete m_pTitleWidget;
		m_pTitleWidget = nullptr;
	}
	if (m_pEditWidget)
	{
		delete m_pEditWidget;
		m_pEditWidget = nullptr;
	}
	if (m_btnDetails)
	{
		delete m_btnDetails;
		m_btnDetails = nullptr;
	}

	delete m_pScene; //删除视图
}

以上就是使用graphicsView控件进行窗口旋转的功能了,如果有需要的,可以从以下链接中下载哟~

旋转QWidget窗口

我是糯诺诺米团,一名C++程序媛~

相关推荐
zhangfeng113312 分钟前
python 数据分析 单细胞测序数据分析 相关的图表,常见于肿瘤免疫微环境、细胞亚群功能研究 ,各图表类型及逻辑关系如下
开发语言·python·数据分析·医学
Sylvia-girl19 分钟前
Java---IDEA
java·开发语言·intellij-idea
Z_W_H_25 分钟前
【Springboot】Bean解释
java·开发语言
L_autinue_Star2 小时前
手写vector容器:C++模板实战指南(从0到1掌握泛型编程)
java·c语言·开发语言·c++·学习·stl
元气小嘉2 小时前
前端技术小结
开发语言·前端·javascript·vue.js·人工智能
励志的大鹰哥2 小时前
V少JS基础班之第七弹
开发语言·javascript·ecmascript
AI360labs_atyun3 小时前
Java在AI时代的演进与应用:一个务实的视角
java·开发语言·人工智能·科技·学习·ai
凤年徐3 小时前
【数据结构与算法】203.移除链表元素(LeetCode)图文详解
c语言·开发语言·数据结构·算法·leetcode·链表·刷题
nbsaas-boot4 小时前
多租户架构下的多线程处理实践指南
java·开发语言·spring
无小道4 小时前
c++--typedef和#define的用法及区别
c语言·开发语言·汇编·c++