使用 Qt 实现自定义拖动窗口

文章目录

      • 如何在 Qt 中实现无标题栏窗口的拖动
        • 准备工作
        • 创建自定义窗口类
        • 使用 `QDialog` 实现拖动功能
        • 详细解释
        • 代码行解释
      • 小结

如何在 Qt 中实现无标题栏窗口的拖动

在许多桌面应用程序中,我们经常需要自定义窗口外观,包括去掉标题栏,使窗口看起来更加现代和美观。然而,去掉标题栏也意味着失去了通过标题栏拖动窗口的功能。在这篇博客中,我将介绍如何在 Qt 中实现鼠标拖动无标题栏窗口的功能。

准备工作

首先,我们需要创建一个基于 QWidgetQDialog 的自定义窗口类。在这个类中,我们将重写鼠标事件处理函数:mousePressEventmouseMoveEventmouseReleaseEvent,以实现拖动功能。

创建自定义窗口类

让我们从创建一个基本的 Qt 应用程序开始,并定义一个 DraggableWidget 类。下面是一个基于 QWidget 的示例:

#include <QApplication>
#include <QWidget>
#include <QMouseEvent>
#include <QDebug>

class DraggableWidget : public QWidget
{
    Q_OBJECT

public:
    DraggableWidget(QWidget *parent = nullptr) : QWidget(parent), isDragging(false)
    {
        // 设置无标题栏窗口
        setWindowFlag(Qt::FramelessWindowHint);
        setAttribute(Qt::WA_DeleteOnClose);
        resize(400, 300); // 设置窗口大小
    }

protected:
    void mousePressEvent(QMouseEvent *event) override
    {
        if (event->button() == Qt::LeftButton) { // 检查是否按下了鼠标左键
            isDragging = true; // 设置拖动状态为真,表示开始拖动
            dragPosition = event->globalPos() - frameGeometry().topLeft(); // 记录鼠标按下时的全局位置与窗口左上角位置的差值
            event->accept(); // 接受事件,防止事件进一步传播
        }
        return QWidget::mousePressEvent(event); // 调用基类的 mousePressEvent 以确保默认行为被执行
    }

    void mouseMoveEvent(QMouseEvent *event) override
    {
        if (isDragging && (event->buttons() & Qt::LeftButton)) { // 检查是否正在拖动并且左键仍然按下
            move(event->globalPos() - dragPosition); // 计算并设置窗口的新位置
            event->accept(); // 接受事件,防止事件进一步传播
        }
        return QWidget::mouseMoveEvent(event); // 调用基类的 mouseMoveEvent 以确保默认行为被执行
    }

    void mouseReleaseEvent(QMouseEvent *event) override
    {
        if (event->button() == Qt::LeftButton) { // 检查是否释放了鼠标左键
            isDragging = false; // 设置拖动状态为假,表示停止拖动
            event->accept(); // 接受事件,防止事件进一步传播
        }
        return QWidget::mouseReleaseEvent(event); // 调用基类的 mouseReleaseEvent 以确保默认行为被执行
    }

private:
    bool isDragging; // 是否正在拖动
    QPoint dragPosition; // 记录拖动时鼠标位置和窗口左上角位置的差值
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    DraggableWidget window;
    window.show();

    return app.exec();
}
使用 QDialog 实现拖动功能

如果您的窗口类是基于 QDialog,实现方式类似。下面是一个基于 QDialog 的示例:

#include "startdialog.h"
#include "ui_startdialog.h"
#include <QMouseEvent>
#include <QDebug>

StartDialog::StartDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::StartDialog)
{
    ui->setupUi(this);
    setWindowFlag(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_DeleteOnClose);
    ui->lineEditPwd->setEchoMode(QLineEdit::Password);

    initialize();
}

StartDialog::~StartDialog()
{
    delete ui;
}

void StartDialog::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) { // 检查是否按下了鼠标左键
        mouse = true; // 设置拖动状态为真,表示开始拖动
        dragPosition = event->globalPos() - frameGeometry().topLeft(); // 记录鼠标按下时的全局位置与窗口左上角位置的差值
        event->accept(); // 接受事件,防止事件进一步传播
    }
    return QDialog::mousePressEvent(event); // 调用基类的 mousePressEvent 以确保默认行为被执行
}

void StartDialog::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) { // 检查是否释放了鼠标左键
        mouse = false; // 设置拖动状态为假,表示停止拖动
        event->accept(); // 接受事件,防止事件进一步传播
    }
    return QDialog::mouseReleaseEvent(event); // 调用基类的 mouseReleaseEvent 以确保默认行为被执行
}

