Зачем щелкать элементы в qlistview, чтобы вернуть их в предыдущее состояние после перетаскивания?
Я реализовал перетаскивание, чтобы изменить порядок элементов в представлении списка, и все мои выходные данные отладки указывают, что это работает должным образом. Однако, когда я снова выбираю элемент, он возвращается к тому, что было раньше в представлении, и когда он становится невыбранным, это изменение также происходит в модели.
Пример:
Список представлений показывает Модель показывает а, б, в, да, б, в, д после перетаскивания b, c, d, ab, c, d, a щелкнув по первому пункту a, c, d, ab, c, d, a щелкнув по второму пункту a, b, d, aa, c, d, a и т.п.
Надеюсь, это имеет смысл. Любые предложения, почему это может происходить? (пример кода сложен, так как это часть большого приложения)
Изменить: это лучшее, что я могу сделать для кода.
Настраиваемое представление списка (у меня есть настраиваемое представление списка, потому что оно должно излучать сигнал, когда элементы перемещаются, а indexesMoved кажется поврежденным):
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import traceback
class ListOrderView(QListView):
itemMoved = pyqtSignal(int, int, QStandardItem) # Old index, new index, item
def __init__(self, parent=None):
try:
super(ListOrderView, self).__init__(parent)
self.setAcceptDrops(True)
self.setDragEnabled(True)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDefaultDropAction(Qt.MoveAction)
self.dragItem = None
self.dragRow = None
except:
Trace2.WriteLine(str(traceback.format_exc())) #writes stuff to a log file
def dropEvent(self, event):
try:
super(ListOrderView, self).dropEvent(event)
self.itemMoved.emit(self.dragRow, self.row(self.dragItem), self.dragItem)
self.dragItem = None
except:
Trace2.WriteLine(str(traceback.format_exc()))
def startDrag(self, supportedActions):
try:
self.dragItem = self.currentItem()
self.dragRow = self.row(self.dragItem)
super(ListOrderView, self).startDrag(Qt.MoveAction)
except:
Trace2.WriteLine(str(traceback.format_exc()))
def currentItem(self):
index = self.currentIndex()
item = self.model().itemFromIndex(index)
return item
def row(self, item):
index = self.selectedIndexes()[0]
row = index.row()
return row
Графический интерфейс, который его использует (просто форма с настраиваемым представлением списка, созданная в Qt Designer):
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from FormsUI.ListOrderControlUI import Ui_ListOrderControl
import traceback
class ListOrderControl(QWidget, Ui_ListOrderControl):
def __init__(self, parent=None):
super(ListOrderControl, self).__init__(parent)
self.setupUi(self)
self.model = QStandardItemModel()
self.model.setSupportedDragActions(Qt.MoveAction)
self.listOrderView.setModel(self.model) #the custom list view
self.model.dataChanged.connect(self.onDataChanged)
def addItem(self, string, select=False):
item = QStandardItem(string)
item.setDropEnabled(False)
self.model.invisibleRootItem().appendRow(item)
if select:
self.listOrderView.selectionModel().setCurrentIndex(self.model.indexFromItem(item), QItemSelectionModel.ClearAndSelect)
def setNewItem(self, row, item):
self.model.setItem(row, item)
def removeRows(self, row, count):
self.model.removeRows(row, count)
# This is here because items are becoming drop enabled when they become unselected.
# No idea why.
def onDataChanged(self, topLeft, bottomRight):
try:
i = topLeft.row()
while i <= bottomRight.row():
item = self.model.item(i)
item.setDropEnabled(False)
i+=1
except:
Trace2.WriteLine(str(traceback.format_exc()))
def printModelContents(self):
Trace2.WriteLine("[LISTCONTROL] item order is:")
for i in range(self.model.rowCount()):
Trace2.WriteLine("\t" + str(self.model.item(i).data(Qt.DisplayRole).toString()) + " dropEnabled = " + str(self.model.item(i).isDropEnabled()))
1 ответ
Оказывается, перетаскивание работало нормально. Сначала немного предыстории. Этот вид списка является частью пользовательского виджета, используемого в нескольких местах большого приложения. В этом конкретном месте нажатие на элемент в списке приводит к тому, что некоторые поля в родительском виджете включаются и заполняются информацией об этом элементе. Это делается на основе текущего выбора в представлении списка. Одним из полей является строка редактирования имени элемента. Когда его содержимое изменяется, оно автоматически обновляет имя своего элемента.
Это означает, что когда элемент перетаскивается, а выделение остается позади, содержимое редактирования строки изменяется, обновляя элемент, который теперь находится в том месте, где перетаскиваемый элемент находился в представлении, но не в модели до тех пор, пока через какое-то сигнал / слот вуду.
В конечном счете, это был ответ; заставить модель излучать сигнал со строкой, в которую был отброшен элемент, и обновлять / заполнять поля, основанные на этом, вместо модели выбора.