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

Qt6实战:用setGeometry和事件过滤器,实现一个可拖拽调整大小的自定义控件(附完整源码)

Qt6实战打造可拖拽调整大小的Photoshop风格浮动面板在图形界面开发中能够自由拖拽和调整大小的浮动面板是专业级应用的标配功能。就像Photoshop的工具箱那样用户可以随心所欲地摆放工作区组件。本文将带你用Qt6实现这样一个工业级交互控件核心在于巧妙运用setGeometry和事件过滤器系统。1. 项目结构与基础控件搭建我们先创建一个继承自QWidget的自定义面板类DraggablePanel。这个类将作为我们可交互浮动面板的基础框架。以下是头文件的基本结构#include QWidget #include QMouseEvent class DraggablePanel : public QWidget { Q_OBJECT public: explicit DraggablePanel(QWidget *parent nullptr); protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent *event) override; private: QPoint dragStartPosition; bool isDragging false; bool isResizing false; QRect resizeStartGeometry; };实现文件中我们先完成构造函数和基本外观设置DraggablePanel::DraggablePanel(QWidget *parent) : QWidget(parent) { setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); setAttribute(Qt::WA_TranslucentBackground); setFixedSize(200, 300); // 设置半透明背景和边框 setStyleSheet(background-color: rgba(50, 50, 50, 200); border: 1px solid #444; border-radius: 4px;); }2. 实现拖拽移动功能拖拽功能的核心是跟踪鼠标位置变化并实时更新控件位置。我们通过重写鼠标事件处理函数来实现void DraggablePanel::mousePressEvent(QMouseEvent *event) { if (event-button() Qt::LeftButton) { dragStartPosition event-globalPosition().toPoint() - frameGeometry().topLeft(); isDragging true; event-accept(); } } void DraggablePanel::mouseMoveEvent(QMouseEvent *event) { if (isDragging (event-buttons() Qt::LeftButton)) { QPoint newPos event-globalPosition().toPoint() - dragStartPosition; move(newPos); event-accept(); } } void DraggablePanel::mouseReleaseEvent(QMouseEvent *event) { if (event-button() Qt::LeftButton) { isDragging false; event-accept(); } }这里有几个关键点需要注意使用globalPosition()获取屏幕坐标而非窗口相对坐标通过frameGeometry()获取包含窗口装饰的完整几何信息在移动操作中保持控件与鼠标的相对位置不变3. 添加边缘调整大小功能更专业的实现是允许用户从面板边缘拖动来调整大小。我们需要先检测鼠标是否位于可调整的边缘区域enum ResizeEdge { None 0, Left 1, Right 2, Top 4, Bottom 8 }; // 在mousePressEvent中添加边缘检测 const int edgeMargin 5; int edge None; QPoint pos event-pos(); if (pos.x() edgeMargin) edge | Left; if (pos.x() width() - edgeMargin) edge | Right; if (pos.y() edgeMargin) edge | Top; if (pos.y() height() - edgeMargin) edge | Bottom; if (edge ! None) { isResizing true; resizeStartGeometry geometry(); resizeEdge edge; return; }然后修改mouseMoveEvent来处理大小调整void DraggablePanel::mouseMoveEvent(QMouseEvent *event) { if (isResizing) { QRect newGeometry resizeStartGeometry; QPoint delta event-globalPosition().toPoint() - dragStartPosition; if (resizeEdge Left) { newGeometry.setLeft(newGeometry.left() delta.x()); if (newGeometry.width() minimumWidth()) { newGeometry.setLeft(newGeometry.right() - minimumWidth()); } } // 类似处理Right/Top/Bottom边缘... setGeometry(newGeometry); return; } // 原有的拖拽代码... }4. 使用事件过滤器优化交互直接重写事件处理函数有时会显得笨重。Qt的事件过滤器系统提供了更灵活的解决方案// 在构造函数中安装事件过滤器 qApp-installEventFilter(this); // 实现事件过滤器 bool DraggablePanel::eventFilter(QObject *watched, QEvent *event) { if (watched this) { switch (event-type()) { case QEvent::MouseButtonPress: // 处理鼠标按下 break; case QEvent::MouseMove: // 处理鼠标移动 break; case QEvent::MouseButtonRelease: // 处理鼠标释放 break; default: break; } } return QWidget::eventFilter(watched, event); }事件过滤器的优势在于可以监控多个对象的交互能够处理更复杂的事件序列便于实现跨控件的交互逻辑5. 完整实现与效果优化将上述功能整合后我们还需要考虑一些细节优化边缘视觉反馈void DraggablePanel::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 绘制可调整大小的边缘指示器 const int edgeSize 3; painter.setPen(Qt::NoPen); painter.setBrush(QColor(100, 100, 100, 150)); if (resizeEdge Left) painter.drawRect(0, 0, edgeSize, height()); // 其他边缘类似... }边界限制// 在调整大小时确保最小尺寸 void DraggablePanel::setGeometry(const QRect rect) { QRect finalRect rect; finalRect.setWidth(qMax(minimumWidth(), rect.width())); finalRect.setHeight(qMax(minimumHeight(), rect.height())); QWidget::setGeometry(finalRect); }完整使用示例int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow mainWindow; DraggablePanel *panel new DraggablePanel(mainWindow); panel-show(); mainWindow.show(); return app.exec(); }6. 高级功能扩展对于更专业的实现可以考虑添加以下功能停靠系统enum DockPosition { Floating, LeftDocked, RightDocked, TopDocked, BottomDocked }; void DraggablePanel::dockTo(DockPosition position) { if (position Floating) { setWindowFlags(windowFlags() | Qt::Tool); show(); return; } // 实现停靠逻辑... }布局记忆// 保存布局到设置 void DraggablePanel::saveLayout(QSettings settings) { settings.setValue(geometry, saveGeometry()); settings.setValue(floating, isFloating()); settings.setValue(dockPosition, dockPosition); } // 从设置恢复布局 void DraggablePanel::restoreLayout(QSettings settings) { restoreGeometry(settings.value(geometry).toByteArray()); // 恢复其他状态... }多面板协调// 管理多个面板的Z-order void PanelManager::bringToFront(DraggablePanel *panel) { foreach (DraggablePanel *p, panels) { if (p ! panel) { p-lower(); } } panel-raise(); }在实际项目中使用这个自定义面板时我发现边缘检测的灵敏度需要仔细调校。太小的边缘区域会让用户难以捕捉而太大的区域又会影响内容区域的交互。经过多次测试5-8像素的边缘范围通常能提供最佳用户体验。

