实现思路
1、简要介绍undo、redo的原理
2、在Qt中实现undo、redo的要点
3、在Qt中实现undo、redo的实例
例子实现效果如下:
可以看到数字的变化为0、64、12、16、60,当我们使用undo的时候,数字从60一直变回到0,此时我们再使用redo,数字又从0变到60
1、简要介绍undo、redo的原理
有一个堆,用于存放每一次的操作(当然也可以是数据),每次操作都把当前的操作(数据)push进这个堆,因为堆是先进后出的,也就是后面进的先出来,也就符合了我们undo、redo的使用规律。
2、在Qt中实现undo、redo的要点
Qt中有一个“QUndoStack”对应于上述所说的堆,推进堆内的东西是一个command的,也就是一个需求,在Qt中有个类“QUndoCommand”,我们只要实现其内部的redo、undo,并在每次操作过后创建对应的command并将其推入“QUndoStack”中,就可以实现redo、undo的效果
3、在Qt中实现undo、redo的实例
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import sys
import random
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QPushButton, QWidget, QUndoCommand, \
QUndoStack, QSlider, QLabel
class SliderCommand(QUndoCommand):
def __init__(self, sld, preValue, curValue, parent=None):
super(SliderCommand, self).__init__(parent)
self.sld = sld
self.preValue = preValue
self.curValue = curValue
self.setText("文字redo/undo")
def redo(self):
self.sld.setValue(self.curValue)
def undo(self):
self.sld.setValue(self.preValue)
class ComplexDrag(QWidget):
def __init__(self):
super(ComplexDrag, self).__init__()
self.undoInit()
self.initUI()
def undoInit(self):
self.undoStack = QUndoStack(self)
self.undoStack.setUndoLimit(50)
undoAction = self.undoStack.createUndoAction(self, "Undo")
undoAction.setShortcut("Ctrl+Z")
redoAction = self.undoStack.createRedoAction(self, "Redo")
redoAction.setShortcut("Ctrl+Shift+Z")
self.addAction(undoAction)
self.addAction(redoAction)
def initUI(self):
verLayout = QVBoxLayout()
horLayout = QHBoxLayout()
self.actionBtn = QPushButton("doAction")
self.actionBtn.clicked.connect(self.doActionFunc)
self.lable = QLabel()
self.lable.setText("当前值为:0")
self.sld = QSlider(Qt.Horizontal, self)
self.sld.setFocusPolicy(Qt.NoFocus)
self.sld.setGeometry(30, 40, 100, 30)
self.sld.valueChanged[int].connect(self.onValueChanged)
verLayout.addWidget(self.sld)
verLayout.addWidget(self.lable)
horLayout.addWidget(self.actionBtn)
verLayout.addLayout(horLayout)
self.setLayout(verLayout)
self.setWindowTitle("Redo and Undo")
def doActionFunc(self):
curValue = random.randint(0, 100)
command = SliderCommand(self.sld, self.sld.value(), curValue)
self.undoStack.push(command)
def onValueChanged(self, num):
self.lable.setText("当前值为:" + str(num))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = ComplexDrag()
ex.show()
app.exec_()
主要分析:
1、首先创建一个堆 self.undoStack = QUndoStack(self)
2、为这个堆创建undo、redo对应的action以及对应的快捷键,详细看undoInit方法
3、我们通过一个按钮改变slider的值
4、点击这个按钮就是一个操作,我们为这个操作创建command即SliderCommand
5、在SliderCommand中实现对应的redo、undo方法