当前位置: 首页 > news >正文

自定义无边框窗口

效果: 可拖动拉伸

ui:设计如下

样式表:在ui CustomDialog 里设置的

                                        #widget_title{background: #E6F1EB;border-top-left-radius: 20px;border-top-right-radius: 20px;}#widget_client{background-color: rgb(255, 255, 255);border-bottom-left-radius: 20px; border-bottom-right-radius: 20px;}#label_title{background-color: #E6F1EB;font-family: Source Han Sans CN;font-size: 24px;font-weight: bold;}

头文件

#ifndef CUSTOMDIALOG_H
#define CUSTOMDIALOG_H#include <QDialog>
#include <QWidget>namespace Ui {
class CustomDialog;
}class CustomDialog : public QDialog
{Q_OBJECTpublic:explicit CustomDialog(QWidget *parent = nullptr);~CustomDialog();void setTitleText(const QString text);
private slots:void on_toolButton_quit_clicked();private:virtual void paintEvent(QPaintEvent *event) override; //重绘,virtual bool eventFilter(QObject *watched, QEvent *event);
private:Ui::CustomDialog *ui;int padding;                    //边距bool moveEnable;                //可移动bool resizeEnable;              //可拉伸bool pressed;                   //鼠标按下bool pressedLeft;               //鼠标按下左侧bool pressedRight;              //鼠标按下右侧bool pressedTop;                //鼠标按下上侧bool pressedBottom;             //鼠标按下下侧bool pressedLeftTop;            //鼠标按下左上侧bool pressedRightTop;           //鼠标按下右上侧bool pressedLeftBottom;         //鼠标按下左下侧bool pressedRightBottom;        //鼠标按下右下侧int rectX, rectY, rectW, rectH; //窗体坐标+宽高QPoint lastPos;                 //鼠标按下处坐标QRect rectLeft;                 //左侧区域QRect rectRight;                //右侧区域QRect rectTop;                  //上侧区域QRect rectBottom;               //下侧区域QRect rectLeftTop;              //左上侧区域QRect rectRightTop;             //右上侧区域QRect rectLeftBottom;           //左下侧区域QRect rectRightBottom;          //右下侧区域
};#endif // CUSTOMDIALOG_H

cpp

