无标题栏窗口的实现拖动,和边的拉伸功能

本文的功能实现,参考了链接:https://blog.csdn.net/Ternence_God/article/details/100150377,图片也是来自其。

引言

创建的程序采用系统窗口,直接可以进行拖动,向八个方向拉伸,一旦设置窗口无标题栏,即:setWindowFlags(Qt::FramelessWindowHint);后,窗口的拖动,拉伸功能便需要重新实现。

效果

由于暂时还没有向平台上传视频,所以咱没有插入视频来直观的显示程序运行的效果。后期补上。

实现

开发环境

在这里插入图片描述

下面以一个小的demo来实现窗口的拖动和拉伸功能。

思路

窗口的拖动

鼠标按下后记住当前鼠标按下点的位置,这个点相对于屏幕而言,同时获取窗口左上角的位置,当鼠标按下移动后,获取当前移动到的点的位置,也是相对于桌面而言的坐标,用移动后的位置减去刚开始鼠标按下的点得到偏移量,用鼠标左上角的点加上偏移量便是移动后窗口的位置,调用move()函数将窗口移动到指定点,实现窗口在鼠标按下不放可拖动。这里不用考虑偏移量是加上还是减去,因为记录了鼠标刚开始按下的点之后,向右移,偏移量变为正值,向左移偏移量便为负值。

窗口的拉伸

由于我们获取窗口的上下左右四个边以及四个角的坐标来判断当鼠标进入指定边或者角时,两者的坐标并不相同,而是有一定的偏差,这是采用划分区域来实现鼠标进入窗口置顶的边或角,从而按照不同的边、角置顶鼠标的样式,保存原来窗口的位置大小,记录鼠标变样后按下点的坐标,和鼠标移动后点的坐标,求得偏移量,从而计算各个边角的位置,从新设置窗口的位置大小。且需要记录窗口被拉伸后鼠标的位置,防止下一次操作直接从上一次拉伸后不释放坐标直接拉伸。
区域划分
在这里插入图片描述

项目结构

在这里插入图片描述
基类选择QDialog类,其它都是默认,然后创建项目。

具体代码

