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++程序媛~

相关推荐
Scott9999HH8 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社9 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海9 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖10 小时前
JDK 26 新特性详解
java·开发语言
马优晨10 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区12 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大13 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai13 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜13 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa13 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio