范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Qt无边框窗体最大化时支持拖拽还原

  一、概述
  用Qt进行开发界面时,既想要实现友好的用户交互又想界面漂亮,那么自定义界面就必不可少。其中有一个操作就是是我们每一个Qter开发者都要会的,而且是经常进行的。
  Qt::FramelessWindowHint这个属性想必大家都使用过,有些同学可能对这个属性很了解,也用的是炉火纯青,今天我们也来说说这个属性。
  关于这个无边框属性网上也有一些文章,有些谈论的是bug,当然了这是针对不同os而言,也有些是跟其他第三方库混合使用时的问题。可是问题归问题,想要实现自定义的优秀界面这个属性也是必不可少的。
  今天我们就来实现一个无边框窗体最大化时,支持拖拽标题栏进行还原的功能。
  无边框窗体支持缩放、移动这些不属于本篇文章的内容,本篇文章主要讲解怎么实现最大化时拖拽标题栏进行还原窗体,本篇文章的代码依赖于博主之前封装的一个拖拽代理类。 二、效果展示
  如效果图所示,做了一个简单的事例,双击标题栏窗体最大化,这个时候如果进行标题栏拖拽,当鼠标按下并移动一段距离时窗体恢复normal状态。
  恢复normal状态下的窗体仍然支持放大和缩小,有接口可以设置。
  三、demo制作
  demo的制作过程还是比较简单的,分为如下几步 1、设计窗体
  通过desinger设计器我们拖拽了一个大致窗体内容,为了更好的展示效果,标题栏加上了icon和背景色
  2、双击放大
  鼠标双击标题栏放大这个功能实现起来方法也比较多,这里博主选择了代码量最少并且实现起来最简单的方式,直接把标题栏的事件循环安装到了主窗体上。 ui.widget->installEventFilter(this);
  接下来我们就需要重写主窗口的eventFilter函数即可 bool DragWidget::eventFilter(QObject * watched, QEvent * event) { 	if (watched == ui.widget) 	{ 		if (event->type() == QEvent::MouseButtonDblClick) 		{ 			if (isMaximized()) 			{ 				showNormal(); 				m_handler.setWidgetResizable(true); 				m_handler.setWidgetMovable(true); 			} 			else 			{ 				showMaximized(); 				m_handler.setWidgetResizable(false); 				m_handler.setWidgetMovable(false); 			} 		} 	}  	return QWidget::eventFilter(watched, event); }
  细心的同学就会发现代码里有一个m_handler变量,这个类就是博主之前自己封装的一个拖拽代理,通过接口可以设置被代理的窗体,并设置需要代理哪些行为。
  本篇文章中所演示的事例代码,我们代理了主窗口上标题栏部分的移动事件和整个窗体的缩放事件,设置代码如下所示 m_handler.activateOn(this); m_handler.useLocalMoveabled(true); m_handler.addLocalWidget(ui.widget); m_handler.setMaximumMove(true, true);
  拖拽代理类内容比较多,本篇文章暂不讲解。 四、拖拽
  为了更好的理解本篇文章,这里需要把拖拽代理类的头文件放出来,这样更有利于大家理解。
  接口都比较简单,代码中也有注释,大家自行阅读。 class WidgetResizeHandler : public QObject {  public: 	explicit WidgetResizeHandler(QObject* parent = 0); 	~WidgetResizeHandler();  public: 	void activateOn(QWidget * topLevelWidget);//添加topLevelWidget事件代理 	void removeFrom(QWidget * topLevelWidget);//移除topLevelWidget事件代理  	Qt::CursorShape CursorShape(QWidget * widget);  	//窗口移动 default:true 	void setWidgetMovable(bool movable); 	bool isWidgetMovable();  	//大小可变 default:true 	void setWidgetResizable(bool resizable); 	bool isWidgetResizable();  	// 橡胶式窗口移动 default:false 	void useRubberBandOnMove(bool use); 	bool isUsingRubberBandOnMove();  	//橡胶式修改大小 default:false 	void useRubberBandOnResize(bool use); 	bool isUsingRubberBandOnResisze();  	void setBorderWidth(int newBorderWidth); 	int borderWidth();  	//局部可移动 	void useLocalMoveabled(bool use); 	void addLocalWidget(QWidget *);  	//最大化时支持拖拽 参数2表示是否可放大缩小 	void setMaximumMove(bool move, bool resize = false);  protected: 	virtual bool eventFilter(QObject * obj, QEvent * event) Q_DECL_OVERRIDE;  private: 	WidgetResizeHandlerImpl * d_ptr; };
  值得注意的是最后一个setMaximumMove接口,他就是我们今天的猪脚-是否支持最大化时拖拽。当我们设置了这个接口后,窗体最大化时也就能进行拖拽,并还原到之前的normal状态。
  文章第三小节讲解demo时,说过主窗体已经被代理拖拽类进行了事件代理,那么主窗体的所有事件首先都会传递给这个代理类,这里我们需要重点关注下鼠标按下时移动事件。 void WidgetData::handleMouseMoveEvent(QMouseEvent* event) { 	if (mLeftButtonPressed) 	{ 		if (d_ptr->mWidgetResizable && mPressedMousePos.onEdges) 		{ 			resizeWidget(event->globalPos()); 		} 		else if (d_ptr->mWidgetMovable) 		{ 			moveWidget(event->globalPos()); 		} 		else if (d_ptr->mMaxMovable) 		{ 			if (mWidget->isMaximized() && TryMoveWidget(event)) 			{ 				d_ptr->mWidgetMovable = true; 				//d_ptr->mWidgetResizable = true; 			} 		} 	} 	else if (d_ptr->mWidgetResizable) 	{ 		updateCursorShape(event->globalPos()); 	} }
  这段代码包含有其他缩放窗体和正常移动的逻辑,最大化时支持移动的逻辑应该不难找木九十TryMoveWidget这个函数,该函数中我们进行了充分的逻辑判断,一旦触发了窗体移动,那么我们把mWidgetMovable变量置为true,下一次鼠标按下移动事件就会触发正常的拖拽逻辑。
  仔细思考上边一段话,其中有2个关键信息 触发窗体移动,并还原到之前的normal状态 进行了第一步后,需要把mWidgetMovable变量置为true,之后走正常的窗体移动流程
  窗体移动
  尝试移动窗体,当鼠标当前位置距离鼠标按下时的距离大于20px时,进行窗体还原操作,并返回true,代表窗体已经被重置到normal态。 bool WidgetData::TryMoveWidget(QMouseEvent* event) { 	QPoint distance = event->globalPos() - mDragPos; 	int length = distance.manhattanLength(); 	if (length > 20) 	{ 		QRect rect = mWidget->normalGeometry(); 		int desX = mDragPos.x() * rect.width() / mWidget->geometry().width(); 		int desY = mDragPos.y(); 		rect.moveTopLeft(event->globalPos() - QPoint(desX, desY));  		mWidget->showNormal(); 		mWidget->setGeometry(rect);  		mDragPos = QPoint(desX, desY); 		mIsMaxMove = true;  		return true; 	}  	return false; }
  上述代码中的mIsMaxMove标识是为了在一次窗体还原操作后,释放鼠标时可以正常的设置缩放标识而设。
  有了上述代码之后,窗体就能还原到最大化之前的大小,并且为之也移动到了鼠标相应的位置,关于这个新位置的计算这里需要说明下。
  x坐标
  x轴坐标使用了比例计算方式。窗体全屏时鼠标按下的位置在窗体上的位置在窗体还原后依然保持不变,这样计算比较简单而且不会出错,保证窗体还原后,鼠标会一直在标题栏内。
  如果需要优化x轴坐标的计算方法,只需要重新计算上述代码中的desX值即可。
  y坐标
  y轴坐标这里没有做特殊处理。因为窗体还原时,标题栏的高度是没有发生变化的,因此这里不需要做特殊处理。

小牛九号电动车为何那么贵?高科技还是割韭菜?这4个原因您在阅读前请点击上面的关注二字,后续会第一时间为您提供更多有价值的相关内容,感谢您的支持。在买电动车的时候,我们可以发现电动车分为两大品牌类别,分为互联网品牌与传统品牌,其中互联网服务器发包指的是什么?有什么作用?服务器发包指的是什么?有什么作用?很多人在使用服务器的过程中都会听说过服务器发包,那么到底什么是发包呢?服务器发包又是什么呢?有什么作用呢。下面我们就简单的聊聊。服务器发包是什么?美国芯片封锁全面升级,国产先进AI芯片或将停产国内芯片行业迎来巨大压力,美国10月7日再出新规,主要就是针对我国芯片产业升级,其中包括了国内高校以及众多高科技企业,特别是针对先进AI芯片,更是让不少国人感到愤怒不已,根据环球网科学家发现新证据表明土星的卫星土卫二可能适合居住科学家发现新证据表明土星的卫星土卫二可能适合居住土卫二是土星的卫星之一,具有很高的宜居潜力,因为它的海洋可能富含溶解的磷,这是生命的重要元素。在土星周围发现的第二颗卫星,土卫二,在iPhone15UItra渲染图背部设计凸显豪华,苹果越来越奔放了今年苹果砍掉了mini系列,引入Plus版本,这是自2017年iPhone8Plus发布以来,苹果时隔五年再一次推出Plus版本的iPhone机型,而就明年,苹果可能会推出UItr梁宁下一个时代,是知识的比拼梁宁身上有很多标签著名产品人得到App课程产品思维30讲主理人湖畔大学产品模块学术主任百度顾问。她曾任联想腾讯高管,工作经历横跨BAT,与京东美团小米华为等企业有长期深度交流。甲子华为Nova11Pro开启16512GB大存储,再加鸿蒙3。0,敢说五年不卡经过两年时间的打磨,华为Mate50系列终于成功反击了,可以说是本年度综合实力最强的顶尖旗舰。其实要说硬核技术还得看华为这位老大哥才行,像小米OV等只会一味的堆料,无非就是在影像配豪华品牌竞争再起波澜奔驰卫冕冠军二线豪华加速洗牌本报记者尹丽梅童海华北京报道中国车市特别是豪华车市场在经历上半年的阵痛后,现阶段正在走向复苏回暖。在刚刚过去的9月,国家统计局工业司高级统计师朱虹在解读工业企业利润数据时称,从8月多个国家陷入恶性通胀,居民存款可能一文不值,什么最值钱?美联储加息带来的负面影响有多大?在全球收割完一波财富后,就留下了一个烂摊子,股市大跌,货币贬值,CPI持续爆表。CPI是反映居民购买的生活消费品和服务项目价格变动的一个指标,它的上欧盟家用能源价格指数发布,雅典电价到底什么水平?据希腊中希时报8日报道,一份最新发布的欧盟家用能源价格指数报告显示,希腊首都雅典9月份再次成为欧盟家庭用电价格最低的城市之一,同时,其天然气价格位列欧盟成员国第4位。数据显示,在310。9日小麦价格信息涨价能否持续?附全国报价表本轮小麦价格上涨,已经持续了大概半个月的时间,区间震荡许久的小麦终于扬眉吐气了一把。今日小麦现货价格依旧以涨为主,山东河南河北地区价格区间普遍在1。561。6元斤,样本点均价1。5
高血压的人可以吃猪油吗?标准答案来了医学的角度,并不建议高血压患者食用猪油。高血压本身是动脉粥样硬化性心血管疾病非常重要的危险因素,高脂饮食,比如摄入过多动物类脂肪,对于动脉粥样硬化性心血管疾病不利。所以高血压病人不高血压,是痰多了,一方巧解高血压是痰撑得,降压药就是骗子。去年回老家,表叔早上起床的时候,突然说自己一只眼睛看不清东西,看啥也是红色的,细问得知,这几天忙的晕头转向,降压药一直没喝,自己血压升高也不知道。我睡过的两个人,若注定不能在一起,不如早点离开世界上,有数不清的人,谁也无法肯定,此时出现在你身边的人,陪在你身边的那个人,到底能陪你多久,又能不能够陪你走到最后。也许,在漫长的人生旅程中,你需要遇见一个又一个的人,经历一段又高血压治疗主要在肝,肝保护好了,血压也就下来了中医看来,高血压属眩晕症,眩晕一症,历代医家论述颇多,在内经中记载诸风掉眩,皆属于肝及上气不足髓海不足诸论。高血压的常见病因大多是因为肝出现了问题,今天给大家介绍一个名方平肝降压方胆结石多是作出来的,4个习惯若早点改正,或可保胆囊健康胆囊位于人体的右腹部位置,与肝脏间通过紧密的管道相连。从生理结构来看,胆囊能够为食物消化提供胆汁,辅助脂质进行利用与吸收同时还能够分泌一定的粘液成分,以免胆道被浓缩胆汁溶解。胆囊个绿茶是高血压的加速器?医生稳定血压,4水尽量少喝播高血压是生活中一种常见的慢性代谢性疾病,它也是影响中老年人健康的首要杀手。高血压在平时又被人们称之为财富病,因为大多的高血压患者都有长期暴饮暴食的不良习惯。高血压的发生与很多因素有庞统落凤坡迷局谁应该为他的死负最大责任?假如庞统不死,刘备是否能一统三国呢?微信游戏三国杀名将传H5卧龙凤雏,代表着东汉末年的两位顶尖谋士,得一可得天下。刘备本来得到了两位,没想到庞统却在落凤坡陨落,早早退出了历史舞台。TES最终没能复仇JDG,jackeylove赛前预言成真在刚刚结束的lpl夏季赛总决赛中,JDG32击败TES拿到夏季赛决赛的冠军,捧起了属于他们的银龙杯牙膏在这场对局中荣获FMVP,击败Knight成为萍乡第一中单,牙膏的沙皇也是招牌TES打野小天,巨魔逆天大棒打爆JDG,张嘉文直言我也很硬JDG和TES的决赛打满了五局,第四局TES的小天成功救主,成为了这场比赛,TES拿下的关键选手,小天的巨魔不但肉,而且一手大棒,把JDG全队搞的心态爆炸,这场比赛的小天的巨魔也成最远的边陲贸易站交易技巧最远的边陲贸易站是游戏中玩家用来进行交易的地方,不过在交易的过程中也是需要注意一些事项,合理的利用交易的技巧可以让你更赚,可能有玩家还不懂怎么交易比较好,下面小编就给大家整理了具体为何库里那么难防?同是攻击型后卫,为何利拉德更容易被限制住?自从库里横空出世以来,联盟当中任何球队在面对勇士队的时候防守库里都是主教练最头疼的事情。甚至他们一整支球队要把50的防守重心全部放在库里一个人身上。其实现如今联盟当中涌现了很多攻击