Qt C++ 实现无边框窗口

Qt C++ 实现无边框窗口

// widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QDebug>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QPushButton>
#include <QString>
#include <QWidget>

#define PADDING 6

enum Location {
    TOP,
    BOTTOM,
    LEFT,
    RIGHT,
    TOP_LEFT,
    TOP_RIGHT,
    BOTTOM_LEFT,
    BOTTOM_RIGHT,
    CENTER
};

class Widget : public QWidget {
    Q_OBJECT

public:
    Widget(QWidget* parent = nullptr);
    ~Widget();

protected:
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);

private:
    void setCursorShape(const QPoint& point);

private:
    // 左键有没有按下
    bool isLeftPressed;
    // 鼠标按下的位置 偏移
    QPoint mouseOffset;
    Location location;
};
#endif  // WIDGET_H


// widget.cpp
#include "widget.h"

Widget::Widget(QWidget* parent) : QWidget(parent) {
    // 设置窗口的宽高
    this->setMinimumWidth(500);
    this->setMinimumHeight(300);

    // 设置背景色
    this->setStyleSheet("background: #303030");

    // 添加两个按钮 - 水平布局
    QHBoxLayout* layout = new QHBoxLayout(this);
    layout->setSpacing(10);
    layout->setContentsMargins(10, 10, 10, 10);

    QPushButton* btn1 = new QPushButton("确定");
    QPushButton* btn2 = new QPushButton("取消");

    layout->addWidget(btn1);
    layout->addWidget(btn2);

    QString style = R"(
        QPushButton {
            background-color: rgb(64, 64, 64);
            font: 16px "Microsoft YaHei";
            color: rgb(200, 200, 200);
            border-radius: 5px;
            padding: 5px;
        }
        QPushButton:hover {
            background-color: rgb(40, 40, 40);
        }
        QPushButton:pressed {
            background-color: rgb(64, 64, 64);
        }
    )";

    btn1->setStyleSheet(style);
    btn2->setStyleSheet(style);

    // 去除标题栏
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);

    this->isLeftPressed = false;

    // 开启鼠标追踪
    this->setMouseTracking(true);
}

Widget::~Widget() {}

void Widget::mousePressEvent(QMouseEvent* event) {
    switch (event->button()) {
        case Qt::RightButton:
            this->close();
            break;
        case Qt::LeftButton:
            this->isLeftPressed = true;
            if (location == CENTER) {
                this->mouseOffset =
                    event->globalPos() - this->frameGeometry().topLeft();
            }
            break;
    }
}

void Widget::mouseMoveEvent(QMouseEvent* event) {
    QPoint globalPos = event->globalPos();

    QRect rect = this->rect();
    QPoint topLeft = mapToGlobal(rect.topLeft());
    QPoint bottomRight = mapToGlobal(rect.bottomRight());

    // 1. 鼠标未按下
    if (!this->isLeftPressed) {
        this->setCursorShape(globalPos);
        return;
    }

    // 2. 鼠标按下, 在CENTER位置按下
    if (this->location == CENTER) {
        move(globalPos - mouseOffset);
        event->accept();
        return;
    }

    // 3. 缩放
    QRect rMove(topLeft, bottomRight);
    switch (location) {
        case TOP:
            // 窗口达到最小高度后,会被鼠标 “向下推走”
            if (bottomRight.y() - globalPos.y() > this->minimumHeight())
                rMove.setY(globalPos.y());
            break;
        case BOTTOM:
            rMove.setHeight(globalPos.y() - topLeft.y());
            break;
        case LEFT:
            if (bottomRight.x() - globalPos.x() > this->minimumWidth())
                rMove.setX(globalPos.x());
            break;
        case RIGHT:
            rMove.setWidth(globalPos.x() - topLeft.x());
            break;
        case TOP_LEFT:
            if (bottomRight.y() - globalPos.y() > this->minimumHeight())
                rMove.setY(globalPos.y());
            if (bottomRight.x() - globalPos.x() > this->minimumWidth())
                rMove.setX(globalPos.x());
            break;
        case TOP_RIGHT:
            if (bottomRight.y() - globalPos.y() > this->minimumHeight())
                rMove.setY(globalPos.y());
            rMove.setWidth(globalPos.x() - topLeft.x());
            break;
        case BOTTOM_LEFT:
            rMove.setHeight(globalPos.y() - topLeft.y());
            if (bottomRight.x() - globalPos.x() > this->minimumWidth())
                rMove.setX(globalPos.x());
            break;
        case BOTTOM_RIGHT:
            rMove.setHeight(globalPos.y() - topLeft.y());
            rMove.setWidth(globalPos.x() - topLeft.x());
            break;
        default:
            break;
    }
    this->setGeometry(rMove);
}

