ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

PyQt6 中文教程:拖放(Drag Drop)操作实战指南

2026/10/4 15:12:14 拓冰建站 浏览量
PyQt6 中文教程:拖放(Drag  Drop)操作实战指南 文档教程【免费下载链接】PyQt-Chinese-tutorialPyQt6中文教程项目地址https://gitcode.com/gh_mirrors/py/PyQt-Chinese-tutorial点击查看免费下载拖放Drag Drop是图形界面中最直观的交互方式之一本教程来自 PyQt6 中文教程PyQt-Chinese-tutorial中的 拖拽操作章节围绕QDrag、QMimeData以及一组可重写的事件处理器展开。读完本文你将掌握两种典型的 PyQt6 拖放实现一是从QLineEdit拖拽纯文本到QPushButton并更新按钮标签二是用鼠标右键拖拽按钮组件本身、在窗口内任意移动它同时还能了解 PyQt6 相对 PyQt5 在拖放 API 上的关键差异。拖放操作的基本概念在计算机图形用户界面中拖放是点击一个虚拟对象、按住不放并将其拖到另一个位置或另一个虚拟对象之上的动作。一般来说它可以触发多种类型的动作或者在两个抽象对象之间建立各种类型的关联。拖放是 GUI 的一部分它让用户能够以非常直观的方式完成复杂的事情。通常我们可以拖放两种东西数据或图形对象。如果把一张图片从一个应用程序拖到另一个应用程序拖放的是二进制数据如果在 Firefox 中把一个选项卡拖到另一个位置拖放的是一个图形组件。这两类场景在 PyQt6 中对应两条不同的实现路径数据传输型拖放依赖 MIME 数据封装而组件拖放则直接操作控件本身的坐标与位置。本文的两个示例恰好分别覆盖了这两种情况。从 PyQt6 的事件和信号教程可知PyQt6 程序是事件驱动的应用进入主循环后由事件源产生事件再交由对应的事件处理器处理。拖放相关的dragEnterEvent、dropEvent、mouseMoveEvent等都属此类事件处理器它们都有默认实现当我们想自定义拖放行为时就需要重写这些方法。QDrag 与基于 MIME 的数据传输拖放的核心类是QDrag它提供对基于 MIME 的拖放数据传输的支持处理拖放操作中的大部分细节。传输的数据包含在QMimeData对象中。在 PyQt6 中相关的类分布在三个模块里从示例代码的导入语句可以清晰看到分工from PyQt6.QtCore import Qt, QMimeData # 枚举、MIME 数据容器 from PyQt6.QtGui import QDrag # 拖放传输载体 from PyQt6.QtWidgets import QPushButton, QWidget, QApplication一个典型的拖放流程是拖动源如启用了拖拽的QLineEdit把数据封装进QMimeData通过QDrag启动拖放QDrag负责在拖动期间展示拖拽对象、与目标部件协商目标部件通过重写dragEnterEvent判断是否接受传入的数据按 MIME 类型过滤若接受dropEvent在释放鼠标时被触发目标部件从QMimeData中取出数据完成最终处理。示例一把纯文本拖放到按钮上simple.py第一个示例中有一个QLineEdit和一个QPushButton。我们把纯文本从行编辑部件拖到按钮部件上按钮的标签会随之改变。完整代码如下# file: simple.py #!/usr/bin/python ZetCode PyQt6 tutorial This is a simple drag and drop example. import sys from PyQt6.QtWidgets import (QPushButton, QWidget, QLineEdit, QApplication) class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent) self.setAcceptDrops(True) def dragEnterEvent(self, e): if e.mimeData().hasFormat(text/plain): e.accept() else: e.ignore() def dropEvent(self, e): self.setText(e.mimeData().text()) class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): edit QLineEdit(, self) edit.setDragEnabled(True) edit.move(30, 65) button Button(Button, self) button.move(190, 65) self.setWindowTitle(Simple drag and drop) self.setGeometry(300, 300, 300, 150) def main(): app QApplication(sys.argv) ex Example() ex.show() app.exec() if __name__ __main__: main()下面逐步拆解这个示例的关键实现。自定义 Button 类成为拖放目标为了把文本拖到QPushButton上我们必须重写reimplement一些方法因此创建了一个继承自QPushButton的Button类class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent) self.setAcceptDrops(True)setAcceptDrops(True)用于开启部件的释放事件drop events。只有调用了该方法部件才会响应后续的拖放事件。dragEnterEvent声明接受的数据类型def dragEnterEvent(self, e): if e.mimeData().hasFormat(text/plain): e.accept() else: e.ignore()dragEnterEvent方法定义了部件接受的数据类型——本例中只接受纯文本text/plain。当拖拽对象进入部件区域时事件对象e携带mimeData我们通过hasFormat(text/plain)判断其 MIME 格式匹配则调用e.accept()放行否则调用e.ignore()拒绝。这一步是拖放能否落地的“准入检查”。dropEvent处理释放动作def dropEvent(self, e): self.setText(e.mimeData().text())dropEvent方法处理释放事件。当用户在按钮上松开鼠标完成放置时这里从mimeData中取出文本text()即text/plain内容的取值方法并作为按钮的新标签显示出来。启用 QLineEdit 的拖拽edit QLineEdit(, self) edit.setDragEnabled(True)QLineEdit部件内置支持拖放操作我们只需要调用setDragEnabled(True)激活它就能从输入框中拖出选中的文本无需任何额外代码。运行该程序的效果如下图所示输入框中输入ZetCode后将其拖到右侧按钮上按钮标签即被替换示例二拖放按钮组件drag_button.py第二个示例演示如何拖放按钮组件本身。窗口上有一个QPushButton鼠标左键点击它时控制台打印press消息鼠标右键按住拖动时则对按钮执行拖放操作把它移动到鼠标释放的位置。完整代码如下# file: drag_button.py #!/usr/bin/python ZetCode PyQt6 tutorial 在这个程序里有一个按钮可以用鼠标左键点击也可以鼠标右键拖拽 import sys from PyQt6.QtCore import Qt, QMimeData from PyQt6.QtGui import QDrag from PyQt6.QtWidgets import QPushButton, QWidget, QApplication class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent) def mouseMoveEvent(self, e): if e.buttons() ! Qt.MouseButton.RightButton: return mimeData QMimeData() drag QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(e.position().toPoint() - self.rect().topLeft()) dropAction drag.exec(Qt.DropAction.MoveAction) def mousePressEvent(self, e): super().mousePressEvent(e) if e.button() Qt.MouseButton.LeftButton: print(press) class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setAcceptDrops(True) self.button Button(Button, self) self.button.move(100, 65) self.setWindowTitle(Click or Move) self.setGeometry(300, 300, 550, 450) def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): position e.position() self.button.move(position.toPoint()) e.setDropAction(Qt.DropAction.MoveAction) e.accept() def main(): app QApplication(sys.argv) ex Example() ex.show() app.exec() if __name__ __main__: main()同样逐步拆解。Button 类重写鼠标事件基于QPushButton创建Button类并重写QPushButton的两个方法mouseMoveEvent和mousePressEvent。其中mouseMoveEvent是拖放操作开始的地方class Button(QPushButton): def __init__(self, title, parent): super().__init__(title, parent)注意本例中按钮自身并没有调用setAcceptDrops因为拖放目标接受方是外层窗口Example而不是按钮本身。限定右键触发拖拽if e.buttons() ! Qt.MouseButton.RightButton: return这里规定只有鼠标右键可以触发拖放操作左键保留给“点击”使用。注意 PyQt6 中枚举写法为Qt.MouseButton.RightButton详见下文的 PyQt5 对比e.buttons()返回当前按下的鼠标按键状态。创建 QDrag 并启动拖放mimeData QMimeData() drag QDrag(self) drag.setMimeData(mimeData) drag.setHotSpot(e.position().toPoint() - self.rect().topLeft()) dropAction drag.exec(Qt.DropAction.MoveAction)创建QDrag对象它提供基于 MIME 的拖放数据传输支持把QMimeData对象设置给drag此处没有填充具体内容仅作为携带者setHotSpot设置拖拽光标的热点位置用当前鼠标位置e.position()注意返回的是QPointF需经toPoint()转为整数坐标减去按钮矩形左上角self.rect().topLeft()这样拖拽时按钮不会“跳帧”drag.exec(Qt.DropAction.MoveAction)启动并进入拖放操作的阻塞循环返回实际执行的放置动作这里将返回值赋给dropAction便于后续判断示例中未进一步使用可以推断在实际应用中可据此检查拖放是否被接受。左键点击打印 pressdef mousePressEvent(self, e): super().mousePressEvent(e) if e.button() Qt.MouseButton.LeftButton: print(press)鼠标左键点击按钮时控制台打印press消息。注意这里先调用了父级的mousePressEvent否则按钮被按下的视觉反馈不会呈现——这一点与事件和信号教程中“重写事件处理器需保留默认逻辑”的思路一致。窗口作为放置目标移动按钮Example窗口调用了self.setAcceptDrops(True)成为拖放目标def dragEnterEvent(self, e): e.accept()dragEnterEvent无条件接受拖入示例中没有做 MIME 过滤接受所有拖放。def dropEvent(self, e): position e.position() self.button.move(position.toPoint()) e.setDropAction(Qt.DropAction.MoveAction) e.accept()dropEvent定义鼠标释放并完成放置后的行为取出当前鼠标指针位置e.position()QPointF同样需toPoint()转换把按钮move到该坐标e.setDropAction(Qt.DropAction.MoveAction)指定本次放置动作的类型——这里是一个移动Move动作最后e.accept()接受该放置事件。从 PyQt5 到 PyQt6 的拖放 API 差异本仓库同时收录了 PyQt5 版拖拽教程对应translated/pyqt5/tuo-zhuai.md与 PyQt6 版本即本文依据的 translated/pyqt6/dragdrop.md英文原文见 original/pyqt6/dragdrop.md。对照两版源码可以归纳出 PyQt6 中拖放编程的关键差异关注点PyQt5 写法PyQt6 写法鼠标按键枚举Qt.RightButton、Qt.LeftButtonQt.MouseButton.RightButton、Qt.MouseButton.LeftButton放置动作枚举Qt.MoveActionQt.DropAction.MoveAction鼠标位置取值e.pos()QPointe.position()QPointF需toPoint()转换启动拖放drag.exec_(Qt.MoveAction)drag.exec(Qt.DropAction.MoveAction)应用主循环app.exec_()app.exec()其中两点对移植代码影响最大枚举彻底命名空间化PyQt6 把所有枚举收纳进对应的作用域类Qt.MouseButton、Qt.DropAction旧的裸枚举写法Qt.RightButton、Qt.MoveAction在 PyQt6 中不再可用坐标返回类型变化e.position()返回浮点坐标的QPointF拖放相关代码里要记得用toPoint()转换否则move()等接收整数QPoint的方法会类型不匹配。拖放操作要点小结回顾本章PyQt6 实现拖放的核心套路可以概括为拖动源内置支持拖拽的控件如QLineEdit只需setDragEnabled(True)自定义拖动源则在mouseMoveEvent中创建QDrag、设置QMimeData与热点再调用exec启动放置目标先setAcceptDrops(True)开启释放事件再重写dragEnterEvent按mimeData().hasFormat(...)过滤可接受的数据类型与dropEvent取数据、改状态、必要时setDropAction声明动作类型两种对象拖放“数据”时通过QMimeData传递拖放“图形组件”时直接操作控件坐标两者共用同一套事件模型事件处理器dragEnterEvent、dropEvent、mouseMoveEvent、mousePressEvent均有默认实现重写时注意保留必要的父级调用如示例二中的super().mousePressEvent(e)。掌握这套机制后你可以进一步扩展出列表重排序、跨窗口拖放、文件拖入处理text/uri-listMIME 格式等更丰富的交互它们都建立在本文所述的QDragQMimeData 事件重写的基础框架之上。赞分享文档教程【免费下载链接】PyQt-Chinese-tutorialPyQt6中文教程项目地址https://gitcode.com/gh_mirrors/py/PyQt-Chinese-tutorial点击查看免费下载相关推荐抖音下载工具怎么用从 Cookie 到批量采集的 4 个实操场景抖音下载工具怎么用从 Cookie 到批量采集的 4 个实操场景 DouK Downloader工程名 TikTokDownloader是一款免费的抖音下文档教程如何永久保存微信聊天记录3步实现完整数据备份与智能分析如何永久保存微信聊天记录3步实现完整数据备份与智能分析 你是否曾担心手机丢失或更换设备时那些珍贵的微信聊天记录会永远消失那些与家人的温馨对话、朋友间的快乐Wails v3 文件拖放File Drag Drop实战从操作系统文件拖入到应用内 HTML5 拖拽Wails v3 文件拖放File Drag Drop实战从操作系统文件拖入到应用内 HTML5 拖拽 本文以 Wails v3 官方示例 drag桌面应用跨平台CLI前端上一篇WeMod-Patcher 解锁 Pro两种补丁方案怎么选附 3 个坑的绕法下一篇FinalBurn Neo 使用指南3 步让旧电脑变成街机模拟器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考