相关文章:

Qt6实战:用setGeometry和事件过滤器,实现一个可拖拽调整大小的自定义控件(附完整源码)

Qt6实战:打造可拖拽调整大小的Photoshop风格浮动面板 在图形界面开发中,能够自由拖拽和调整大小的浮动面板是专业级应用的标配功能。就像Photoshop的工具箱那样,用户可以随心所欲地摆放工作区组件。本文将带你用Qt6实现这样一个工业级交互控件…...

别再手动对齐轨迹了!用evo的-a和-s参数,5分钟搞定SLAM轨迹评估与可视化

别再手动对齐轨迹了!用evo的-a和-s参数,5分钟搞定SLAM轨迹评估与可视化 刚接触SLAM或视觉里程计的朋友们,是否曾被这样的场景困扰:明明算法输出的轨迹形状与真实轨迹相似,但两条曲线在坐标系中错位明显,根本…...

快速掌握开源工具:3分钟实现高效电子书转换

快速掌握开源工具:3分钟实现高效电子书转换 【免费下载链接】anyflip-downloader Download anyflip books as PDF 项目地址: https://gitcode.com/gh_mirrors/an/anyflip-downloader 你是否曾为在线电子书无法离线保存而烦恼?当网络不稳定或需要随…...

从GSM到5G NR:手把手教你用ADS2022的【Sources - Modulated】面板搭建通信系统仿真

从GSM到5G NR:用ADS2022构建完整通信系统仿真的实战指南 在无线通信系统设计中,仿真环节往往决定着产品研发的成败。Keysight的ADS2022作为行业标杆工具,其Sources - Modulated面板提供的丰富信号源模型,能够精准模拟从2G到5G的各…...

5步完成AI模型部署:DeepStream-Yolo实战终极指南

5步完成AI模型部署:DeepStream-Yolo实战终极指南 【免费下载链接】DeepStream-Yolo NVIDIA DeepStream SDK 8.0 / 7.1 / 7.0 / 6.4 / 6.3 / 6.2 / 6.1.1 / 6.1 / 6.0.1 / 6.0 / 5.1 implementation for YOLO models 项目地址: https://gitcode.com/gh_mirrors/de/…...

VisualCppRedist AIO:一站式解决Windows DLL缺失问题的智能方案

VisualCppRedist AIO:一站式解决Windows DLL缺失问题的智能方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况&#xf…...

抖音下载器完整教程:免费无水印批量下载的终极解决方案

