Qt开源作品16-通用无边框拖动拉伸
一、前言
相信各位CS结构开发的程序员,多多少少都遇到过需要美化界面的事情,一般都不会采用系统的标题栏,这样就需要无边框标题栏窗体,默认的话无边框的标题栏都不支持拉伸和拖动的,毕竟去掉了标题栏则意味着失去了系统的窗体的属性,拉伸和拖动都需要自己写代码去实现,网上有很多类似的开源的方案,我也看过不少,总体来说复杂了些,对于初学者来说有可能看的云里雾里的,比如边框四周八个方位都可以自由拉伸这块,我的思路是针对设定的八个方位的区域进行识别鼠标是否按下,按下的哪个部位则执行什么拉伸策略,鼠标移到哪个位置则对应改变鼠标指针形状,更浅显易懂一些,至于拖动移动,还可以设置拖动的标题栏的高度等。
主要功能:
- 可以指定需要无边框的widget
- 边框四周八个方位都可以自由拉伸
- 可设置对应位置的边距,以便识别更大区域
- 可设置是否允许拖动
- 可设置是否允许拉伸
二、代码思路
bool FramelessWidget::eventFilter(QObject *watched, QEvent *event)
{
if (widget != 0 && watched == widget) {
if (event->type() == QEvent::Resize) {
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
int width = widget->width();
int height = widget->height();
//左侧描点区域
rectLeft = QRect(0, padding, padding, height - padding * 2);
//上侧描点区域
rectTop = QRect(padding, 0, width - padding * 2, padding);
//右侧描点区域
rectRight = QRect(width - padding, padding, padding, height - padding * 2);
//下侧描点区域
rectBottom = QRect(padding, height - padding, width - padding * 2, padding);
//左上角描点区域
rectLeftTop = QRect(0, 0, padding, padding);
//右上角描点区域
rectRightTop = QRect(width - padding, 0, padding, padding);
//左下角描点区域
rectLeftBottom = QRect(0, height - padding, padding, padding);
//右下角描点区域
rectRightBottom = QRect(width - padding, height - padding, padding, padding);
} else if (event->type() == QEvent::HoverMove) {
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
QHoverEvent *hoverEvent = (QHoverEvent *)event;
QPoint point = hoverEvent->pos();
if (resizeEnable) {
if (rectLeft.contains(point)) {
widget->setCursor(Qt::SizeHorCursor);
} else if (rectRight.contains(point)) {
widget->setCursor(Qt::SizeHorCursor);
} else if (rectTop.contains(point)) {
widget->setCursor(Qt::SizeVerCursor);
} else if (rectBottom.contains(point)) {
widget->setCursor(Qt::SizeVerCursor);
} else if (rectLeftTop.contains(point)) {
widget->setCursor(Qt::SizeFDiagCursor);
} else if (rectRightTop.contains(point)) {
widget->setCursor(Qt::SizeBDiagCursor);
} else if (rectLeftBottom.contains(point)) {
widget->setCursor(Qt::SizeBDiagCursor);
} else if (rectRightBottom.contains(point)) {
widget->setCursor(Qt::SizeFDiagCursor);
} else {
widget->setCursor(Qt::ArrowCursor);
}
}
//根据当前鼠标位置,计算XY轴移动了多少
int offsetX = point.x() - lastPos.x();
int offsetY = point.y() - lastPos.y();
//根据按下处的位置判断是否是移动控件还是拉伸控件
if (moveEnable) {
if (pressed) {
widget->move(widget->x() + offsetX, widget->y() + offsetY);
}
}
if (resizeEnable) {
if (pressedLeft) {
int resizeW = widget->width() - offsetX;
if (widget->minimumWidth() <= resizeW) {
widget->setGeometry(widget->x() + offsetX, rectY, resizeW, rectH);
}
} else if (pressedRight) {
widget->setGeometry(rectX, rectY, rectW + offsetX, rectH);
} else if (pressedTop) {
int resizeH = widget->height() - offsetY;
if (widget->minimumHeight() <= resizeH) {
widget->setGeometry(rectX, widget->y() + offsetY, rectW, resizeH);
}
} else if (pressedBottom) {
widget->setGeometry(rectX, rectY, rectW, rectH + offsetY);
} else if (pressedLeftTop) {
int resizeW = widget->width() - offsetX;
int resizeH = widget->height() - offsetY;
if (widget->minimumWidth() <= resizeW) {
widget->setGeometry(widget->x() + offsetX, widget->y(), resizeW, resizeH);
}
if (widget->minimumHeight() <= resizeH) {
widget->setGeometry(widget->x(), widget->y() + offsetY, resizeW, resizeH);
}
} else if (pressedRightTop) {
int resizeW = rectW + offsetX;
int resizeH = widget->height() - offsetY;
if (widget->minimumHeight() <= resizeH) {
widget->setGeometry(widget->x(), widget->y() + offsetY, resizeW, resizeH);
}
} else if (pressedLeftBottom) {
int resizeW = widget->width() - offsetX;
int resizeH = rectH + offsetY;
if (widget->minimumWidth() <= resizeW) {
widget->setGeometry(widget->x() + offsetX, widget->y(), resizeW, resizeH);
}
if (widget->minimumHeight() <= resizeH) {
widget->setGeometry(widget->x(), widget->y(), resizeW, resizeH);
}
} else if (pressedRightBottom) {
int resizeW = rectW + offsetX;
int resizeH = rectH + offsetY;
widget->setGeometry(widget->x(), widget->y(), resizeW, resizeH);
}
}
} else if (event->type() == QEvent::MouseButtonPress) {
//记住当前控件坐标和宽高以及鼠标按下的坐标
QMouseEvent *mouseEvent = (QMouseEvent *)event;
rectX = widget->x();
rectY = widget->y();
rectW = widget->width();
rectH = widget->height();
lastPos = mouseEvent->pos();
//判断按下的手柄的区域位置
if (rectLeft.contains(lastPos)) {
pressedLeft = true;
} else if (rectRight.contains(lastPos)) {
pressedRight = true;
} else if (rectTop.contains(lastPos)) {
pressedTop = true;
} else if (rectBottom.contains(lastPos)) {
pressedBottom = true;
} else if (rectLeftTop.contains(lastPos)) {
pressedLeftTop = true;
} else if (rectRightTop.contains(lastPos)) {
pressedRightTop = true;
} else if (rectLeftBottom.contains(lastPos)) {
pressedLeftBottom = true;
} else if (rectRightBottom.contains(lastPos)) {
pressedRightBottom = true;
} else {
pressed = true;
}
} else if (event->type() == QEvent::MouseMove) {
//改成用HoverMove识别
} else if (event->type() == QEvent::MouseButtonRelease) {
//恢复所有
pressed = false;
pressedLeft = false;
pressedRight = false;
pressedTop = false;
pressedBottom = false;
pressedLeftTop = false;
pressedRightTop = false;
pressedLeftBottom = false;
pressedRightBottom = false;
widget->setCursor(Qt::ArrowCursor);
}
}
return QObject::eventFilter(watched, event);
}
三、效果图

