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

PySide2:QListWidget等控件用ExtendedSelection时禁用拖拽多选

彻底禁用PySide2 QListWidget/QTreeWidget/QTableWidget的拖拽多选(保留Ctrl/Shift多选)

要实现保留ExtendedSelection模式下的Ctrl/Shift键多选,同时完全禁用鼠标拖拽多选,重写mouseMoveEvent的方式存在边界漏洞(比如快速拖拽时仍会触发多选),更可靠的方案是直接重写selectionCommand方法——这个方法负责决定用户操作对应的选择行为,从根源上拦截拖拽多选的命令。

核心思路

QAbstractItemView.selectionCommand()会在每次选择操作前被调用,返回对应的选择命令类型。我们可以在此处判断:如果是鼠标拖拽操作且未按住Ctrl/Shift键,就返回QAbstractItemView.NoSelection(不执行任何选择),其他情况保留原有逻辑,这样既能保留标准的多选快捷键,又彻底阻止拖拽多选。

示例代码(以QListWidget为例)

import sys
from PySide2.QtWidgets import QListWidget, QApplication, QAbstractItemView
from PySide2.QtCore import Qt, QEvent

NAMES = ["sparrow", "robin", "crow", "raven", "woodpecker", "hummingbird"]


class CustomListWidget(QListWidget):
    def __init__(self):
        super().__init__()
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        for name in NAMES:
            self.addItem(name)

    def selectionCommand(self, index, event=None):
        # 判断是否是鼠标拖拽且未按住Ctrl/Shift键
        if event and event.type() == QEvent.MouseMove:
            modifiers = QApplication.keyboardModifiers()
            if modifiers not in (Qt.ControlModifier, Qt.ShiftModifier, 
                                Qt.ControlModifier | Qt.ShiftModifier):
                return QAbstractItemView.NoSelection
        # 其他情况保留原有选择逻辑
        return super().selectionCommand(index, event)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    custom_list = CustomListWidget()
    custom_list.show()
    sys.exit(app.exec_())

适配QTreeWidget/QTableWidget

只需把上述代码中的CustomListWidget继承类改成QTreeWidget或QTableWidget即可,逻辑完全通用——因为这三个控件都继承自QAbstractItemView,selectionCommand是它们的共同方法。

效果验证

  • 单选:点击任意条目,仅选中该条目
  • Ctrl键多选:按住Ctrl点击条目,可加选/取消选中
  • Shift键连续选:选中一个条目后,按住Shift点击另一个条目,选中两者之间的所有条目
  • 鼠标拖拽:按住鼠标左键拖拽,不会选中任何额外条目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:37:20