QTreeWidget 仅在按键时拖放

Posted

技术标签:

【中文标题】QTreeWidget 仅在按键时拖放【英文标题】:QTreeWidget drag and drop only when pressing key 【发布时间】:2017-05-13 09:09:10 【问题描述】:

那么,让我们考虑一下这个小sn-p:

import sys
import random
import string

from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMenu, QAction, \
    QTreeWidget, QTreeWidgetItem, QAbstractItemView
from PyQt5.QtGui import QCursor, QKeySequence


class PageTree(QTreeWidget):

    def __init__(self, parent=None):
        super().__init__(parent)

        self.alphabet = list(string.ascii_lowercase)
        self.index = 0
        self.header().hide()
        self.view_menu = QMenu(self)
        self.create_actions()
        self.setDragEnabled(True)
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)

    def create_actions(self):
        action = QtWidgets.QAction("Add new", self.view_menu)
        action.triggered.connect(self.on_add_page)
        action.setShortcuts(QKeySequence("a"))
        self.view_menu.addAction(action)
        self.addActions(self.view_menu.actions())

    def add_page(self, name, parent=None):
        if (parent is None and len(self.selectedItems()) == 1):
            parent = self.selectedItems()[0]

        item = QTreeWidgetItem(parent)
        item.setText(0, name)
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        self.addTopLevelItem(item)

        if (parent):
            parent.setExpanded(True)

        return item

    def on_add_page(self):
        self.add_page("test_page_0".format(self.alphabet[self.index]), None)
        self.index += 1
        self.index %= len(self.alphabet)

    def contextMenuEvent(self, ce):
        super().contextMenuEvent(ce)
        self.view_menu.exec(QCursor.pos())


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    tree_widget = PageTree()
    tree_widget.resize(400, 600)
    tree_widget.show()
    sys.exit(app.exec_())

如您所见,当前代码显示了一个简单的 QTreeWidget,借助 setDragEnabled, setDragDropMode, setSelectionBehavior 函数,您可以使用内置的拖放功能对项目重新排序。

事情就是这样,我想实现一种行为,即仅在按下键时才发生拖放(即:ctrl)。否则,无论您是尝试拖动项目还是在悬停项目时按住鼠标按钮,我都希望小部件能够正常运行并且项目保持静态。

我该如何实现这种行为?

【问题讨论】:

【参考方案1】:

这很容易通过覆盖startDrag来实现:

class PageTree(QTreeWidget):
    ...

    def startDrag(self, actions):
        if QtWidgets.qApp.keyboardModifiers() & Qt.MetaModifier:
            super().startDrag(actions)

请注意,我在这里使用了 Meta (Windows) 键,因为Ctrl and Shift modifiers 会影响与鼠标结合使用的各个方面。 (另外,在 Linux 上,Alt + 拖动组合通常用于移动窗口,因此它也可能不是一个好的选择)。不过,您可以通过选择不同的selection mode 来解决此问题。

【讨论】:

哇,这确实很容易:)。不过,我不明白使用控制键有什么问题,我试过了,它工作正常......我错过了什么吗? @BPL。对我来说,使用控制键可能会与选择冲突。如果一个项目没有被选中,ctrl+drag 可以正常工作。但如果它选中,最初的 ctrl+click 会取消选择该项目,并且拖动失败。我想它一定是特定于平台的东西。 很久以前当我问这个问题时,我不知道你所说的控制键冲突选择是什么意思,也没有坚持(我认为它工作正常)但今天我'已经尝试使用我的一些旧小部件,我终于understood。我正在尝试找到一个合适的解决方案并且仍然能够使用控制修饰符(窗口元键将弹出窗口开始菜单)但还没有找到任何东西。到目前为止有什么建议吗? @BPL。您不能同时拥有这两种方式,因此您必须关闭扩展选择或选择不冲突的鼠标+键组合。

以上是关于QTreeWidget 仅在按键时拖放的主要内容,如果未能解决你的问题,请参考以下文章

关于qt中的QTreeWidget的拖放问题

如何阻止 QTreeWidget 在拖放时创建重复项

在 PyQt 中使用拖放重新排序 QTreeWidget 中的项目

QTreeWidgetItem 的拖放不能正常工作

在PyQt5中的QTreeWidget和QListWidget之间拖动项目?

HTML5 拖放 - 仅在每个拖放区的项目上