有没有办法在 Tkinter小部件中添加撤消和重做Entry
功能,或者我必须使用单行Text
小部件来实现此类功能?
Text
如果是后者,在将小部件配置为小部件时我应该遵循什么提示Entry
?
一些可能需要调整的功能包括捕获Return
KeyPress
、将 tab 按键转换为更改焦点的请求,以及从剪贴板粘贴的文本中删除换行符。
有没有办法在 Tkinter小部件中添加撤消和重做Entry
功能,或者我必须使用单行Text
小部件来实现此类功能?
Text
如果是后者,在将小部件配置为小部件时我应该遵循什么提示Entry
?
一些可能需要调整的功能包括捕获Return
KeyPress
、将 tab 按键转换为更改焦点的请求,以及从剪贴板粘贴的文本中删除换行符。
检查 Tkinter 自定义条目。我添加了剪切、复制、粘贴上下文菜单和撤消重做功能。
# -*- coding: utf-8 -*-
from tkinter import *
class CEntry(Entry):
def __init__(self, parent, *args, **kwargs):
Entry.__init__(self, parent, *args, **kwargs)
self.changes = [""]
self.steps = int()
self.context_menu = Menu(self, tearoff=0)
self.context_menu.add_command(label="Cut")
self.context_menu.add_command(label="Copy")
self.context_menu.add_command(label="Paste")
self.bind("<Button-3>", self.popup)
self.bind("<Control-z>", self.undo)
self.bind("<Control-y>", self.redo)
self.bind("<Key>", self.add_changes)
def popup(self, event):
self.context_menu.post(event.x_root, event.y_root)
self.context_menu.entryconfigure("Cut", command=lambda: self.event_generate("<<Cut>>"))
self.context_menu.entryconfigure("Copy", command=lambda: self.event_generate("<<Copy>>"))
self.context_menu.entryconfigure("Paste", command=lambda: self.event_generate("<<Paste>>"))
def undo(self, event=None):
if self.steps != 0:
self.steps -= 1
self.delete(0, END)
self.insert(END, self.changes[self.steps])
def redo(self, event=None):
if self.steps < len(self.changes):
self.delete(0, END)
self.insert(END, self.changes[self.steps])
self.steps += 1
def add_changes(self, event=None):
if self.get() != self.changes[-1]:
self.changes.append(self.get())
self.steps += 1
免责声明:这些只是我想到如何实施它的想法。
class History(object):
def __init__(self):
self.l = ['']
self.i = 0
def next(self):
if self.i == len(self.l):
return None
self.i += 1
return self.l[self.i]
def prev(self):
if self.i == 0:
return None
self.i -= 1
return self.l[self.i]
def add(self, s):
del self.l[self.i+1:]
self.l.append(s)
self.i += 1
def current(self):
return self.l[self.i]
运行一个线程,每 X 秒(0.5?)保存条目的状态:
history = History()
...
history.add(stringval.get())
您还可以设置保存条目状态的事件,例如 的压力Return
。
prev = history.prev()
if prev is not None:
stringvar.set(prev)
或者
next = history.next()
if next is not None:
stringvar.set(next)
注意根据需要设置锁。
使用此方法进行撤消/重做的更新:
我正在创建一个包含很多框架的 GUI,每个框架都包含至少十个或更多“入口”小部件。我使用了 History 类,并为我拥有的每个输入字段创建了一个历史对象。我能够将所有条目小部件值存储在列表中,如此处所做的那样。我正在使用附加到每个条目小部件的“跟踪”方法,该方法将调用历史类的“添加”功能并存储每个更改。通过这种方式,我能够在不单独运行任何线程的情况下做到这一点。但是这样做的最大缺点是,我们不能使用这种方法进行多次撤消/重做。
问题:当我跟踪条目小部件的每一次更改并将其添加到列表中时,它也会“跟踪”当我们“撤消/重做”时发生的更改,这意味着我们不能再退一步。一旦您进行撤消,它就是将被跟踪的更改,因此“撤消”值将被添加到最后的列表中。因此,这不是正确的方法。
解决方案:完美的方法是为每个条目小部件创建两个堆栈。一个用于“撤消”,一个用于“重做”。当条目发生变化时,将该值推入撤消堆栈。当用户按下撤消时,从撤消堆栈中弹出最后存储的值,重要的是将此值推送到“重做堆栈”。因此,当用户按下重做时,从重做堆栈中弹出最后一个值。