.pro,.ui文件采用自动生成的,不做任何改变。
widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
protected:enum mouseArea{topLeftCorner = 11,topBorder = 12,topRightCorner = 13,leftBorder = 21,midArea = 22,rightBorder = 23,leftBottomConrner = 31,bottomBorder = 32,rightBottomConrner = 33,};enum winDivideArea{oneArea = 1,twoArea,threeArea,};void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void setMouseCursorStyle(QMouseEvent *event);//设置鼠标光标的样式int determineArea(QPoint pos);//判断点pos所在的区域void mouseStrechDrag(QMouseEvent *event,QPoint &offset);//鼠标拉伸拖动
private:Ui::Widget *ui;QPoint      m_pressPos;//鼠标按下点的位置QPoint      m_topLeftPos;//鼠标左上角的位置QPoint      m_lastPos;//上一次拉伸点的位置const int   m_floatValue;//鼠标所在位置的浮动值int         m_region;//鼠标所在的区域
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent),m_floatValue(10), ui(new Ui::Widget)
{ui->setupUi(this);setWindowFlags(Qt::FramelessWindowHint);setMouseTracking(true);
}Widget::~Widget()
{delete ui;
}void Widget::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {
//        m_pressPos = event->globalPos();//获取在屏幕坐标系统中的位置
//        m_topLeftPos = geometry().topLeft();//获取窗口左上角的位置,原本采取左上角坐标+偏移量m_lastPos = event->globalPos();m_pressPos = pos();m_region = determineArea(event->pos());//在父窗口中的位置//        qDebug()<<QStringLiteral("鼠标位置:")<<m_pressPos<<QStringLiteral("位置:")<<event->pos()
//        <<QStringLiteral("窗口左上角的位置:")<<m_topLeftPos;//在父窗口中的位置}QWidget::mousePressEvent(event);
}void Widget::mouseMoveEvent(QMouseEvent *event)
{if (isMaximized()){return;}setMouseCursorStyle(event);if (event->buttons() == Qt::LeftButton) {QPoint offset = event->globalPos() - m_lastPos;if (m_region == midArea) {move(m_pressPos + offset);}else {mouseStrechDrag(event,offset);}}QWidget::mouseMoveEvent(event);
}void Widget::mouseReleaseEvent(QMouseEvent *event)
{QWidget::mouseReleaseEvent(event);
}void Widget::setMouseCursorStyle(QMouseEvent *event)
{int region = determineArea(event->pos());//这里的区域必须为局部变量,否则会出现拉伸中出现区域变更,导致功能紊乱switch (region) {case topLeftCorner:case rightBottomConrner:setCursor(Qt::SizeFDiagCursor);//设置光标的形状使用setCursor(),使用setShape()设置不上,并不知为啥break;case topBorder:case bottomBorder:setCursor(Qt::SizeVerCursor);break;case topRightCorner:case leftBottomConrner:setCursor(Qt::SizeBDiagCursor);break;case leftBorder:case rightBorder:setCursor(Qt::SizeHorCursor);break;case midArea:setCursor(Qt::ArrowCursor);break;default:break;}
}int Widget::determineArea(QPoint pos)
{int xArea = 0;int yArea = 0;int areaFlag = 0;if (pos.x() < m_floatValue) {xArea = oneArea;}else if (pos.x() > width() - m_floatValue) {xArea = threeArea;}else {xArea = twoArea;}if (pos.y() < m_floatValue) {yArea = oneArea;}else if (pos.y() > height() - m_floatValue) {yArea = threeArea;}else {yArea = twoArea;}return areaFlag = yArea * 10 + xArea;
}void Widget::mouseStrechDrag(QMouseEvent *event,QPoint &offset)
{QRect rect = geometry();qDebug()<<QStringLiteral("鼠标移动的位置:")<<event->globalPos()<<QStringLiteral("按下点位置:")<<m_pressPos<<QStringLiteral("偏移量:")<<event->globalPos()-m_pressPos;switch (m_region) {case topLeftCorner:rect.setTopLeft(rect.topLeft() + offset);break;case rightBottomConrner:rect.setBottomRight(rect.bottomRight() + offset);break;case topBorder:rect.setTop(rect.top() + offset.y());break;case bottomBorder:rect.setBottom(rect.bottom() + offset.y());break;case topRightCorner:rect.setTopRight(rect.topRight() + offset);break;case leftBottomConrner:rect.setBottomLeft(rect.bottomLeft() + offset);break;case leftBorder:rect.setLeft(rect.left() + offset.x());break;case rightBorder:rect.setRight(rect.right() + offset.x());break;default:break;}//设置拉伸的最小宽度和高度if (rect.width() < 200 || rect.height() < 100) {return ;}setGeometry(rect);m_lastPos = event->globalPos();
}//void Widget::setMouseCursorStyle(QMouseEvent *event)
//{
//    //转换后存在误差,鼠标在左下角获取的位置与左下角的位置不一样,因而无法实现下述方法
//    qDebug()<<QStringLiteral("鼠标在父窗口的位置:")<<mapFromParent(event->globalPos())<<
//    QStringLiteral("鼠标的位置:")<<event->pos()<<QStringLiteral("左上角")<<geometry().topLeft()
//    <<QStringLiteral("右上角")<<geometry().topRight()<<QStringLiteral("左下角")<<geometry().bottomLeft()
//    <<QStringLiteral("右下角")<<geometry().bottomRight()<<QStringLiteral("左边")<<geometry().left()
//    <<QStringLiteral("右边")<<geometry().right()<<QStringLiteral("上边")<<geometry().top()
//    <<QStringLiteral("下边")<<geometry().bottom()<<QStringLiteral("转换后左下角")<<mapFromParent(geometry().bottomLeft());//获取位置相同,都是鼠标在父窗口中的位置
//    if (event->pos().x() > geometry().left() &&event->pos().x() < geometry().right()
//    && event->pos().y() > geometry().top() && event->pos().y() < geometry().bottom())
//    {//中间
//        cursor().setShape(Qt::ArrowCursor);
//    }else if (event->pos() == mapFromParent(geometry().topLeft())) {//左上角
//        qDebug()<<QStringLiteral("鼠标在左上角");
//        cursor().setShape(Qt::SizeFDiagCursor);
//    }else if (event->pos() == mapFromParent(geometry().topRight())) {//右上角
//        cursor().setShape(Qt::SizeBDiagCursor);
//    }else if (event->pos() == geometry().bottomLeft()) {//左下角
//        cursor().setShape(Qt::SizeBDiagCursor);
//    }else if (event->pos() == geometry().bottomRight()) {//右下角
//        cursor().setShape(Qt::SizeFDiagCursor);
//    }else if (event->pos().x() == geometry().left()) {//左边
//        cursor().setShape(Qt::SizeHorCursor);
//    }else if (event->pos().x() == geometry().right()) {//右边
//        cursor().setShape(Qt::SizeHorCursor);
//    }else if (event->pos().y() == geometry().top()) {//上边
//        cursor().setShape(Qt::SizeVerCursor);
//    }else if (event->pos().y() == geometry().bottom()) {//下边
//        cursor().setShape(Qt::SizeVerCursor);
//    }
//}

