启用排序后,如何正确更新QTableWidget中特定行的数据。我注意到,当我更改启用了排序的列的数据时,这些行会立即重新排序,结果第二列的数据被放在错误的行中。
这是开始的屏幕截图:
接下来,我双击C行以对其进行编辑,如下所示:
现在,您会看到它正确地更改了第0列中的数据以显示ZZZ,但是第二列文本现在位于错误的行中。我该如何解决?
import os, sys, json
from PySide import QtGui, QtCore
class TokenEditorDialog(QtGui.QDialog):
def __init__(self, key, value, parent=None):
super(TokenEditorDialog, self).__init__(parent)
self.resize(300,50)
self.uiKey = QtGui.QLineEdit(key)
self.uiValue = QtGui.QLineEdit(value)
self.uiOk = QtGui.QPushButton('OK')
self.uiCancel = QtGui.QPushButton('Cancel')
self.uiButtons = QtGui.QDialogButtonBox()
self.uiButtons.addButton(self.uiOk, QtGui.QDialogButtonBox.ActionRole)
self.uiButtons.addButton(self.uiCancel, QtGui.QDialogButtonBox.ActionRole)
self.layout = QtGui.QFormLayout()
self.layout.addRow('Key', self.uiKey)
self.layout.addRow('Value', self.uiValue)
self.layout.addWidget(self.uiButtons)
self.setLayout(self.layout)
# connections
self.uiOk.clicked.connect(self.accept)
self.uiCancel.clicked.connect(self.close)
class TokenEditorWidget(QtGui.QWidget):
def __init__(self, tokens, parent=None):
super(TokenEditorWidget, self).__init__(parent)
self.resize(400, 400)
self.setWindowTitle('Token Editor')
# privates
self.uiView = QtGui.QTableWidget()
self.uiView.setSortingEnabled(True)
self.uiView.setAlternatingRowColors(True)
self.uiView.verticalHeader().hide()
self.uiView.horizontalHeader().show()
self.uiView.setShowGrid(False)
self.uiView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self.uiView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.uiView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.selection = self.uiView.selectionModel()
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.uiView)
self.setLayout(self.layout)
self.createActions()
self.createMenus()
# connections
self.selection.selectionChanged.connect(self.updateControls)
self.uiView.itemDoubleClicked.connect(self.editSelectedItem)
self.uiView.customContextMenuRequested.connect(self.showContextMenu)
# initialize
self.setTokens(tokens)
self.updateControls()
def setTokens(self, tokens):
'''
Description:
Loop through tuples and append table
'''
self.uiView.setColumnCount(2)
self.uiView.setRowCount(0)
self.uiView.setHorizontalHeaderLabels(['Key', 'Value'])
for k, v in tokens:
rowIndex = self.uiView.rowCount()
self.uiView.insertRow(rowIndex)
self.uiView.setItem(rowIndex, 0, QtGui.QTableWidgetItem(k))
self.uiView.setItem(rowIndex, 1, QtGui.QTableWidgetItem(v))
self.uiView.resizeColumnsToContents()
self.uiView.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.uiView.horizontalHeader().setStretchLastSection(True)
def updateControls(self):
state = len(self.selection.selectedRows())
self.act_remove.setEnabled( state >= 1)
self.act_edit.setEnabled( state == 1)
def createActions(self):
self.act_add = QtGui.QAction('Add New...', self)
# self.act_add.triggered.connect(self.saveHotkeysPreset)
self.act_edit = QtGui.QAction('Edit...', self)
self.act_edit.triggered.connect(self.editSelectedItem)
self.act_remove = QtGui.QAction('Remove', self)
self.act_remove.triggered.connect(self.removeSelectedItems)
self.act_clear = QtGui.QAction('Clear', self)
self.act_clear.triggered.connect(self.clearItems)
def createMenus(self):
self.file_menu = QtGui.QMenu('File')
self.file_menu.addAction(self.act_add)
self.file_menu.addSeparator()
self.file_menu.addAction(self.act_edit)
self.file_menu.addAction(self.act_remove)
self.file_menu.addSeparator()
self.file_menu.addAction(self.act_clear)
# self.menuBar().addMenu(self.file_menu)
menuBar = QtGui.QMenuBar(self)
menuBar.addMenu(self.file_menu)
self.layout.setMenuBar(menuBar)
def removeSelectedItems(self):
indices = []
selectedRows = self.selection.selectedRows()
for x in selectedRows:
indices.append(QtCore.QPersistentModelIndex(x))
for x in indices:
self.uiView.removeRow(x.row())
def clearItems(self):
self.setTokens([])
def showContextMenu(self):
self.file_menu.exec_(QtGui.QCursor.pos())
def editSelectedItem(self):
selectedRows = self.selection.selectedRows()
if selectedRows:
# rowIndex = QtCore.QPersistentModelIndex(selectedRows[0])
rowIndex = selectedRows[0].row()
key = self.uiView.item(rowIndex, 0).text()
value = self.uiView.item(rowIndex, 1).text()
dlg = TokenEditorDialog(key, value, parent=self)
if dlg.exec_():
self.uiView.item(rowIndex, 0).setText(dlg.uiKey.text())
self.uiView.item(rowIndex, 1).setText(dlg.uiValue.text())
def main():
app = QtGui.QApplication(sys.argv)
ex = TokenEditorWidget(
tokens=[
('A', 'Description'),
('B', 'Description'),
('C', 'Description'),
('D', 'Description'),
('E', 'Description'),
('F', 'Description'),
],
)
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
答案 0 :(得分:0)
我认为问题在于,随着第一列项目的修改,表格将进行排序,然后第二项目被修改。信号'dataChanged'可能已连接到排序。
我的解决方案仅限于您的代码,这可能不是最好的方法。我通常更喜欢为这种事情编写自己的模型视图类。
您只需按照以下步骤修改editSelectedItem
方法:
def editSelectedItem(self):
selectedRows = self.selection.selectedRows()
if selectedRows:
# rowIndex = QtCore.QPersistentModelIndex(selectedRows[0])
rowIndex = selectedRows[0].row()
key = self.uiView.item(rowIndex, 0).text()
value = self.uiView.item(rowIndex, 1).text()
dlg = TokenEditorDialog(key, value, parent=self)
if dlg.exec_():
# this line retrieves the current column index of the sorting on the table
icol = self.uiView.horizontalHeader().sortIndicatorSection()
if icol == 0:
self.uiView.item(rowIndex, 1).setText(dlg.uiValue.text())
self.uiView.item(rowIndex, 0).setText(dlg.uiKey.text())
elif icol == 1:
self.uiView.item(rowIndex, 0).setText(dlg.uiKey.text())
self.uiView.item(rowIndex, 1).setText(dlg.uiValue.text())
else:
# if you want to add more cases
pass
希望对您有帮助。