在 PyQt 中实现撤销和重做功能可以使用 QUndoStack 类。QUndoStack 提供了一个可用于记录操作的栈,每当执行操作时,该操作会被压入栈中,以便随时进行撤销和重做。
以下是一个简单的示例程序,演示了如何使用 QUndoStack 实现撤销和重做功能:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QTextEdit, QUndoCommand, \
QUndoStack
class TextEditCommand(QUndoCommand):
def __init__(self, widget, old_text):
super().__init__("TextEdit")
self.widget = widget
self.new_text = widget.toPlainText()
self.old_text = old_text
def undo(self):
self.widget.setPlainText(self.old_text)
def redo(self):
self.widget.setPlainText(self.new_text)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# 创建文本编辑器和菜单项
self.text_edit = QTextEdit()
self.undo_stack = QUndoStack()
undo_action = QAction("Undo", self)
redo_action = QAction("Redo", self)
# 将菜单项添加到菜单栏中
edit_menu = self.menuBar().addMenu("&Edit")
edit_menu.addAction(undo_action)
edit_menu.addAction(redo_action)
# 将文本编辑器添加到窗口中
self.setCentralWidget(self.text_edit)
# 连接菜单项的槽函数
undo_action.triggered.connect(self.undo_stack.undo)
redo_action.triggered.connect(self.undo_stack.redo)
# 连接文本编辑器的槽函数
self.text_edit.textChanged.connect(self.on_text_changed)
def on_text_changed(self):
# 当文本内容发生变化时,将新旧内容保存到命令对象中,并将命令对象添加到栈中
command = TextEditCommand(self.text_edit, self.text_edit.toPlainText())
self.undo_stack.push(command)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
在这个示例程序中,我们创建了一个主窗口,其中包含一个文本编辑器和撤销/重做菜单项。当用户修改文本时,我们创建一个 TextEditCommand 对象来记录新旧文本内容,并将其添加到 QUndoStack 中。
TextEditCommand 继承自 QUndoCommand 类,并实现了 undo() 和 redo() 方法。在 undo() 方法中,我们通过调用 QTextEdit 的 setPlainText() 方法来恢复旧的文本内容;在 redo() 方法中,则是通过调用 setPlainText() 方法来恢复新的文本内容。
注意,在 on_text_changed() 槽函数中,我们创建了一个新的 TextEditCommand 对象,并将其推送到栈中。如果用户连续多次输入字符,那么每个字符都会被记录为一个单独的命令对象,并且可以进行撤销和重做操作。
最后,在菜单项的触发信号上连接 QUndoStack 的 undo() 和 redo() 操作即可完成撤销和重做功能。