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

文章目录

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

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

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

准备工作

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

创建自定义窗口类

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

#include <QApplication>
#include <QWidget>
#include <QMouseEvent>
#include <QDebug>class DraggableWidget : public QWidget
{Q_OBJECTpublic: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.mzph.cn/pingmian/41498.shtml

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

相关文章

SQL Server端口配置指南:最佳实践与技巧

1. 引言 SQL Server通常使用默认端口1433进行通信。为了提高安全性和性能&#xff0c;正确配置SQL Server的端口非常重要。本指南将帮助您了解如何配置和优化SQL Server的端口设置&#xff0c;以满足不同环境和需求。 2. 端口配置基础 2.1 默认端口 SQL Server的默认端口是…

LabVIEW幅频特性测试系统

使用LabVIEW软件开发的幅频特性测试系统。该系统整合了Agilent 83732B信号源与Agilent 8563EC频谱仪&#xff0c;通过LabVIEW编程实现自动控制和数据处理&#xff0c;提供了成本效益高、操作简便的解决方案&#xff0c;有效替代了昂贵的专用仪器&#xff0c;提高了测试效率和设…

一款EF Core下高性能、轻量级针对分表分库读写分离的解决方案

ShardingCore项目介绍 ShardingCore是一款开源、简单易用、高性能、普适性&#xff0c;针对EF Core生态下的分表分库的扩展解决方案&#xff0c;支持EF Core2的所有版本&#xff0c;支持EF Core2的所有数据库、支持自定义路由、动态路由、高性能分页、读写分离的一款EF Core拓展…

华为云生态和快速入门

华为云生态 新技术催生新物种&#xff0c;新物种推动新生态 数字技术催生各类运营商去重塑并颠覆各行业的商业模式 从业务层面看&#xff0c;企业始终如一的目标是业务增长和持续盈利&#xff0c;围绕这些目标衍生出提质、增效、降本、安全、创新和合规的业务诉求&#xff0c…

本迪戈和阿德莱德银行与MongoDB合作, 利用生成式AI对银行核心技术进行现代化改造

MongoDB公司&#xff08;纳斯达克股票代码&#xff1a;MDB&#xff09;近日宣布与本迪戈和阿德莱德银行 (Bendigo and Adelaide Bank&#xff0c;澳大利亚证券交易所股票代码&#xff1a;BEN&#xff09;建立合作伙伴关系。 本迪戈和阿德莱德银行将使用MongoDB Atlas对其银行核…

【PTGui、Pano2VR6、UE4】VR全景拍摄及漫游交互制作操作实例(更新中)

一、基本思路 首先进行VR全景拍摄&#xff0c;获取高质量的全景图像&#xff1b;然后使用PTGui进行图像拼接&#xff0c;确保图像的连续性与准确性&#xff1b;接着利用Pano2VR6进行VR漫游的制作&#xff0c;添加交互元素与多媒体内容&#xff1b;最后进行作品的调试与优化&am…

条件筛选1-4题(30 天 Pandas 挑战)

条件筛选 1. 相关知识点1.1 query条件或查询1.2 query条件与查询1.3 存在查询及列名修改1.4 条件查询&#xff0c;相等1.5 删除重复值1.6 排序 2. 题目2.1 大的国家2.2 可回收且低脂的产品2.3 从不订购的客户2.4 文章浏览 I 1. 相关知识点 1.1 query条件或查询 # |或 world.q…

三星组件新的HBM开发团队加速HBM研发

为应对人工智能(AI)市场扩张带来的对高性能存储解决方案需求的增长&#xff0c;三星电子在其设备解决方案(DS)部门内部成立了全新的“HBM开发团队”&#xff0c;旨在提升其在高带宽存储器(HBM)领域的竞争力。根据Business Korea的最新报告&#xff0c;该团队将专注于推进HBM3、…

CUDA编程基础

文章目录 1、GPU介绍2、CUDA程序进行编译3、CUDA线程模型3.1、一维网格一维线程块3.2、二维网格二维线程块3.3、三维网格三维线程块3.3、不同组合形式 4、nvcc编译流程5、CUDA程序基本架构6、错误检测函数6.1、运行时API错误代码6.2、检查核函数 7、CUDA记时7.1、记时代码7.2、…

期货量化交易:探索金融投资的新领域

在当今快速发展的金融市场中&#xff0c;期货量化交易作为一种新兴的投资策略&#xff0c;正逐渐受到投资者的关注。本文将深入探讨期货量化交易的概念、优势、风险以及其在现代投资组合中的作用&#xff0c;旨在为广大读者提供一个全面而深入的视角。 期货市场概览 期货市场…

Google Earth Engine(GEE)——控制台ui.Textbox复制你想要的textbox

结果 函数: ui.Textbox(placeholder, value, onChange, disabled, style) A textbox that enables the user to input text information. Arguments: placeholder (String, optional): The placeholder text to display when the textbox is empty. Defaults to none. …

VBA语言専攻T3学员领取资料通知0706

T3学员领取资料通知0706 各位学员∶本周MF系列VBA技术资料增加641-645讲&#xff0c;T3学员看到通知后请免费领取,领取时间7月5日晚上19:00-7月6日晚上19:00。本次增加内容&#xff1a; MF641:前个窗体组合框选项联动下个组合框 MF642:工作表中数据选项联动下个数据验证 MF…

技术驱动旅游创新!深度解析景区导览小程序的地图渲染与AR导航技术

随着现代生活节奏的加快&#xff0c;人们在外出旅游时更倾向于轻便出行&#xff0c;携带导览地图已成为过去。然而&#xff0c;面对景区广阔的面积和众多景点&#xff0c;游客常常感到迷茫&#xff0c;难以快速定位到自己所需的地点。景区导览小程序让游客只需搜索景区名称&…

人工智能系列-NumPy(二)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 链接数组 anp.array([[1,2],[3,4]]) print(第一个数组&#xff1a;) print(a) print(\n) bnp.array([[5,6],[7,8]]) print(第二个数组&#xff1a;) print(b) print(\n) print…

zigbee笔记:六、看门狗定时器(Watch Dog)

一、看门狗基础 1、看门狗功能&#xff1a; 由于单片机的工作常常会受到来自外界电磁场的干扰&#xff0c;造成各种寄存器和内存的数据混乱&#xff0c;会导致程序指针错误等&#xff0c;程序运行可能会陷入死循环。程序的正常运行被打断&#xff0c;由单片机控制的系统无法继…

Motion Guidance: 扩散模型实现图像精确编辑的创新方法

在深度学习领域&#xff0c;扩散模型&#xff08;diffusion models&#xff09;因其能够根据文本描述生成高质量图像而备受关注。然而&#xff0c;这些模型在精确编辑图像中对象的布局、位置、姿态和形状方面仍存在挑战。本文提出了一种名为“运动引导”&#xff08;motion gui…

河南新企业如何把握建筑装饰乙级资质办理的最佳时机

河南新企业在办理建筑装饰乙级资质时&#xff0c;把握最佳时机是确保申请过程顺利、高效的关键。以下是一些建议&#xff0c;帮助新企业更好地把握办理时机&#xff1a; 一、了解政策动态与要求 关注政策变动&#xff1a;政策调整往往会影响资质办理的条件、流程和周期。企业…

【数据库了解与学习】

1.下载所需版本安装包 1.1将所需文件压缩包以及安装包放在你选择的任意一盘&#xff0c;新建一个没有文字和空格的文件夹 1.2双击打开安装包&#xff0c;选择Custom自定义模式然后点击右下方的Next 1.4三连点击1&#xff0c;再点击箭头出现3&#xff0c;选中3出现4&#xff0c;…

MySQL——JDBC中对象解释

DriverManager Class.forName("com.mysql.cj.jdbc.Driver"); // 固定写法&#xff0c;加载驱动 Connection connection DriverManager.getConnection(url, username, password); // Connection:代表数据库 // 数据库设置自动提交 // 事务提交 // 自动回滚 connecti…

TypeScript中的类型谓词如何使用

在 TypeScript 中&#xff0c;类型谓词是一种特殊的返回类型&#xff0c;它可以帮助 TypeScript 编译器在特定的代码块中确定变量的具体类型。类型谓词的形式为 parameterName is Type。 interface VNode {__v_isVNode: boolean;// 其他属性... }function isVNode(value: any)…