void StartDialog::mouseMoveEvent(QMouseEvent *event)
{
    if (mouse && (event->buttons() & Qt::LeftButton)) { // 检查是否正在拖动并且左键仍然按下
        move(event->globalPos() - dragPosition); // 计算并设置窗口的新位置
        event->accept(); // 接受事件,防止事件进一步传播
    }
    return QDialog::mouseMoveEvent(event); // 调用基类的 mouseMoveEvent 以确保默认行为被执行
}
详细解释
  1. 设置无标题栏窗口

    • 使用 setWindowFlag(Qt::FramelessWindowHint) 去掉窗口的标题栏。
    • 使用 setAttribute(Qt::WA_DeleteOnClose) 确保窗口关闭时释放资源。
  2. 实现拖动逻辑

    • mousePressEvent 中,检查鼠标左键按下事件,记录按下时的鼠标位置与窗口左上角位置的差值,并标记为拖动状态。
    • mouseMoveEvent 中,检查是否在拖动状态,并根据当前鼠标位置计算窗口的新位置。
    • mouseReleaseEvent 中,检查鼠标左键释放事件,停止拖动状态。
代码行解释
  • dragPosition = event->globalPos() - frameGeometry().topLeft();:计算鼠标按下时的全局位置和窗口左上角位置的差值,这个差值在拖动过程中保持不变,用于计算新的窗口位置。
  • move(event->globalPos() - dragPosition);:根据当前鼠标位置和记录的差值计算窗口的新位置,并移动窗口。
  • event->accept();:接受事件,防止事件进一步传播给其他控件或处理程序。
  • return QDialog::mousePressEvent(event); 和类似的 mouseReleaseEvent 以及 mouseMoveEvent:调用基类的事件处理函数,确保默认行为被执行。

小结

通过重写 mousePressEventmouseMoveEventmouseReleaseEvent 函数,我们可以在没有标题栏的窗口中实现拖动功能。这种方法在需要自定义窗口外观的应用程序中非常有用。

希望这篇博客能帮助您在 Qt 应用程序中实现拖动无标题栏窗口的功能。如果您有任何问题或建议,请在下方留言讨论。感谢您的阅读!

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

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

相关文章

Spring AOP、Spring MVC工作原理、发展演变、常用注解

Spring AOP 概念 AOP全称为Aspect Oriented Programming&#xff0c;表示面向切面编程。切面指的是将那些与业务无关&#xff0c;但业务模块都需要使用的功能封装起来的技术。 AOP基本术语 **连接点&#xff08;Joinpoint&#xff09;&#xff1a;**连接点就是被拦截到的程序执…

智能文档革新:合合信息智能文档处理平台上线基金合同抽取模型!

一、什么是基金合同&#xff1f; 基金合同是指具有平等地位主体的基金当事人在基金活动中&#xff0c;为规范其间的权利、义务&#xff0c;依意思表示一致而形成的契约或协议。《证券投资基金法》第五十二条规定&#xff0c;公开募集基金的基金合同应当包括下列内容: &#x…

软件游戏d3dcompiler_43.dll丢失怎么办,总结几种有效的方法

在使用电脑时&#xff0c;可能会碰到找不到d3dcompiler_43.dll的问题。即在使用过程中&#xff0c;突然弹出一个提示“d3dcompiler_43.dll丢失”&#xff0c;由于此文件的缺失&#xff0c;部分程序将无法启动。为恢复正常使用&#xff0c;我们需要修复此文件。接下来&#xff0…

【C++】 解决 C++ 语言报错:Undefined Reference

文章目录 引言 未定义引用&#xff08;Undefined Reference&#xff09;是 C 编程中常见的错误之一&#xff0c;通常在链接阶段出现。当编译器无法找到函数或变量的定义时&#xff0c;就会引发未定义引用错误。这种错误会阻止生成可执行文件&#xff0c;影响程序的正常构建。本…

Java项目:基于SSM框架实现的中小企业人力资源管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的中小企业人力资源管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简…

matlab 绘制高等数学中的二维函数示例

matlab 绘制高等数学中的二维函数示例 绘制高等数学中的二维函数示例绘制结果 绘制高等数学中的二维函数示例 clc,clear,close all; % 定义方程 eqn (x, y) (x.^2 y.^2).^3 - y.^4;% 绘制方程曲线和坐标轴 ezplot(eqn, [-2, 2, -2, 2]) hold on % 在同一图形中保持绘图% 绘…

国际上备考所有云计算/IT证书的五大优质免费课程网站

最近越来越多的小伙伴来问小李哥&#xff0c;小李哥亚马逊云科技AWS认证大满贯是在哪里上课复习的呢&#xff1f;全部上付费课程那不是一笔巨款吗&#xff1f;小李哥这次来盘点备考国际上IT证书的5大优质免费课程网站(不只是亚马逊云科技AWS的课程&#xff0c;其他课程同样可以…

满足GMSL静电防护要求的方案

