短版
如何实现对PySide/PyQt中QListWidgetItems
所做编辑的撤消功能?在
来自Qt教程的提示?
下面为Qt用户(c++)编写的教程可能有答案,但我不是一个c++用户,所以有点迷失了:Using Undo/Redo with Item Views
加长版
我使用一个QListWidget
来学习如何绕过PyQt的Undo Framework(在这个主题的an article的帮助下)。当我自己实现一个命令(比如从列表中删除一个项目)时,我可以使用undo/redo。在
我还想让小部件中的QListWidgetItems
可编辑。这很简单:只需将ItemIsEditable
标志添加到每个项目。问题是,如何将这样的编辑推送到undo堆栈,然后才能撤消/重做它们?在
下面是一个简单的工作示例,它显示了一个列表,允许您删除项,以及撤消/重做这样的删除操作。应用程序同时显示列表和撤消堆栈。需要做什么才能将编辑放到堆栈上?在
简单的工作示例
from PySide import QtGui, QtCore
class TodoList(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.initUI()
self.show()
def initUI(self):
self.todoList = self.makeTodoList()
self.undoStack = QtGui.QUndoStack(self)
undoView = QtGui.QUndoView(self.undoStack)
buttonLayout = self.buttonSetup()
mainLayout = QtGui.QHBoxLayout(self)
mainLayout.addWidget(undoView)
mainLayout.addWidget(self.todoList)
mainLayout.addLayout(buttonLayout)
self.setLayout(mainLayout)
self.makeConnections()
def buttonSetup(self):
#Make buttons
self.deleteButton = QtGui.QPushButton("Delete")
self.undoButton = QtGui.QPushButton("Undo")
self.redoButton = QtGui.QPushButton("Redo")
self.quitButton = QtGui.QPushButton("Quit")
#Lay them out
buttonLayout = QtGui.QVBoxLayout()
buttonLayout.addWidget(self.deleteButton)
buttonLayout.addStretch()
buttonLayout.addWidget(self.undoButton)
buttonLayout.addWidget(self.redoButton)
buttonLayout.addStretch()
buttonLayout.addWidget(self.quitButton)
return buttonLayout
def makeConnections(self):
self.deleteButton.clicked.connect(self.deleteItem)
self.quitButton.clicked.connect(self.close)
self.undoButton.clicked.connect(self.undoStack.undo)
self.redoButton.clicked.connect(self.undoStack.redo)
def deleteItem(self):
rowSelected=self.todoList.currentRow()
rowItem = self.todoList.item(rowSelected)
if rowItem is None:
return
command = CommandDelete(self.todoList, rowItem, rowSelected,
"Delete item '{0}'".format(rowItem.text()))
self.undoStack.push(command)
def makeTodoList(self):
todoList = QtGui.QListWidget()
allTasks = ('Fix door', 'Make dinner', 'Read',
'Program in PySide', 'Be nice to everyone')
for task in allTasks:
todoItem=QtGui.QListWidgetItem(task)
todoList.addItem(todoItem)
todoItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
return todoList
class CommandDelete(QtGui.QUndoCommand):
def __init__(self, listWidget, item, row, description):
super(CommandDelete, self).__init__(description)
self.listWidget = listWidget
self.string = item.text()
self.row = row
def redo(self):
self.listWidget.takeItem(self.row)
def undo(self):
addItem = QtGui.QListWidgetItem(self.string)
addItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.listWidget.insertItem(self.row, addItem)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
myList=TodoList()
sys.exit(app.exec_())
注:我在QtCentre贴了一张earlier version of this question。在
你提到的那个教程真的没什么帮助。视图撤销重做实现的方法确实很多,我们只需要选择最简单的一种。如果处理小列表,最简单的方法是保存每次更改的所有数据,并在每次撤消或重做操作时从头恢复完整列表。在
如果仍然需要原子更改列表,可以使用
QListWidget::itemChanged
信号跟踪用户所做的编辑。这有两个问题:QObject::blockSignals
调用中以阻止不需要的信号。在QListWidget::currentItemChanged
,假设用户无法找到一种方法来编辑一个项目,而不首先使其成为当前的。在所以这是使其工作的更改(除了在两个地方添加
ItemIsEditable
标志):新的变革课程:
^{pr2}$每次验证并接受项的新文本时,将其另存为列表项数据。准半伪码:
对不起,如果它看起来太像C++了。在我会这样做:
创建一个自定义的^{} 并使用以下两个信号:
editorEvent
closeEditor
在
editorEvent
:保存当前状态On
closeEditor
:获取新状态并创建一个QUndoCommand
,它为Redo
设置新状态,为Undo
设置旧状态。在相关问题 更多 >
编程相关推荐