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

相关推荐
奔跑吧邓邓子12 分钟前
【Python爬虫(34)】Python多进程编程:开启高效并行世界的钥匙
开发语言·爬虫·python·多进程
Heris9939 分钟前
2.22 c++练习【operator运算符重载、封装消息队列、封装信号灯集】
开发语言·c++
----云烟----40 分钟前
C/C++ 中 volatile 关键字详解
c语言·开发语言·c++
yuanpan1 小时前
23种设计模式之《组合模式(Composite)》在c#中的应用及理解
开发语言·设计模式·c#·组合模式
BanLul1 小时前
进程与线程 (三)——线程间通信
c语言·开发语言·算法
十八朵郁金香1 小时前
【JavaScript】深入理解模块化
开发语言·javascript·ecmascript
Hello.Reader1 小时前
深入理解 Rust 的 `Rc<T>`:实现多所有权的智能指针
开发语言·后端·rust
程序员阿鹏1 小时前
jdbc批量插入数据到MySQL
java·开发语言·数据库·mysql·intellij-idea
yoona10201 小时前
Rust编程语言入门教程(八)所有权 Stack vs Heap
开发语言·后端·rust·区块链·学习方法
莲动渔舟1 小时前
国产编辑器EverEdit - 在编辑器中对文本进行排序
java·开发语言·编辑器