什么是GMSL&#xff1f;它是做什么用的&#xff1f;它有什么优点&#xff1f;设计GMSL防静电有啥难度&#xff1f; 带着这些疑问我们先了解下什么是GMSL。 一&#xff0e;简述 GMSL GMSL&#xff08;Gigabit Multimedia Serial Link&#xff09;即千兆多媒体串行链路&#xf…

odoo 物联网 设备数据采集方案

图一 架构手稿(许老师专属) 图二 架构简图 部署 方案一&#xff1a; odoo业务数据库与设备采集数据库使用一个instance。 缺点&#xff1a;重启pg服务相互影响。 方案二&#xff1a; odoo业务数据库与设备采集数据库独立部署&#xff0c;使用两个instance。 优点&#xff1a;…

一个使用率超高的大数据实验室是如何练成的?

厦门大学嘉庚学院“大数据应用实训中心”&#xff08;以下简称“实训中心”&#xff09;自2022年建成以来&#xff0c;已经成为支撑“大数据专业”复合型人才培养的重要支撑&#xff0c;目前实训中心在专业课程实验教学、项目实训、数据分析类双创比赛、毕业设计等方面都有深入…

CVPR2024自动驾驶轨迹预测方向的论文整理

2024年自动驾驶轨迹预测方向的论文汇总 1、Producing and Leveraging Online Map Uncertainty in Trajectory Prediction 论文地址&#xff1a;https://arxiv.org/pdf/2403.16439 提出针对在线地图不确定性带给轨迹预测的影响对应的解决方案。 在轨迹预测中&#xff0c;利用在…

vscode连接SSH——连接学校服务器,使用conda配置个人环境并使用

服务器的连接 在vscode远程资源管理中配置配置文件&#xff0c;如下图&#xff1a; 然后点击左下角进行连接&#xff1a; 点击需要连接的服务器&#xff0c;输入对应密码即可登录成功。 服务器上创建自己的环境 确保服务器上已安装anaconda。 先查看服务器上的conda信息&…

Linux_共享内存通信

目录 1、共享内存原理 2、申请共享内存 2.1 ftok 2.2 测试shmget、ftok 2.3 查看系统下的共享内存 3、关联共享内存 3.1 测试shmat 4、释放共享内存 4.1 测试shmctl 5、实现共享内存通信 6、共享内存的特性 结语 前言&#xff1a; 在Linux下&#xff0c;有一…

jenkins在使用pipeline时,为何没有方块形视图

项目场景&#xff1a; 安装完Jenkins时后&#xff0c;通过pipeline创建的项目任务。 问题描述 在立即构建后&#xff0c;没有显示每个阶段的视图。 原因分析&#xff1a; 原因是&#xff0c;刚安装的Jenkins&#xff0c;这个视图不是Jenkins自带的功能&#xff0c;而必须安装…

Cannot resolve symbol ‘log`

idea里的代码log变红色&#xff0c;是因为缺少Lombok插件。 安装lombok插件即可。安装完应用&#xff0c;重启软件就好了。 依次点击菜单栏中的 File → Settings&#xff08;Windows/Linux&#xff09; 或 IntelliJ IDEA → Preferences&#xff08;macOS&#xff09;。在设置…

设计模式探索:单例模式

1. 什么是单例模式? 定义: 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一种全局访问点以访问该实例。常见的场景包括身份证号码、政府等需要唯一实例的情况。 单例模式通常用于那些需要在应用程序中仅存在一个实例的情况,例如配置管理器、线程池、数据…

ret2syscall简单总结

主要是自己的简单的学习总结。 知识点 关于系统调用如何传递参数问题&#xff0c;即系统调用约定&#xff08;syscall&#xff0c;int 80h&#xff0c;svc&#xff09;_int 80h intel汇编用法-CSDN博客 ret2syscall的做题思路&#xff08;以32位程序为例&#xff09; - ZikH…

2024年【山东省安全员A证】考试试卷及山东省安全员A证考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 山东省安全员A证考试试卷根据新山东省安全员A证考试大纲要求&#xff0c;安全生产模拟考试一点通将山东省安全员A证模拟考试试题进行汇编&#xff0c;组成一套山东省安全员A证全真模拟考试试题&#xff0c;学员可通过…

react 项目中预防xss攻击的插件 dompurify

一、安装 $ yarn add dompurify $ yarn add --dev types/dompurify 二、使用 import DOMPurify from dompurify;// 1、处理&#xff1a; DOMPurify.sanitize(htmlContent)// 2、之后放进 dangerouslySetInnerHTML dangerouslySetInnerHTML{{ __html: cleanHTML }} 如&#…

Django自动生成Swagger接口文档 —— Python

1. 前言 当接口开发完成&#xff0c;紧接着需要编写接口文档。传统的接口文档通常都是使用Word或者一些接口文档管理平台进行编写&#xff0c;但此类接口文档维护更新比较麻烦&#xff0c;每次接口有变更&#xff0c;需要手动修改接口文档。在实际的工作中&#xff0c;经常会遇…