QUndoCommand的使用——实现undo/redo

实现思路

1、简要介绍undo、redo的原理
2、在Qt中实现undo、redo的要点
3、在Qt中实现undo、redo的实例

例子实现效果如下:
QUndoCommand的使用——实现undo/redo_第1张图片

可以看到数字的变化为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方法

你可能感兴趣的:(QT,pyqt5,undo,redo,撤销,删除,python)