首页 > 解决方案 > 使 QTableView 中的项目可拖动但不可选择

问题描述

一些背景知识(理解问题不是完全必要的):

在我今年早些时候开发的 PySide2 应用程序中,我有一个与自定义模型一起使用的 QTableView。可以选择其中的一些项目,然后单击按钮对所选项目执行批量操作。其他一些项目作为数据存在的视觉指示,但执行批量操作的函数不知道如何处理它们,所以我将它们设为不可选择。我的程序中有另一个区域可以接受来自外部文件或来自我的 TableView 中的项目的丢弃。在这种情况下,表中的每一个项目都应该能够被拖放到另一个区域。

问题:

当一个项目不可选择时,它似乎也不可拖动。

我试过的:

在代码方面不多,因为我真的不知道如何处理那个。我尝试了很多标志组合但没有成功。

我已经用谷歌搜索和浏览 StackOverflow 几个小时了,但找不到任何相关的东西,我只是被人们询问如何通过拖放重新排序表格的帖子所淹没。

最小复制代码:

from PySide2 import QtCore, QtWidgets, QtGui


class MyWindow(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.setGeometry(300, 200, 570, 450)
        self.setWindowTitle("Drag Example")
        model = QtGui.QStandardItemModel(2, 1)
        table_view = QtWidgets.QTableView()

        selectable = QtGui.QStandardItem("I'm selectable and draggable")
        selectable.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDragEnabled)
        model.setItem(0, 0, selectable)

        non_selectable = QtGui.QStandardItem("I'm supposed to be draggable, but I'm not")
        non_selectable.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDragEnabled)
        model.setItem(1, 0, non_selectable)

        table_view.setModel(model)
        table_view.setDragDropMode(table_view.DragOnly)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(table_view)
        self.setLayout(layout)


app = QtWidgets.QApplication([])
win = MyWindow()
win.show()
app.exec_()

有没有人有关于如何使项目启用拖动但禁用选择的建议?

谢谢

标签: pythonpython-2.7pyside2

解决方案


我找到了一种解决方法,虽然不一定是完美的答案,但它对我有用。

我没有使项目不可选择,而是使用自定义数据角色使其在视觉上看起来像是在选择它时没有选择。

我在批量函数中使用相同的数据标志来过滤选择。

为了使它看起来即使项目没有被选中,我使用了自定义样式的项目委托:

class MyDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None):
        super(MyDelegate, self).__init__(parent)

    def paint(self, painter, option, index):

        if option.state & QtWidgets.QStyle.State_Selected:
            if index.data(Qt.UserRole) == 2:  # Some random flag i'm using
                text_brush = option.palette.brush(QtGui.QPalette.Text)
                if index.row() % 2 == 0:
                    bg_brush = option.palette.brush(QtGui.QPalette.Base)
                else:
                    bg_brush = option.palette.brush(QtGui.QPalette.AlternateBase)
                # print brush
                option.palette.setBrush(QtGui.QPalette.Highlight, bg_brush)
                option.palette.setBrush(QtGui.QPalette.HighlightedText, text_brush)

        super(MyDelegate, self).paint(painter, option, index)

在我设置的表格中:

delegate = MyDelegate()
table_view.setItemDelegate(delegate)

我从这篇文章中改编了这个解决方案:QTreeView Item Hover/Selected background color based on current color


推荐阅读