wxpython中文教程技巧撤销重做框架

发布时间:2020-04-08编辑:脚本学堂
有关wxpython中怎么撤销重做框架的方法,wxpython如何实现具备撤销以及重做用户动作的能力,wxpython中文教程的一个小技巧,感兴趣的朋友参考下。

python中怎么实现具备撤销以及重做用户动作的能力.

以下例子展示了这个功能如何在 wxPython 中完成.

专题:wxpython中文教程

例子:
 

复制代码 代码示例:

#!/usr/bin/python
#coding=utf-8

#newt.py

from wxPython.lib.sheet import *
from wx.lib.plot import *
import wx

stockUndo = []
stockRedo = []

class UndoText:
    def __init__(self, sheet, text1, text2, row, column):
        self.RedoText = text2
        self.row = row
        self.col = column
        self.UndoText = text1
        self.sheet = sheet
       
    def undo(self):
        self.RedoText = self.sheet.GetCellValue(self.row, self.col)
        if self.UndoText == None:
            self.sheet.SetCellValue('')
        else:
            self.sheet.SetCellValue(self.row, self.col, self.UndoText)
           
    def redo(self):
        if self.RedoText == None:
            self.sheet.SetCellValue('')
        else:
            self.sheet.SetCellValue(self.row, self.col, self.RedoText)

    def undo(self):
        self.RedoSize = self.sheet.GetColSize(self.pos)
        self.sheet.SetColSize(self.pos, self.UndoSize)
        self.sheet.ForceRefresh()
       
    def redo(self):
        self.UndoSize = 80
        self.sheet.SetColSize(self.pos, self.RedoSize)
        self.sheet.ForceRefresh()
       
class UndoRowSize:
    def __init__(self, sheet, position, size):
        self.sheet = sheet
        self.pos = position
        self.RedoSize = size
        self.UndoSize = 20
       
    def undo(self):
        self.RedoSize = self.sheet.GetRowSize(self.pos)
        self.sheet.SetRowSize(self.pos, self.UndoSize)
        self.sheet.ForceRefresh()
       
    def redo(self):
        self.UndoSize = 20
        self.sheet.SetRowSize(self.pos, self.RedoSize)
        self.sheet.ForceRefresh()
       
class MySheet(CSheet):
    instance = 0
    def __init__(self, parent):
        CSheet.__init__(self, parent)
        self.SetLabelBackgroundColour('#DBD4D4')
        self.SetRowLabelAlignment(wx.ALIGN_CENTER,
                                  wx.ALIGN_CENTER)
        self.text = ''
    def OnCellChange(self, event):
        toolbar = self.GetParent().toolbar1
        if not toolbar.GetToolEnabled(808):
            toolbar.EnableTool(808, True)
        r = event.GetRow()
        c = event.GetCol()
        text = self.GetCellValue(r, c)
        #self.text -- 改变之前的文本
        #text -- 改变之后的文本
        undo = UndoText(self, self.text, text, r, c)
        stockUndo.append(undo)
       
        if stockRedo:
            #这看起来有些惊讶,不过确实是所有电子表格程序的标准行为
            del stockRedo[:]
            toolbar.EnableTool(809, False)
           
    def OnColSize(self, event):
        toolbar = self.GetParent().toolbar1
        if not toolbar.GetToolEnabled(808):
            toolbar.EnableTool(808, True)
           
        pos = event.GetRowOrCol()
        size = self.GetColSize(pos)
        undo = UndoColSize(self, pos, size)
        stockUndo.append(undo)
       
        if stockRedo:
            del stockRedo[:]
            toolbar.EnableTool(809, False)

    def OnRowSize(self, event):
        toolbar = self.GetParent().toolbar1
        if not toolbar.GetToolEnabled(808):
            toolbar.EnableTool(808, True)
           
        pos = event.GetRowOrCol()
        size = self.GetRowSize(pos)
        undo = UndoRowSize(self, pos, size)
       
        stockUndo.append(undo)       
        if stockRedo:
            del stockRedo[:]
            toolbar.EnableTool(809, False)           
       