抖音下载器完整教程:免费无水印批量下载的终极解决方案 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback supp…...

别再让用户清缓存了!React/Vue项目里这个ServiceWorker配置不改,上线就踩坑

彻底解决React/Vue项目线上缓存问题的工程化实践 每次发布新版本后,用户反馈页面不更新?这可能是ServiceWorker在"好心办坏事"。作为前端开发者,我们都遇到过这样的场景:本地测试一切正常,但上线后用户却看不…...

3小时变3分钟:Dify Workflow可视化开发终极指南

3小时变3分钟:Dify Workflow可视化开发终极指南 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程,自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/aw/Awesome-Dify-Workfl…...

告别单调Slider!手把手教你用C#为Unity UI组件扩展自定义事件(附源码下载)

突破原生限制:C#与Unity深度整合打造高交互性Slider组件 在游戏开发中,UI交互体验往往决定了产品的第一印象。Unity内置的Slider组件虽然提供了基础功能,但在实际项目中,我们经常需要更精细的交互控制——比如精确捕捉拖拽开始和结…...

基恩士DL-EP1与欧姆龙PLC的EIP通信实战:从IP配置到数据读取

1. 硬件连接与基础环境搭建 第一次接触基恩士DL-EP1和欧姆龙PLC通信时,我花了大半天时间才搞明白硬件连接的门道。DL-EP1这个传感器网关就像个翻译官,负责把基恩士传感器的"方言"转换成EtherNet/IP这种PLC能听懂的"普通话"。实际操作…...

重新掌控你的华硕笔记本:告别臃肿,迎接轻量高效的G-Helper时代

重新掌控你的华硕笔记本:告别臃肿,迎接轻量高效的G-Helper时代 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, F…...

Kazumi番剧采集应用完全指南:如何免费观看高清动漫与实时弹幕

Kazumi番剧采集应用完全指南:如何免费观看高清动漫与实时弹幕 【免费下载链接】Kazumi 基于自定义规则的番剧采集APP,支持流媒体在线观看,支持弹幕,支持实时超分辨率。 项目地址: https://gitcode.com/gh_mirrors/ka/Kazumi …...

从零实战:手把手教你编写USB键盘驱动

1. USB键盘驱动开发基础 要开发一个USB键盘驱动,首先需要理解USB HID(Human Interface Device)类设备的工作原理。USB键盘属于HID设备的一种,它通过中断传输方式与主机通信。当你在键盘上按下或释放按键时,键盘会通过U…...

从CloudCompare的ccViewer源码入手,拆解一个工业级Qt+OpenGL点云查看器的架构设计

从CloudCompare的ccViewer源码剖析工业级QtOpenGL点云查看器设计 在三维点云处理领域,一个高效、稳定的可视化工具往往能决定整个工作流程的顺畅程度。CloudCompare作为开源点云处理软件的标杆,其内置的ccViewer模块展现了工业级3D查看器应有的架构水准。…...

安全代码审查

安全代码审查:守护数字世界的基石 在数字化时代,软件已成为社会运转的核心载体,但随之而来的安全漏洞也带来了巨大风险。安全代码审查作为开发流程中的关键环节,能够从源头发现并修复潜在漏洞,避免数据泄露、系统瘫痪…...

Manjaro新手避坑指南:从依赖缺失到签名错误,一次搞定所有安装报错

Manjaro新手避坑指南:从依赖缺失到签名错误,一次搞定所有安装报错 第一次打开Manjaro的终端,输入sudo pacman -S命令时,那种期待和忐忑交织的感觉我还记得很清楚。作为一个刚从Ubuntu转投Arch系的新手,我完全没预料到接…...

从SPI引脚别名到实战选型:当芯片手册上的SDI/SDO把你搞晕时,这份避坑指南请收好

从SPI引脚别名到实战选型:当芯片手册上的SDI/SDO把你搞晕时,这份避坑指南请收好 刚拿到一款新传感器的评估板,准备用STM32的硬件SPI接口对接时,发现手册上标注的引脚名称竟然是SDI和SDO——这和教科书上常见的MOSI/MISO完全对不上…...

【AGI人类学第一课】:SITS2026圆桌首发“文明韧性评估量表”(含17维自测题),测出你在AGI浪潮中的真实坐标——前15%已启动神经接口预适应训练

