QTreeWidget перетаскивает только при нажатии клавиши

Итак, давайте рассмотрим этот небольшой фрагмент:

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). В противном случае я бы хотел, чтобы виджет вел себя нормально, а элементы оставались статичными, независимо от того, пытаетесь ли вы перетаскивать элементы или удерживать кнопку мыши при наведении курсора на элементы.

Как я могу реализовать это поведение?


person BPL    schedule 29.12.2016    source источник


Ответы (1)


Это довольно легко реализовать, переопределив startDrag:

class PageTree(QTreeWidget):
    ...

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

Обратите внимание, что здесь я использовал ключ Meta (Windows), потому что Модификаторы Ctrl и Shift влияют на различные аспекты выделения в сочетании с мышью. (Кроме того, в Linux комбинация Alt + перетаскивание обычно используется для перемещения окон, так что это тоже не лучший выбор). Однако эту проблему можно обойти, выбрав другой выбор. режим.

person ekhumoro    schedule 29.12.2016
comment
Вау, это было действительно легко :) . Тем не менее, я не понимаю, в чем проблема с использованием клавиши управления, я пробовал, и все работает нормально... я что-то упустил? - person BPL; 29.12.2016
comment
@БПЛ. Для меня использование клавиши управления может конфликтовать с выбором. Если элемент не выбран, Ctrl+перетаскивание работает нормально. Но если он выбран, первоначальный щелчок с нажатой клавишей Ctrl отменяет выбор элемента, и перетаскивание завершается ошибкой. Я полагаю, это должно быть специфично для платформы. - person ekhumoro; 29.12.2016
comment
Когда я задал этот вопрос давным-давно, я не знал, что вы имели в виду под конфликтным выбором клавиши управления, и не настаивал на этом (я думал, что это работает нормально), но сегодня я попытался использовать некоторые из моих старых виджеты, и я наконец-то понял. Я пытаюсь найти правильное решение для этого и все еще могу использовать модификатор управления (мета-ключ окна откроет меню запуска Windows), но пока ничего не нашел. Любое предложение до сих пор? - person BPL; 04.08.2018
comment
@БПЛ. У вас не может быть и того, и другого, поэтому вам придется либо отключить расширенный выбор, либо выбрать неконфликтующую комбинацию мышь+клавиша. - person ekhumoro; 04.08.2018