我有含有QListWidget一个的Qt4应用(使用PyQt的绑定),像这样初始化:

class MyList(QtGui.QListWidget):
    def __init__(self):
        QtGui.QListWidget.__init__(self)
        self.setDragDropMode(self.InternalMove)

我可以添加项目,这让我可以拖放重新排序列表。但是,我怎么通知时,列表获取用户重新排序?我尝试添加一个dropMimeData(self, index, data, action)方法的类,但它从未被调用。

有帮助吗?

解决方案

我不得不处理这和它在一个痛苦的屁股,但这里是做什么:

您必须对您的eventFilter子安装ListWidget,然后查看该ChildRemoved事件。本次活动涵盖了移动和拆卸,所以应该重新安排项目工作,拖放名单内下降。

我写我的Qt在C ++,但这里有一个pythonification版本:

class MyList(QtGui.QListWidget):
    def __init__(self):
        QtGui.QListWidget.__init__(self)
        self.setDragDropMode(self.InternalMove)
        self.installEventFilter(self)

    def eventFilter(self, sender, event):
        if (event.type() == QEvent.ChildRemoved):
            self.on_order_changed()
        return False # don't actually interrupt anything

    def on_order_changed(self):
        # do magic things with our new-found knowledge

如果您有一个包含此列表中的一些其他类,你可能希望有移动的事件过滤器的方法。希望这可以帮助,我知道我已经搞清楚了这一点之前,这个打了一天。

其他提示

我有一个更简单的方法。 :)

您可以实际上myList->model()访问listwidget的内部模型 - 并从那里有很多的信号,可用

如果你只关心拖放,连接到layoutChanged。 如果有移动按钮(其通常与移除实现+添加)连接到rowsInserted

如果你想知道什么是感动,rowsMoved可能比layoutChanged更好。

我发现三分球粗壮的回答没有工作,但是我明显越来越事件当列表顺序实际上并没有改变。我转身 Chani的答案它不工作的要求,但没有代码,我花了一点工作在Python实现。

我想我会分享代码片段,以帮助未来的用户:

class MyList(QListWidget):
    def __init__(self):
        QListWidget.__init__(self)
        self.setDragDropMode(self.InternalMove)
        list_model = self.model()
        list_model.layoutChanged.connect(self.on_layout_changed)

    def on_layout_changed(self):
        print "Layout Changed"

此在PySide测试,但没有理由它不会在PyQt的工作。

不是一个解决方案,但一些想法:

您也许应该检查什么是supportedDropActions方法返回。这可能是你需要覆盖该方法,包括Qt的:: MoveAction或Qt的:: CopyAction。

您有而QListView :: indexesMoved信号,但我不知道它是否会如果你使用QListWidget发出。它实在值得校验。

我知道这是旧的,但我可以把我的代码使用Trey的答复工作,想分享我的Python的解决方案。这是一个QListWidget内的QDialog,不是一个是子类。

class NotesDialog(QtGui.QDialog):
    def __init__(self, notes_list, notes_dir):
        QtGui.QDialog.__init__(self)
        self.ui=Ui_NotesDialog()
        # the notesList QListWidget is created here (from Qt Designer)
        self.ui.setupUi(self) 

        # install an event filter to catch internal QListWidget drop events
        self.ui.notesList.installEventFilter(self)

    def eventFilter(self, sender, event):
        # this is the function that processes internal drop in notesList
        if event.type() == QtCore.QEvent.ChildRemoved:
            self.update_views() # do something
        return False # don't actually interrupt anything

QListWidget.model()方法似乎是最优雅的提出的解决方案,但对我来说在PyQt5没有工作。我不知道为什么,但也许东西搬到QT5改变。该eventFilter方法没有工作,但还有另一种替代方案,是值得考虑的:压倒一切的QDropEvent和检查,如果event.source是自我。见下面的代码这是一个MVCE与所有用于PyQt5检查编码在所提出的解决方案:

import sys
from PyQt5 import QtGui, QtWidgets, QtCore


class MyList(QtWidgets.QListWidget):
    itemMoved = QtCore.pyqtSignal()

    def __init__(self):
        super(MyList, self).__init__()
        self.setDragDropMode(self.InternalMove)
        list_model = self.model()
        # list_model.layoutChanged.connect(self.onLayoutChanged)  # doesn't work
        # self.installEventFilter(self)  # works
        self.itemMoved.connect(self.onLayoutChanged)  # works

    def onLayoutChanged(self):
        print("Layout Changed")

    def eventFilter(self, sender, event):
        """
        Parameters
        ----------
        sender : object
        event : QtCore.QEvent
        """
        if event.type() == QtCore.QEvent.ChildRemoved:
            self.onLayoutChanged()
        return False

    def dropEvent(self, QDropEvent):
        """
        Parameters
        ----------
        QDropEvent : QtGui.QDropEvent
        """

        mime = QDropEvent.mimeData()  # type: QtCore.QMimeData
        source = QDropEvent.source()

        if source is self:
            super(MyList, self).dropEvent(QDropEvent)
            self.itemMoved.emit()


app = QtWidgets.QApplication([])
form = MyList()
for text in ("one", "two", "three"):
    item = QtWidgets.QListWidgetItem(text)
    item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
    item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
    item.setCheckState(QtCore.Qt.Checked)
    form.addItem(item)

form.show()
sys.exit(app.exec_())
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top