main.cpp文件也采用默认生成的文件。
这样就可以编译,运行,查看程序的运行效果了。

注意点

  1. 理解思路,将窗口划分为9个区域,进行编号,之所以要划分区域是因为上面被注释掉的代码在运行时会发现鼠标即使到了窗口的指定边,但是与获取的指定边的坐标总有偏差。
  2. 需要在构造函数中设置鼠标跟踪,要不不能实现鼠标放置在指定边时出现特定的鼠标样式,只在鼠标点击后才能出现特定 的鼠标样式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/524008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Centos7 Docker 文件拷贝_入门试炼04

前提&#xff1a;容器服务必须启动才可以进行文件拷贝 一、常用命令 需求宿主机某一文件/目录->>容器内部docker cp 需要拷贝的文件或目录 容器名称:容器目录容器内部某一文件/目录->>宿主机docker cp 容器名称:容器内目录/文件 宿主机目录/文件 docker cp 容器名…

数据库之战 | 寻找你心中的数据库漫威英雄

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;作者&#xff1a;S.L.Cloud转自&#xff1a;京东云开发者社区《复仇者联盟4-终局之战》…

qt中event->globalPos()与pos()

理解 event->globalPos() 事件触发点相对于桌面的位置&#xff1b; pos() 程序相对于桌面左上角的位置&#xff0c;实际是窗口的左上角坐标。 下面是通过图示更加清楚的表明上述的解释&#xff1a; 红点所在处即为窗口左上角的坐标pos()&#xff1b; 若鼠标在程序窗口中点…

Centos7 Docker 目录挂载_入门试炼06

文章目录一、目录挂载格式二、需求实战2.1. 目录挂载2.2. 测试目录挂载_同步文件2.3. 测试目录挂载_同步文件夹一、目录挂载格式 我们可以在创建容器的时候&#xff0c;将宿主机的目录与容器内的目录进行映射&#xff0c;这样我们就可以通过修改宿主机某个目录的文件从而去影响…

git查看之前的提交日志

提要 使用git指令查看当前项目在这之前所有人提交的记录&#xff0c;可以使用tig指令。 在命令行输入&#xff1a;tig,然后回车。 出现之前所有人在此项目下的提交信息。按q键退出。 还可以使用指令git log,然后回车&#xff0c;可以查看当天最近的几次提交记录。退出的时候…

Centos7 Docker查看容器IP地址_入门试炼07

一、查看容器IP地址 1. 查看容器运行的各种数据 docker inspect mycentos32. 查看容器ip docker inspect --format{{.NetworkSettings.IPAddress}} mycentos3获取其他信息&#xff0c;找到获取信息的节点&#xff0c;同理 执行docker inspect mycentos3后的所有内容&#x…

Elastic Jeff Yoshimura:开源正在开启新一轮的创新 | 人物志

戳蓝字“CSDN云计算”关注我们哦&#xff01;人物志&#xff1a;观云、盘点、对话英雄。以云计算风云人物为核心&#xff0c;聚焦个人成长、技术创新、产业发展&#xff0c;还原真实与鲜活&#xff01;“从我们的角度来说&#xff0c;开源正在开启新一轮的创新。”在首次中国举…

qt在窗口的子部件中绘制矩形

引言 在窗口中绘制矩形&#xff0c;只需重写paintEvent()函数&#xff0c;在重回函数中实现绘制矩形便可。但在窗口的某一个子部件中实现绘制矩形&#xff0c;此时就需重写事件过滤函数&#xff0c;在指定的子部件的绘图事件实现绘制矩形。 结构 窗口部件的组成如下图&#…

