質問

私のQt4用のPyQtのバインディング)が含まれて QListWidget, 初期化され、このように:

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

て追加する事ができますので、またドラッグ&ドロップ並べ替えます。がどのように通知リストを返し注文により、ユーザーまたの追加 dropMimeData(self, index, data, action) 法のクラスがることはありませんが呼び出されます。

役に立ちましたか?

解決

これに対処しなければならなかったので、それはお尻の痛みですが、ここで何をすべきかです:

ListWidget サブクラスに eventFilter をインストールしてから、 ChildRemoved イベントを監視する必要があります。このイベントは移動だけでなく削除もカバーするため、リスト内でドラッグアンドドロップを使用してアイテムを再配置する場合に機能するはずです。

QtをC ++で記述していますが、ここにPython化バージョンがあります:

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

このリストを含む他のクラスがある場合、イベントフィルターメソッドをそこに移動することができます。これがお役に立てば幸いです、これを理解する前にこれと1日戦わなければならなかったことを知っています。

他のヒント

しています。:)

で実際にアクセスのlistwidgetの内部モデル myList->model() -から多くの信号が可能です。

場合だけドラッグ&ドロップ接続し、 layoutChanged.だって移動ボタンが実装されて除去+追加)に接続 rowsInserted ます。

したい場合はどの移動 rowsMoved の方が良いかもしれないよ layoutChanged.

Trey Stoutの回答は機能しましたが、リストの順序が実際に変更されていないときに明らかにイベントを取得していました。 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ソリューションを共有したいと考えました。これは、サブクラス化されたものではなく、 QDialog 内の QListWidget 用です。

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がselfであるかどうかを確認することです。 PyQt5でチェックインするために提案されたすべてのソリューションがコーディングされたMVCEである以下のコードを参照してください。

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