2015-11-11 134 views
0

我在使用QListView和QStandardItemModel實現拖放重排序時遇到了一些問題。使用itemChanged信號處理選中的項目是可以的,但是當使用拖放對項目進行重新排序時,似乎在觸發信號時會創建一個臨時項目。列表中有5個項目,但是每次重新排序項目時,即使最後只有5個可見,模型行數也變爲6。爲什麼當我特別設定動作移動時,它會暫時變爲6?我想僅處理新訂單中的5個項目,因爲該列表直接用於更新另一個窗口小部件。我嘗試了dataChange信號,但沒有區別。PyQt:QListView拖放重排序信號問題

我的設置是PyQt的4.11.4與Python 2.7.10在Win 7

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_()) 

回答

2

更新,我發現這是一個解決方法,它涉及到使用singleshot計時器。在將物品放入列表中後,計時器觸發插槽並找到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_())