Qt C++ 实现无边框窗口

这篇具有很好参考价值的文章主要介绍了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));
    }
}


文章来源地址https://www.toymoban.com/news/detail-854084.html

到了这里,关于Qt C++ 实现无边框窗口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化

    Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化 1、main.cpp 2、widget.h 3、widget.cpp 4、效果展示 5、完成

    2024年02月16日
    浏览(64)
  • Qt窗口设置无边框不能移动,鼠标穿透后不能响应点击事件

      最近在做一个迷你小工具,准备干点不可描述的事情,想要短小强悍,始终在最顶层显示,同时不要自带的关闭按钮和边框,百度一下,发现是需要设置如下两个属性:   那么问题来了,这样的话一运行窗体就在正中间,而且无法拖动,就像这样   哪怕对于我这种

    2024年02月10日
    浏览(59)
  • C++界面开发框架Qt 6.x入门指南 - 拥有程序主窗口

    Qt技术交流群:166830288      欢迎一起进群讨论 点击获取Qt组件下载 Qt Widget 是桌面环境中典型的用户界面元素,这些小部件很好地集成到底层平台,在 Windows、Linux 和 macOS 上提供原生外观。 这些小部件成熟且具有丰富的用户界面元素,适用于大多数传统用户界面。 与 

    2024年02月05日
    浏览(45)
  • 06-5_Qt 5.9 C++开发指南_Splash 与登录窗口(MouseEvent鼠标事件;注册表;加密)

    一般的大型应用程序在启动时会显示一个启动画面,即 Splash 窗口。Splash 窗口是一个无边对话框,一般显示一个图片,展示软件的信息。Splash 窗口显示时,程序在后台做一些比较耗时的启动准备工作,Splash 窗口显示一段时间后自动关闭,然后软件的主窗口显示出来。Qt有一个

    2024年02月13日
    浏览(45)
  • 【VisualStudio】使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月10日
    浏览(76)
  • 【Visual Studio】Qt 的实时绘图曲线功能,使用 C++ 语言,配合 Qt 开发串口通信界面

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 战斗背景:做了个串口接收界面,用来接收传输过来的信号。但是光用数字显示太单调,需要用图线显示出来。 战略目标:干掉它。 战术路线:Qt 绘图可以使用 Qt Charts,先了解

    2024年02月11日
    浏览(49)
  • 【VisualStudio】基于 Visual Studio 使用 C++ 语言开发 Qt 环境配置教程

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 先上一张效果图,具体步骤主要分为以下三步。 这一步不再赘述,注意一定要安装 C++ 语言。 可以参考这个教程 Visual Studio 2022安装与使用教程。 这一步也不再赘述,网上搜索教

    2024年02月15日
    浏览(66)
  • 【Visual Studio】使用 C++ 语言,配合 Qt,开发了一个串口通信界面

    知识不是单独的,一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏:Visual Studio。 我要使用的功能比较简单,主要包含扫描串口、打开串口、发送数据、接收数据、暂停按钮、停止按钮,因此接下里将围绕这几个功能依次更新。 我的工程项目名字叫 “GUI”。

    2024年02月11日
    浏览(68)
  • Qt 中动态加载窗口(C++)

    在编程中,我经常会遇见要根据用户触发按钮,动态生成窗口的情况。在此有两种方法可以动态生成窗口:一:直接在槽函数中调用窗口类。二:将 **.ui 添加到资源文件,通过 QUiLoader 加载。 现将两种方法介绍如下。 在 Qt 中创建 Qt 设计师界面类 一: 1)在函数中实例化窗体

    2024年02月11日
    浏览(38)
  • C++,使用Qt设计一个登录窗口

    要求如下: 1、给窗体改变名称并设置窗口图标、尺寸固定 2、中间放log图 3、用户名和密码使用图片完成 4、账户用明文模式,密码用密文模式 5、点击登录后,将界面上的用户名和“admin”比较,密码和“123456”比较,如果匹配成功,则输出登录成功,如果匹配失败,则输出

    2024年02月12日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包