Centos7 Docker 删除容器_入门试炼08

说明命令删除指定的容器格式docker rm $CONTAINER_ID/NAME删除容器指定容器名称docker rm mycentos3删除容器指定容器iddocker rm 90913daea673 注意&#xff0c;只能删除停止的容器 效果图&#xff1a; #删除所有容器 docker rm docker ps -a -q删除所有容器的原理&#xff…

Spark精华问答:DataFrame与RDD的主要区别在哪?

Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。目前的热度已经超过Hadoop,正所谓青出于蓝而胜于蓝&#xff0c;今天我们就来看看关于park 的精华问答吧。1Q&#xff1a;DataFrame是什么?A&#xff1a;DataFrame是一种以RDD为基础的分布式数据集&#xff0c;类…

Centos7 使用Docker MySQL部署_01

文章目录Docker MySQL部署Docker MySQL部署 #1.拉取mysql镜像 docker pull mysql #2.查看拉取的mysql镜像 docker images#3.创建MySQL容器 docker run -di --name ly_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 mysql注&#xff1a;-p 代表端口映射&#xff0c;格式为 …

“自带大屏”的便利店,你见过吗?

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01; 平常&#xff0c;便利店倒是见过很多&#xff0c;但是“自带大屏”的便利店&#xf…

Centos7 使用Docker 部署Tomca+mysql+调试联通_02

文章目录一、Tomcat部署1. 拉取tomcat镜像2. 上传cas项目3. 修改cas系统的配置文件4. 创建tomcat容器5. 浏览器测试部署的web应用6. 输入账号密码测试mysql连接7. 访问注销接口测试一、Tomcat部署 1. 拉取tomcat镜像 docker pull tomcat:7-jre7注&#xff1a;拉取tomcat镜像&…

无剧透 | 分析《复联》英雄得出的结论:什么样的技术人适合做管理?

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;转自&#xff1a;技术领导力作者&#xff1a;力小哥/技术领导力社区特约撰稿人4月24日…

Centos7 使用Docker 部署Nginx+mysql+tomcat+调试联通_03

文章目录Nginx部署1. 拉取Nginx镜像2. 创建Nginx容器3. 测试Nginx4. 配置反向代理5. 浏览器nginx容器和tomcat容器联通测试6. 浏览器tomcat容器和mysql容器联通测试7. 浏览器注销接口测试Nginx部署 1. 拉取Nginx镜像 docker pull nginx2. 创建Nginx容器 docker run -di --na…

qt种实现搜索栏功能

引言 在搜索栏种输入要搜索的文本&#xff0c;就会出现相关联的文本提示&#xff0c;这是可以通过鼠标选中要搜索的文本&#xff0c;或者通过上下键选中要搜索的文本。 效果 效果图如下所示&#xff1a; 实现 下面是相关的代码实现&#xff0c;读者只需参考&#xff0c;理解…

Docker Redis部署_04

Docker Redis部署部署 1. 拉取Redis镜像2. 创建Redis容器3. 客户端测试 1. 拉取Redis镜像 docker pull redis2. 创建Redis容器 docker run -di --namepinyougou_redis -p 6379:6379 redis查看redis容器是否已经运行&#xff1a; docker ps3. 客户端测试 在你的本地电脑命令提…

关于谷歌云,你应该知道的一切! | 技术头条

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;译者&#xff1a;风车云马 在国内,“谷歌云”这个词并不像“亚马逊AWS”、“微软Azure…

Docker 容器导出为镜像

Docker 镜像备份与迁移 1. 容器保存为镜像2. 镜像备份3. 镜像恢复与迁移 1. 容器保存为镜像 我们可以通过以下命令将容器保存为镜像 docker commit pinyougou_nginx mynginxpinyougou_nginx是容器名称mynginx是新的镜像名称 pinyougou_nginx容器已经成功保存为mynginx镜像&…

Storm精华问答 | Kafka在Storm中的角色是什么?

戳蓝字“CSDN云计算”关注我们哦&#xff01;Storm是Twitter开源的分布式实时大数据处理框架&#xff0c;被业界称为实时版Hadoop。随着越来越多的场景对Hadoop的MapReduce高延迟无法容忍&#xff0c;比如网站统计、推荐系统、预警系统、金融系统等&#xff0c; 大数据实时处理…