void Widget::mouseReleaseEvent(QMouseEvent* event) {
    if (event->button() == Qt::LeftButton) {
        isLeftPressed = false;
    }
}

void Widget::setCursorShape(const QPoint& point) {
    QRect rect = this->rect();
    QPoint topLeft = mapToGlobal(rect.topLeft());
    QPoint bottomRight = mapToGlobal(rect.bottomRight());

    int x = point.x();
    int y = point.y();

    if (x >= topLeft.x() && x <= topLeft.x() + PADDING && y >= topLeft.y() &&
        y <= topLeft.y() + PADDING) {
        // 左上角
        location = TOP_LEFT;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));
    } else if (x <= bottomRight.x() && x >= bottomRight.x() - PADDING &&
               y <= bottomRight.y() && y >= bottomRight.y() - PADDING) {
        // 右下角
        location = BOTTOM_RIGHT;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));
    } else if (x >= topLeft.x() && x <= topLeft.x() + PADDING &&
               y <= bottomRight.y() && y >= bottomRight.y() - PADDING) {
        // 左下角
        location = BOTTOM_LEFT;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    } else if (x <= bottomRight.x() && x >= bottomRight.x() - PADDING &&
               y >= topLeft.y() && y <= topLeft.y() + PADDING) {
        // 右上角
        location = TOP_RIGHT;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    } else if (x >= topLeft.x() && x <= topLeft.x() + PADDING) {
        // 左边
        location = LEFT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    } else if (x >= bottomRight.x() - PADDING && x <= bottomRight.x()) {
        // 右边
        location = RIGHT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    } else if (y >= topLeft.y() && y <= topLeft.y() + PADDING) {
        // 上边
        location = TOP;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    } else if (y >= bottomRight.y() - PADDING && y <= bottomRight.y()) {
        // 下边
        location = BOTTOM;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    } else {
        location = CENTER;
        this->setCursor(QCursor(Qt::ArrowCursor));
    }
}


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java入门基础知识第八课(数组)——冒泡排序、Arrays工具类

前面二白讲了关于数组的概念、语法以及简单的输入输出&#xff0c;实际上关于数组的知识还有很多&#xff0c;接下来咱们讲一下冒泡排序以及一些常用的Arrays工具类&#xff0c;需要记忆的知识很多&#xff0c;而且容易混淆。 一、冒泡排序 简介&#xff08;原理&#xff09;…

基于SpringBoot的“银行OA系统的设计与实现”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“银行OA系统的设计与实现”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 用户登录界面 管理员主界面 员工基本档…

知道做到 一篇总结学习方法的笔记

元数据 [!abstract] 知道做到&#xff1a;跃迁式学习 书名&#xff1a; 知道做到&#xff1a;跃迁式学习作者&#xff1a; 彼得•霍林斯简介&#xff1a; 学习是改善你的生活环境、成为你想成为的人的关键。科学的方法能加速学习进程&#xff0c;让你事半功倍。技能、信息和能力…

openkylin系统通过网线连接ubuntukylin系统上网攻略

openkylin系统通过网线连接ubuntukylin系统上网攻略 主机1&#xff1a;x64 amd &#xff0c;系统&#xff1a;ubuntukylin 22.04 &#xff0c;状态&#xff1a;通过wifi连接热点进行上网&#xff0c;并共享网络。 主机2&#xff1a;x64 intel &#xff0c;系统&#xff1a;ope…

5.x 版本 CallKit SDK 无法弹起通话界面

5.x 版本 CallKit SDK 作为接听方在前台的情况下无法弹起通话界面&#xff0c;作为拨打方能正常弹起通话界面 分析&#xff08;根因分析、需求分析&#xff09; CallKit SDK 初始化依赖于 IMKit SDK 初始化&#xff0c;如果您使用 IMLib SDK 的方法初始化的话&#xff0c;会导…

告别百年激进笔记

系列文章目录 八次危机笔记 告别百年激进笔记 文章目录 系列文章目录前言导图第一部分 资本全球化的宏大叙事第一节 人类创造的两个异化物第二节 全球资本化与制度性致贫第三节 国家竞争的“微笑曲线”第四节 欧债危机实属政治危机第五节 日本研究中的另类思考第六节 从…

流程图的新语法-mermaid的快速使用--推荐

chatgpt或者现在的大数据采用的流程图给出的代码如下&#xff1a; graph TD;A[接收客户请求] --> B[问题分类];B --> C[技术支持];B --> D[维修服务];C --> E[远程解决];C --> F[现场支持];D --> G[维修完成];G --> H[服务反馈];style A fill:#f9f,strok…

【数据结构与算法】贪心算法及例题

目录 贪心算法例题一&#xff1a;找零问题例题二&#xff1a;走廊搬运物品最优方案问题输入样例例题三&#xff1a;贪心自助餐 贪心算法 贪心算法是一种在每一步选择中都采取当前状态下最优的选择&#xff0c;以期望最终达到全局最优解的算法。它的核心思想是每次都选择当前最…

即插即用模块详解SCConv:用于特征冗余的空间和通道重构卷积

目录 一、摘要 二、创新点说明 2.1 Methodology 2.2SRU for Spatial Redundancy​编辑 2.3CRU for Channel Redundancy 三、实验 3.1基于CIFAR的图像分类 3.2基于ImageNet的图像分类 3.3对象检测 四、代码详解 五、总结 论文&#xff1a;https://openaccess.thecvf.c…

kafka的概念以及Zookeeper集群 + Kafka集群 +elfk集群

目录 zookeeper同步过程 分布式通知和协调 zookeeper同步过程 分布式通知和协调 准备 3 台服务器做 Zookeeper 集群 192.168.68.5 192.168.68.6 192.168.68.7 安装前准备 //关闭防火墙 systemctl stop firewalld systemctl disable firewalld setenforce 0 node1服务器&a…

Linux进阶篇:性能监控工具:socket 统计信息

Linux性能监控工具&#xff1a;socket 统计信息 1 ss命令介绍 ss 是 Socket Statistics 的缩写。ss 命令可以用来获取 socket 统计信息&#xff0c;它显示的内容和 netstat 类似。但 ss 的优势在于它能够显示更多更详细的有关 TCP 和连接状态的信息&#xff0c;而且比 netsta…

ssm052游戏攻略网站的设计与实现+vue

游戏攻略网站设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本游戏攻略网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处…

使用avx2 指令集加速向量算法运算

使用cpu-z 查看cpu指令集 2 向量加&#xff0c;乘法&#xff0c;除法 我们使用向量加&#xff0c;为什么函数是0 到 8 的计算&#xff0c;因为avx2 寄存器为256位&#xff0c;同时设置启动增强指令集 #include <immintrin.h> // 引入包含AVX2指令集的头文件void vecto…

2024认证杯数学建模A题保暖纤维保暖能力原创论文讲解(含完整python代码)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了认证杯数学中国数学建模网络挑战赛第一阶段A题目保暖纤维的保暖能力完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品…

【Conda基础命令】使用conda创建、查看、删除虚拟环境及可能的报错处理

文章目录 前言&#xff08;1&#xff09; 在默认路径下创建一个新的虚拟环境&#xff08;2&#xff09; 查看已有的虚拟环境&#xff08;3&#xff09; 删除已有的虚拟环境&#xff08;谨慎操作&#xff09;&#xff08;4&#xff09;激活虚拟环境&#xff08;5&#xff09;退出…

社区养老服务系统|基于springboot社区养老服务系统设计与实现(源码+数据库+文档)

社区养老服务系统目录 目录 基于springboot社区养老服务系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员部分功能 &#xff08;1&#xff09; 用户管理 &#xff08;2&#xff09;服务种类管理 &#xff08;3&#xff09;社区服务管理 &#xff08…

STM32F103ZE-中断

文章目录 122.12.22.32.42.52.62.6.12.6.2 33.13.23.34.14.3 56788.18.2 NVIC 管理所有中断EXTI 外部中断事件控制器 针对外部 可以看成NVIC 下属 1 中断和 中止&#xff08;不回去了&#xff09;不一样 搁一段时间就如果不用中断 用while&#xff08;&#xff09; 可能夹半天…

中伟视界:智慧矿山智能化预警平台功能详解

矿山智能预警平台是一种高度集成化的安全监控系统&#xff0c;它能够提供实时的监控和报警功能&#xff0c;帮助企业和机构有效预防和响应潜在的安全威胁。以下是矿山智能预警平台的一些关键特性介绍&#xff1a; 报警短视频生成&#xff1a; 平台能够在检测到报警时自动生成短…

记录一次内存溢出

1、查看catalina相关日志&#xff0c;确定关键字相关行号 文件&#xff1a;catalina.out命令1&#xff1a;cat -n catalina.out |grep -a OutOfMemoryError与内存溢出相关的如上&#xff0c;每一个行号其实都对应到具体时间点。可以发现&#xff0c;这个范围相符合&#xff1…

Harbor安装手册

安装Docker yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager \ --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i -e /mirrors.cloud.aliyuncs.com/d -e /mirrors.aliyuncs.com/d \ /etc/yum.repos.d/…
最新文章