PyQt:QListView 拖放重新排序信号问题
Posted
技术标签:
【中文标题】PyQt:QListView 拖放重新排序信号问题【英文标题】:PyQt: QListView drag and drop reordering signal issue 【发布时间】:2015-11-11 16:32:02 【问题描述】:我在使用 QListView 和 QStandardItemModel 实现拖放重新排序时遇到了一些麻烦。使用 itemChanged 信号处理选中的项目很好,但是当使用拖放重新排序项目时,似乎在触发信号时创建了一个临时项目。列表中有 5 个项目,但是每次重新排序项目时,模型行数变为 6,即使最后只有 5 个可见。为什么当我专门设置动作移动时它会暂时变成6?我只想处理新订单中的 5 个项目,因为该列表直接用于更新另一个小部件。我尝试了 dataChange 信号,但没有任何区别。
我的设置是 Win 7 上的 PyQt 4.11.4 和 Python 2.7.10。
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_())
【问题讨论】:
【参考方案1】:更新,我找到了一个解决方法,它涉及使用单次计时器。在列表中删除一个项目后,计时器会触发插槽,它会以新顺序找到 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_())
【讨论】:
以上是关于PyQt:QListView 拖放重新排序信号问题的主要内容,如果未能解决你的问题,请参考以下文章
PyQt QListView 拖放问题,用于在一个列表中导入和重新排列
在 PyQt 中使用拖放重新排序 QTreeWidget 中的项目