class Newt(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, -4, title, size=(550, 500),
                          style=wx.DEFAULT_FRAME_STYLE
                          |wx.NO_FULL_REPAINT_ON_RESIZE)
       
        box = wx.BoxSizer(wx.VERTICAL)
        menuBar = wx.MenuBar()
        menu1 = wx.Menu()
        quit = wx.MenuItem(menu1, 105, "退出(&QtCtrl+Q)", "退出 Newt")
        quit.SetBitmap(wx.Image('icons/stock_exit-16.png',
                                wx.BITMAP_TYPE_PNG).ConvertToBitmap())
        menu1.AppendItem(quit)
        menuBar.Append(menu1, "文件(&F)")
        self.Bind(wx.EVT_MENU, self.OnQuitNewt, id=105)
        self.SetMenuBar(menuBar)
        #设置工具栏
        self.toolbar1 = wx.ToolBar(self, id=-1, style=wx.TB_HORIZONTAL
                                   |wx.NO_BORDER|wx.TB_FLAT|wx.TB_TEXT)
        self.toolbar1.AddSimpleTool(808,
                                    wx.Image('icons/stock_undo.png',
                                             wx.BITMAP_TYPE_PNG).
                                    ConvertToBitmap(), '撤销', '')
        self.toolbar1.AddSimpleTool(809,
                                    wx.Image('icons/stock_redo.png',
                                             wx.BITMAP_TYPE_PNG).
                                    ConvertToBitmap(), '重做', '')

        self.toolbar1.EnableTool(808, False)
        self.toolbar1.EnableTool(809, False)
        self.toolbar1.AddSeparator()
        self.toolbar1.AddSimpleTool(813,
                                    wx.Image('icons/stock_exit.png',
                                             wx.BITMAP_TYPE_PNG).
                                    ConvertToBitmap(), '退出', '')
        self.toolbar1.Realize()
        self.toolbar1.Bind(wx.EVT_TOOL, self.OnUndo, id=808)
        self.toolbar1.Bind(wx.EVT_TOOL, self.OnRedo, id=809)
        self.toolbar1.Bind(wx.EVT_TOOL, self.OnQuitNewt, id=813)
        box.Add(self.toolbar1, border=5)
        box.Add((5, 10), 0)
        self.SetSizer(box)
        self.sheet1 = MySheet(self)
        self.sheet1.SetNumberRows(55)
        self.sheet1.SetNumberCols(25)
        for i in range(self.sheet1.GetNumberRows()):
            self.sheet1.SetRowSize(i, 20)
        self.sheet1.SetFocus()
        box.Add(self.sheet1, 1, wx.EXPAND)
        self.CreateStatusBar()
        self.Center()
        self.Show(True)
       
    def OnUndo(self, event):
        if len(stockUndo) == 0:
            return
       
        a = stockUndo.pop()
        if len(stockUndo) == 0:
            self.toolbar1.EnableTool(808, False)
           
        a.undo()
        stockRedo.append(a)
        self.toolbar1.EnableTool(809, True)

    def OnRedo(self, event):
        if len(stockRedo) == 0:
            return
       
        a = stockRedo.pop()
        if len(stockRedo) == 0:
            self.toolbar1.EnableTool(809, False)
           
        a.undo()
        stockUndo.append(a)
        self.toolbar1.EnableTool(808, True)
       
    def OnQuitNewt(self, event):
        self.Close()
       
app = wx.PySimpleApp()
newt = Newt(None, -1, "Newt")
app.MainLoop()

在这个例子中,想要对单元格文本改变、列和行大小改变上的撤销和重做. 因此必须要将相关事件绑定到我们的方法上.
而这些绑定在示例代码中是看不到的.

可以在 CSheet 类的 sheet.py 文件中找到这些代码:
 

self.Bind(wx.grid.EVT_GRID_ROW_SIZE, self.OnRowSize)
self.Bind(wx.grid.EVT_GRID_COL_SIZE, self.OnColSize)
self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnCellChange)
 

在上面的 3 个方法中,我们创建了 3 个 Undo 对象. 它们分别是:UndoText、UndoColSize 以及 UndoRowSize,每个对象又有两个方法. undo() 以及 redo(). 两个方法负责在改变完成之前和之后将应用程序带入相应状态. 此后 3 个对象被追加到 stockUndo 清单中. 这样来确保所有必要的改变都给存储起来. 最后,当我们按下撤销、重做按钮,就会调用 OnUndo()  以及 OnRedo()方法。

以下方法调用才是真正完成工作的:
a.undo()
a.redo()
3 个对象随之在 stockUndo 和 stockRedo 清单之间移动.
而在两个清单中不再有对象剩下时,就通过 EnableTool() 方法来令到按钮失效.

如图:
wxpython撤销重做框架
图:newt.py