四、开源主页
- 以上作品完整源码下载都在开源主页,会持续不断更新作品数量和质量,欢迎各位关注。
- 本开源项目已经成功升级到V2.0版本,分门别类,图文并茂,保你爽到爆。
- Qt开源武林秘籍开发经验,看完学完,20K起薪,没有找我!
- 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
- 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
- 开源秘籍:https://gitee.com/feiyangqingyun/qtkaifajingyan
- 个人主页:https://qtchina.blog.csdn.net/
- 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
Qt开源作品16-通用无边框拖动拉伸的更多相关文章
- Qt开源作品38-无边框窗体方案(无抖动,支持win、linux、mac等系统,侧边半屏顶部全屏)
一 前言 不知道各位程序员有没有遇到过这样一种困惑,好不容易在开源网站找到了类似的想要的项目代码,结果down下来一编译,我勒个去,几百个错误,根本没法用,熟悉的人还好可以直接阅读代码进行修改(有些只 ...
- WPF无边框拖动、全屏、缩放
原文:WPF无边框拖动.全屏.缩放 版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/lwwl12/article/details/78059361 先看效果 ...
- winform学习(9)无边框拖动窗体
去除边框 选中窗体,在属性中找到FormBorderStyle,设置为None 实现无边框拖动 [DllImport("user32.dll")] public st ...
- Qt编写自定义控件67-通用无边框
一.前言 在之前的一篇文章中写过一个通用的移动控件,作用就是用来传入任意的widget控件,可以在父类容器中自由移动.本篇文章要写的是一个通用的无边框类,确切的说这不叫控件应该叫组件才对,控件是要看得 ...
- qt 5 小练习 创建无边框界面
我们大家都知道QT5 自带的界面不是那么美观,并且每个软件我们都发现他们的边框是自定义的,所以我决定写一篇这样的博文,也许已经有许许多多篇大牛写的论文了,但我还是想写一篇记录自己的学习QT的历程 首先 ...
- 【Qt】Qt之自定义界面(实现无边框、可移动)【转】
简述 UI设计是指对软件的人机交互.操作逻辑.界面美观的整体设计.好的UI设计不仅是让软件变得有个性.有品位,还要让软件的操作变得舒适简单.自由,充分体现软件的定位和特点. 爱美之心人皆有之.其实软件 ...
- Qt之自定义界面(实现无边框、可移动)
简述 UI设计是指对软件的人机交互.操作逻辑.界面美观的整体设计.好的UI设计不仅是让软件变得有个性.有品位,还要让软件的操作变得舒适简单.自由,充分体现软件的定位和特点. 爱美之心人皆有之.其实软件 ...
- WPF 无边框拖动
无边框之后的拖动方法有三种. 我个人是喜欢第一和第三的方法,看个人去需求. 第三种代码比较仓促,有需要者可以立马用,或者稍作整理修改. 对于WIN10 .NET 4.5以上的框架可以使用 WIndow ...
- pyqt5无边框拖动
from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * import sys class ...
- CreateWindow创建无边框 可拉伸窗体
createwindow 定义 HWND WINAPI CreateWindow( _In_opt_ LPCTSTR lpClassName, _In_opt_ LPCTSTR lpWindowNam ...
随机推荐
- 云原生周刊:Score 成为 CNCF 沙箱项目|2024.08.12
开源项目推荐 KubeOne Kubermatic KubeOne 自动化管理您所有云环境.本地环境.边缘计算和物联网环境中的集群操作.KubeOne 可以安装高可用(HA)的主集群,也可以安装单主集 ...
- 云原生周刊:Harbor v2.11 版本发布 | 2024.6.17
开源项目推荐 Descheduler Descheduler 是一个工具,可用于优化 Kubernetes 集群中 Pod 的部署位置.它可以找到可以移动的 Pod,并将其驱逐,让默认调度器将它们重新 ...
- C#/.NET/.NET Core技术前沿周刊 | 第 10 期(2024年10.14-10.20)
前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...
- 题解:「NOIP2022 提高组」种花
题解:「NOIP2022 提高组」种花 题目大意:给定一个 \(n \times m\) 的01矩阵,0表示可以种花,1表示土坑(无法种花),现在要在图上种出一个C型或F型(C,F横着的两条线的长度都 ...
- Flink Time
基础概念 支持三种时间概念: Processing Time 时间递增 Ingestion Time : 摄入时间,数据进入Flink框架的时间,在Source Operator中设置,每个事件拿到当 ...
- fabric基本使用
fabric简介 Fabric 是一个 Python 的库,同时它也是一个命令行工具.它提供了丰富的同 SSH 交互的接口,可以用来在本地或远程机器上自动化.流水化地执行 Shell 命令.使用 ...
- 2024-11-13:求出所有子序列的能量和。用go语言,给定一个整数数组nums和一个正整数k, 定义一个子序列的能量为子序列中任意两个元素之间的差值绝对值的最小值。 找出nums中长度为k的所有子
2024-11-13:求出所有子序列的能量和.用go语言,给定一个整数数组nums和一个正整数k, 定义一个子序列的能量为子序列中任意两个元素之间的差值绝对值的最小值. 找出nums中长度为k的所有子 ...
- 在网页上调起本机C#程序
前言 最近开始整理笔记里的库存草稿,本文是 23 年 5 月创建的了(因为中途转移到 onedrive,可能还不止) 网页调起电脑程序是经常用到的场景,比如百度网盘下载,加入 QQ 群之类的 我之前做 ...
- 解密prompt系列43. LLM Self Critics
前一章我们介绍了基于模型自我合成数据迭代,来提升LLM生成更合理的自我推理思考链路.但在模型持续提升的道路上,只提升Generator能力是不够的,需要同步提升Supervisor.Verifier的 ...
- Spring源码学习 ------ IoC——AOP
一直想抽空把Spring源码拿来读读,但真正去做这件事的时候发现不简单,Spring发展这么多年,它的规模已不是一个一般的开源框架所能比的,它的主要架构和流程不是非常清晰,很难抓到要害,但有一点可以肯 ...