第一章:SITS2026圆桌:AGI与人类未来 2026奇点智能技术大会(https://ml-summit.org) 圆桌共识:AGI不是工具,而是共演伙伴 在SITS2026主会场C厅的90分钟闭门圆桌中,来自DeepMind、OpenAI、中科院自动化所及联合国AI伦理…...

从缺页异常到内存陷阱:一个mincore函数如何帮你检测手游里的透视自瞄挂

从缺页异常到内存陷阱:mincore函数在手游反外挂中的实战解析 手游安全攻防战从未停歇,尤其是FPS和MOBA类游戏中透视与自瞄外挂的泛滥,让开发者们不断寻找更底层的检测方案。当传统的内存校验和API监控难以应对内核级外挂时,Linux内…...

eNSP实战:从零搭建企业级网络拓扑

1. 企业级网络拓扑设计基础 刚接触企业网络搭建的新手常会觉得无从下手,但其实只要掌握几个关键点就能快速入门。eNSP作为华为官方推出的网络仿真工具,完美复刻了真实设备的操作体验,特别适合用来练习企业网络部署。我经手过不少中小企业的网…...

如何用LizzieYzy围棋AI分析工具提升你的围棋水平:5个实战技巧

如何用LizzieYzy围棋AI分析工具提升你的围棋水平:5个实战技巧 【免费下载链接】lizzieyzy LizzieYzy - GUI for Game of Go 项目地址: https://gitcode.com/gh_mirrors/li/lizzieyzy LizzieYzy是一款功能强大的围棋AI分析工具,通过直观的图形界面…...

AGI如何重构人力资源管理闭环:从人才画像到组织健康度预测的7步落地方法论

第一章:AGI驱动的人力资源管理范式跃迁 2026奇点智能技术大会(https://ml-summit.org) 传统人力资源管理正经历由通用人工智能(AGI)引发的结构性重构——从流程自动化迈向认知协同、从经验决策转向因果推演、从岗位适配升维至潜能涌现。AGI不…...

什么是不会表达情绪?情绪管理困难与学习障碍的关系是什么?

情绪管理困难如何影响孩子的学习和行为表现 情绪管理困难能显著影响孩子的学习和行为表现。首先,情绪困扰可能导致家庭作业拖延,孩子在情绪低落时往往会拖延完成作业,从而影响学业成绩。其次,课堂上的行为问题也常与情绪管理有关。…...

拆开看个究竟:暴力拆解微波炉整流管CL01-12,揭秘13层硅片堆叠的耐压秘密

暴力拆解微波炉整流管CL01-12:13层硅片堆叠背后的高压奥秘 微波炉高压整流二极管CL01-12看似普通,却藏着令人惊叹的工程智慧。当第一次用万用表测量时,发现它需要9V以上电压才能导通,这与普通二极管的0.7V形成鲜明对比。这种异常现…...

Minitab局部宏进阶教程:打造动态统计计算工具(含ODBC连接技巧)

Minitab局部宏进阶教程:打造动态统计计算工具(含ODBC连接技巧) 在数据分析领域,Minitab作为一款专业的统计软件,其宏功能常常被低估。许多用户仅停留在基础操作层面,却不知局部宏能实现怎样的自动化魔法。本…...

别再只盯着5G了!车联网里那些不起眼但至关重要的通信技术:CAN总线、LoRa与RFID实战解析

车联网底层通信技术实战:CAN总线、LoRa与RFID的工程化落地指南 当行业热议5G车联网时,真正决定系统稳定性的往往是那些沉默的"基础设施级"通信协议。在重庆某智能网联汽车测试场,我们曾目睹一辆搭载最新5G模组的原型车因CAN总线仲裁…...

PUBG-Logitech压枪脚本高级配置与性能调优手册

PUBG-Logitech压枪脚本高级配置与性能调优手册 【免费下载链接】PUBG-Logitech PUBG罗技鼠标宏自动识别压枪 项目地址: https://gitcode.com/gh_mirrors/pu/PUBG-Logitech PUBG-Logitech是一款基于罗技鼠标宏与计算机视觉识别技术的绝地求生压枪辅助工具,通过…...

Chaplin:基于唇语识别的实时无声语音输入实战指南

Chaplin:基于唇语识别的实时无声语音输入实战指南 【免费下载链接】chaplin A real-time silent speech recognition tool. 项目地址: https://gitcode.com/gh_mirrors/chapl/chaplin 在嘈杂的会议室中无法进行语音输入?在图书馆需要安静地记录想…...

Zotero-SciHub插件实战:学术文献自动获取的技术原理与实现深度解析

Zotero-SciHub插件实战:学术文献自动获取的技术原理与实现深度解析 【免费下载链接】zotero-scihub A plugin that will automatically download PDFs of zotero items from sci-hub 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-scihub 学术研究者在…...