#include "customdialog.h"
#include "ui_customdialog.h"
#include <QStyleOption>
#include <QPainter>
#include <QMouseEvent>
CustomDialog::CustomDialog(QWidget *parent) :QDialog(parent),ui(new Ui::CustomDialog)
{ui->setupUi(this);setWindowFlags(Qt::FramelessWindowHint);setAttribute(Qt::WA_TranslucentBackground);//设置窗口透明化ui->toolButton_quit->setStyleSheet("QToolButton{border-radius: 20px;opacity: 1;""font-family: Source Han Sans CN;""font-size: 24px;""font-weight: norm;""background-color:#E6F1EB;}");padding = 8;moveEnable = true;resizeEnable = true;pressed = false;pressedLeft = false;pressedRight = false;pressedTop = false;pressedBottom = false;pressedLeftTop = false;pressedRightTop = false;pressedLeftBottom = false;pressedRightBottom = false;this->setMouseTracking(true);//绑定事件过滤器this->installEventFilter(this);//设置悬停为真,必须设置这个,不然当父窗体里边还有子窗体全部遮挡了识别不到MouseMove,需要识别HoverMovethis->setAttribute(Qt::WA_Hover, true);
}CustomDialog::~CustomDialog()
{delete ui;
}void CustomDialog::setTitleText(const QString text)
{ui->label_title->setText(text);
}void CustomDialog::paintEvent(QPaintEvent *)
{QStyleOption opt;opt.init(this);QPainter painter(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);}bool CustomDialog::eventFilter(QObject *watched, QEvent *event)
{if (watched == this) {if (event->type() == QEvent::Resize) {//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内int width = this->width();int height = this->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)) {this->setCursor(Qt::SizeHorCursor);} else if (rectRight.contains(point)) {this->setCursor(Qt::SizeHorCursor);} else if (rectTop.contains(point)) {this->setCursor(Qt::SizeVerCursor);} else if (rectBottom.contains(point)) {this->setCursor(Qt::SizeVerCursor);} else if (rectLeftTop.contains(point)) {this->setCursor(Qt::SizeFDiagCursor);} else if (rectRightTop.contains(point)) {this->setCursor(Qt::SizeBDiagCursor);} else if (rectLeftBottom.contains(point)) {this->setCursor(Qt::SizeBDiagCursor);} else if (rectRightBottom.contains(point)) {this->setCursor(Qt::SizeFDiagCursor);} else {this->setCursor(Qt::ArrowCursor);}}//根据当前鼠标位置,计算XY轴移动了多少int offsetX = point.x() - lastPos.x();int offsetY = point.y() - lastPos.y();//根据按下处的位置判断是否是移动控件还是拉伸控件if (moveEnable) {if (pressed) {this->move(this->x() + offsetX, this->y() + offsetY);}}if (resizeEnable) {if (pressedLeft) {int resizeW = this->width() - offsetX;if (this->minimumWidth() <= resizeW) {this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);}} else if (pressedRight) {this->setGeometry(rectX, rectY, rectW + offsetX, rectH);} else if (pressedTop) {int resizeH = this->height() - offsetY;if (this->minimumHeight() <= resizeH) {this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);}} else if (pressedBottom) {this->setGeometry(rectX, rectY, rectW, rectH + offsetY);} else if (pressedLeftTop) {int resizeW = this->width() - offsetX;int resizeH = this->height() - offsetY;if (this->minimumWidth() <= resizeW) {this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);}if (this->minimumHeight() <= resizeH) {this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);}} else if (pressedRightTop) {int resizeW = rectW + offsetX;int resizeH = this->height() - offsetY;if (this->minimumHeight() <= resizeH) {this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);}} else if (pressedLeftBottom) {int resizeW = this->width() - offsetX;int resizeH = rectH + offsetY;if (this->minimumWidth() <= resizeW) {this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);}if (this->minimumHeight() <= resizeH) {this->setGeometry(this->x(), this->y(), resizeW, resizeH);}} else if (pressedRightBottom) {int resizeW = rectW + offsetX;int resizeH = rectH + offsetY;this->setGeometry(this->x(), this->y(), resizeW, resizeH);}}} else if (event->type() == QEvent::MouseButtonPress) {//记住当前控件坐标和宽高以及鼠标按下的坐标QMouseEvent *mouseEvent = (QMouseEvent *)event;rectX = this->x();rectY = this->y();rectW = this->width();rectH = this->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;this->setCursor(Qt::ArrowCursor);}}return QObject::eventFilter(watched, event);
}void CustomDialog::on_toolButton_quit_clicked()
{reject();
}

相关文章:

自定义无边框窗口

效果&#xff1a; 可拖动拉伸 ui&#xff1a;设计如下 样式表&#xff1a;在ui CustomDialog 里设置的 #widget_title{background: #E6F1EB;border-top-left-radius: 20px;border-top-right-radius: 20px;}#widget_client{background-color: rgb(255, 255, 255);border-bottom…...

【网络安全 --- kali2023安装】超详细的kali2023安装教程(提供镜像资源)

如果你还没有安装vmware 虚拟机&#xff0c;请参考下面博客安装 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;https://blog.csdn.net/m0…...

机器学习笔记(二)

过拟合 如下图左边,模型出现了过拟合现象 为了解决过拟合现象, 其中一个做法是多收集数据,如右图。 第二种做法是减少模型的特征数量,即x 第三种做法是正则化 正则化就是减少x前面的参数 w的数值, 不用消除x 正则化的梯度下降如下, 因为只是缩小了w的值,而 b的值保持不变 …...

Java @Override 注解

在代码中&#xff0c;你可能会看到大量的 Override 注解。 这个注解简单来说就是让编译器去读的&#xff0c;能够避免你在写代码的时候犯一些低级的拼写错误。 Java Override 注解用来指定方法重写&#xff08;Override&#xff09;&#xff0c;只能修饰方法并且只能用于方法…...

用rabbitMq 怎么处理“延迟消息队列”?

延迟消息队列是一种允许消息在发送后等待一段时间&#xff0c;然后再被消费的机制。这种机制通常用于需要延迟处理的应用场景&#xff0c;如定时任务、消息重试、消息调度等。在 RabbitMQ 中&#xff0c;实现延迟消息队列需要使用一些额外的组件和技术&#xff0c;因为 RabbitM…...

不常见的JS加密分析

前言 ​ 今天发现一个很少见的JS加密代码&#xff0c;他由一段十分少见的环境检测逻辑&#xff0c;修改一个字符都会被检测到&#xff0c;十分神奇&#xff0c;今天献上。 源代码 let hiJsJiami;!function(){const Zg3GArray.prototype.slice.call(arguments);return eval(&…...

TCP原理特性详解

文章目录 可靠传输机制1.确认应答2.超时重传2.连接管理1.三次握手2.四次挥手 传输效率1.滑动窗口2.流量控制3.拥塞控制4.延时应答5.捎带应答 面向字节流粘包问题 TCP异常情况 可靠传输机制 可靠性&#xff1a;即发送方知道数据是发送成功了&#xff0c;还是失败了。 1.确认应答…...

什么是懒加载,JS如何实现懒加载,在php中如何去实现懒加载

懒加载&#xff08;Lazy Loading&#xff09;是一种前端优化技术&#xff0c;用于推迟加载页面中的某些资源&#xff08;如图片、脚本、样式等&#xff09;&#xff0c;直到用户需要访问或者接近该资源时才进行加载。这可以减少初始页面加载时间&#xff0c;并提高页面性能和用…...

Cesium 展示——读取文件——加载 geojson 文件数据

文章目录 需求分析方法一:加载 geojson 文件方法二:加载 后台解析后的 geojson 文件结果需求 在做项目时,对加载 geojson 格式的数据有了一定的了解,因此试着尝试接手后台解析的 geojson 数据进行绘制,因此做了总结如下 分析 方法一:加载 geojson 文件 this.od6 = wi…...

(二)Apache log4net™ 手册 - 配置

0、引言 在上一篇文章中我们简单介绍了 Log4Net 及其核心的三大组件。本文将在上一篇文章的基础上继续探讨与 Log4Net 配置相关的内容。 1、配置 将日志请求插入到应用程序代码中需要进行大量的计划和工作。观察表明&#xff0c;大约4%的代码专门用于日志记录。因此&#xf…...

Elasticsearch:时间点 API

Elasticsearch&#xff1a;时间点 API-CSDN博客 在今天的文章中&#xff0c;我将着重介绍 Point in time API。在接下来的文章中&#xff0c;我将介绍如何运用 PIT 来对搜索结果进行分页。这也是被推荐使用的方法。 Point in time API 默认情况下&#xff0c;搜索请求针对目标…...

hive数据表定义

分隔符 CREATE TABLE emp( userid bigint, emp_name array<string>, emp_date map<string,date>, other_info struct<deptname:string, gender:string>) ROW FORMAT DELIMITED FIELDS TERMINATED BY \t COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMINAT…...

OpenMesh 网格简化之顶点聚类

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 顶点聚类方法将落在给定大小体素中的所有顶点集中到单个顶点之上,其过程有点类似于点云体素下采样,之后再基于聚类之后的顶点重新连接面片,以达到网格简化的目的。 二、实现代码 #define _USE_MATH_DEFINES #in…...

C++ 类和对象篇(八) const成员函数和取地址运算符重载

目录 一、const成员函数 1. const成员函数是什么&#xff1f; 2. 为什么有const成员函数&#xff1f; 3. 什么时候需要使用const修饰成员函数&#xff1f; 二、取地址运算符重载 1. 为什么需要重载取地址运算符&#xff1f; 2. 默认取地址运算符重载函数 3. 默认const取地址运…...

k8s 集群安装(vagrant + virtualbox + CentOS8)

主机环境&#xff1a;windows 11 k8s版本&#xff1a;v1.25 dashboard版本&#xff1a;v2.7.0 calico版本&#xff1a; v3.26.1 CentOS8版本&#xff1a;4.18.0-348.7.1.el8_5.x86_64 用到的脚本&#xff1a; https://gitcode.net/sundongsdu/k8s_cluster 1. Vagrant创建…...

8、Docker数据卷与数据卷容器

一、数据卷(Data Volumes) 为了很好的实现数据保存和数据共享&#xff0c;Docker提出了Volume这个概念&#xff0c;简单的说就是绕过默认的联合文件系统&#xff0c;而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。 数据卷 是一个可供一个或多个容器使用的特殊目…...

大数据与Hadoop入门理论

一、大数据的3种数据类型 1、结构化数据 可定义&#xff0c;有类型、格式、结构的强制约束 如&#xff1a;RDBMS&#xff08;关系型数据库管理系统&#xff09; 2、非结构化数据 没有规律没有数据约束可言&#xff0c;很复杂难以解析 如&#xff1a;文本文件&#xff0c;视…...

持续集成部署-k8s-深入了解 Pod:探针

持续集成部署-k8s-深入了解 Pod:探针 1. 探针分类2. 探针探测方式3. 探针参数配置4. 启动探针的应用5. Liveness 探针的应用6. Readiness 探针的应用1. 探针分类 Kubernetes 中的探针是指容器内的进程用于告知 Kubernetes 组件其自身状态的机制; Readiness Probe:就绪探针用…...

来单提醒/客户催单 ----苍穹外卖day9

来单提醒 需求分析 代码开发 注意:前端请求的并不是8080端口;而是先请求Nginx,Nginx进行反向代理以后转发到8080端口 这段代码首先创建了一个orders类用于更新订单状态 并且在更新状态后使用websocket发送给后端提醒 将信息放在map后,使用json的string化方式传给一个接收对象,…...

【单片机】18-红外线遥控

一、红外遥控背景知识 1.人机界面 &#xff08;1&#xff09;当面操作&#xff1a;按键&#xff0c;旋转/触摸按键&#xff0c;触摸屏 &#xff08;2&#xff09;遥控操作&#xff1a;红外遥控&#xff0c;433M/2.4G无线通信【穿墙能力强】&#xff0c;蓝牙-WIFI-Zigbee-LoRa等…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...