简体   繁体   English

PyQt:QListView拖放重新排序信号问题

[英]PyQt: QListView drag and drop reordering signal issue

I'm having a bit of trouble implementing drag and drop reordering using a QListView and QStandardItemModel. 我在使用QListView和QStandardItemModel实现拖放重新排序时遇到了一些麻烦。 Using the itemChanged signal for processing checked items is fine however when the items are reordered using drag and drop there seems to be a temporary item created when the signal is triggered. 使用itemChanged信号来处理选中的项目很好,但是当使用拖放对项目进行重新排序时,似乎会在触发信号时创建一个临时项目。 There are 5 items in the list however every time upon reordering an item the model row count becomes 6 even though there are only 5 visible in the end. 列表中有5个项目,但是每次重新排序项目时,即使最后只有5个可见,模型行计数也变为6。 Why does it become temporarily 6 when I specifically set the action to move? 当我专门设置动作要移动时,为什么会暂时变为6? I would like to deal with just the 5 items in the new order since the list is directly used to update another widget. 我只想处理新订单中的5个项目,因为该列表直接用于更新另一个小部件。 I tried the dataChange signal but there's no difference. 我尝试了dataChange信号,但没有区别。

My setup is PyQt 4.11.4 with Python 2.7.10 on Win 7. 我的设置是在Win 7上使用Python 2.7.10的PyQt 4.11.4。

import sys

from PyQt4.QtGui import *
from PyQt4.QtCore import *

if __name__ == '__main__':
    app = QApplication(sys.argv)

    # Our main window will be a QListView
    list = QListView()
    list.setDragDropMode(QAbstractItemView.InternalMove)
    list.setDefaultDropAction(Qt.MoveAction)
    list.setDragDropOverwriteMode(False)
    list.setAcceptDrops(True)
    list.setDropIndicatorShown(True)
    list.setDragEnabled(True)
    list.setWindowTitle('Example List')
    list.setMinimumSize(600, 400)

    # Create an empty model for the list's data
    model = QStandardItemModel(list)

    # Add some textual items
    foods = [
        'pizza',
        'burger',
        'steak',
        'chips',
        'soda'
    ]

    for food in foods:
        # create an item with a caption
        item = QStandardItem(food)

        # add a checkbox to it
        item.setCheckable(True)
        item.setData({'one': 1, 'two': 2, 'three': 3})
        item.setDragEnabled(True)
        item.setDropEnabled(False)

        # Add the item to the model
        model.appendRow(item)

    def on_item_changed(item):
        # If the changed item is not checked, don't bother checking others
        print 'DEBUG model rowcount'
        print model.rowCount()
        print 'itemChanged'
        if not item.checkState():
            return

        # Loop through the items until you get None, which
        # means you've passed the end of the list
        i = 0
        while model.item(i):
            if not model.item(i).checkState():
                return
            i += 1

        app.quit()

    model.itemChanged.connect(on_item_changed)

    # Apply the model to the list view
    list.setModel(model)

    w = QMainWindow()
    w.setCentralWidget(list)
    w.show()

    sys.exit(app.exec_())

Update, I found a workaround on this and it involves using a singleshot timer. 更新,我发现了一个解决方法,它涉及使用单发计时器。 After dropping an item in the list, the timer fires the slot and it finds 5 items in the new order instead of 6. 将项目放到列表中后,计时器会触发该广告位,并以新的顺序找到5个项目,而不是6个项目。

import sys

from PyQt4.QtGui import *
from PyQt4.QtCore import *

if __name__ == '__main__':
    app = QApplication(sys.argv)

    # Our main window will be a QListView
    list = QListView()
    list.setDragDropMode(QAbstractItemView.InternalMove)
    list.setDefaultDropAction(Qt.MoveAction)
    list.setDragDropOverwriteMode(False)
    list.setAcceptDrops(True)
    list.setDropIndicatorShown(True)
    list.setDragEnabled(True)
    list.setWindowTitle('Example List')
    list.setMinimumSize(600, 400)

    # Create an empty model for the list's data
    model = QStandardItemModel(list)

    # Add some textual items
    foods = [
        'pizza',
        'burger',
        'steak',
        'chips',
        'soda'
    ]

    for food in foods:
        # create an item with a caption
        item = QStandardItem(food)

        # add a checkbox to it
        item.setCheckable(True)
        item.setData({'one': 1, 'two': 2, 'three': 3})
        item.setDragEnabled(True)
        item.setDropEnabled(False)

        # Add the item to the model
        model.appendRow(item)

    def showModelCount():
        print 'DEBUG rowcount after singleshot'
        print model.rowCount()

    def on_item_changed(item):
        # If the changed item is not checked, don't bother checking others
        print 'DEBUG model rowcount'
        print model.rowCount()

        QTimer.singleShot(1, showModelCount)

        print 'itemChanged'
        if not item.checkState():
            return

        # Loop through the items until you get None, which
        # means you've passed the end of the list
        i = 0
        while model.item(i):
            if not model.item(i).checkState():
                return
            i += 1

        app.quit()

    model.itemChanged.connect(on_item_changed)

    # Apply the model to the list view
    list.setModel(model)

    w = QMainWindow()
    w.setCentralWidget(list)
    w.show()

    sys.exit(app.exec_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM