You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide:如何将QTreeView(QStandardItemModel)项拖拽至QLineEdit并获取数据

将QTreeView项拖拽到QLineEdit的实现方案

我来帮你搞定这个拖拽问题!其实核心就是处理好拖拽时的MIME数据传递,下面给你一个完整的可运行示例,每一步都讲清楚:

关键思路

  1. 让QTreeView允许向外拖拽项
  2. 让QLineEdit接受拖拽事件
  3. 正确解析拖拽过来的MIME数据,提取项的文本内容

完整代码示例

from PySide6.QtWidgets import (QApplication, QTreeView, QLineEdit, QWidget, QVBoxLayout, QStandardItem, QStandardItemModel)
from PySide6.QtCore import (Qt, QMimeData, QModelIndex, QDataStream, QIODevice)

# 自定义模型,添加纯文本格式的MIME数据(可选但更简单)
class CustomStandardItemModel(QStandardItemModel):
    def mimeData(self, indexes):
        # 先获取父类默认的MIME数据
        mime_data = super().mimeData(indexes)
        # 如果有选中的项,添加纯文本格式的数据
        if indexes:
            first_item_text = self.data(indexes[0], Qt.DisplayRole)
            mime_data.setText(first_item_text)
        return mime_data

# 自定义TreeView,开启拖拽功能
class MyTreeView(QTreeView):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 设置为仅允许向外拖拽
        self.setDragMode(QTreeView.DragOnly)
        # 初始化示例数据
        model = CustomStandardItemModel()
        root = model.invisibleRootItem()
        
        # 添加一些测试项
        item1 = QStandardItem("项目A")
        subitem1 = QStandardItem("子项目A1")
        item1.appendRow(subitem1)
        item2 = QStandardItem("项目B")
        root.appendRows([item1, item2])
        
        self.setModel(model)
        self.expandAll()  # 展开所有节点方便拖拽

# 自定义LineEdit,处理拖拽接收
class MyLineEdit(QLineEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 开启接受拖拽的功能
        self.setAcceptDrops(True)
        self.setPlaceholderText("拖拽树中的项到这里...")
    
    def dragEnterEvent(self, event):
        # 检查MIME数据是否符合要求(纯文本或模型数据格式)
        if event.mimeData().hasText() or event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            event.acceptProposedAction()
        else:
            super().dragEnterEvent(event)
    
    def dragMoveEvent(self, event):
        # 同dragEnterEvent的检查逻辑
        if event.mimeData().hasText() or event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            event.acceptProposedAction()
        else:
            super().dragMoveEvent(event)
    
    def dropEvent(self, event):
        # 优先使用纯文本格式(如果有的话)
        if event.mimeData().hasText():
            self.setText(event.mimeData().text())
            event.acceptProposedAction()
        # 如果只有模型默认的MIME格式,就解析它
        elif event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            data_stream = QDataStream(event.mimeData().data("application/x-qabstractitemmodeldatalist"), QIODevice.ReadOnly)
            # 模型MIME数据的格式是:每行/列对应一个QMap<角色, 值>
            while not data_stream.atEnd():
                # 读取无关的行列信息,重点是后面的角色数据
                data_stream.readInt32()  # row
                data_stream.readInt32()  # column
                map_size = data_stream.readInt32()
                item_data = {}
                for _ in range(map_size):
                    role = data_stream.readInt32()
                    value = data_stream.readQVariant()
                    item_data[role] = value
                # 提取显示文本
                if Qt.DisplayRole in item_data:
                    self.setText(item_data[Qt.DisplayRole])
                    break
            event.acceptProposedAction()
        else:
            super().dropEvent(event)

# 主窗口测试
class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        layout = QVBoxLayout()
        layout.addWidget(MyTreeView())
        layout.addWidget(MyLineEdit())
        self.setLayout(layout)
        self.setWindowTitle("TreeView拖拽到LineEdit演示")
        self.resize(400, 350)

if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

代码说明

  1. CustomStandardItemModel:我重写了mimeData方法,在默认的模型MIME数据基础上添加了纯文本格式,这样LineEdit可以直接读取文本,不用复杂解析。如果不想自定义模型,也可以直接用默认的QStandardItemModel,此时LineEdit会走解析模型MIME数据的分支。
  2. MyTreeView:通过setDragMode(QTreeView.DragOnly)开启向外拖拽功能,并初始化了一些测试数据方便你验证。
  3. MyLineEdit:
    • 开启setAcceptDrops(True)允许接收拖拽
    • dragEnterEvent和dragMoveEvent用来筛选可接受的拖拽类型
    • dropEvent是核心:先尝试读取纯文本,不行就解析模型的MIME数据,提取出项的显示文本并设置到LineEdit中

这样你就能轻松实现从TreeView拖拽项到LineEdit的功能啦!

内容的提问来源于stack exchange,提问作者stowaway

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:40:38