在 Tkinter Entry 小部件中撤消和重做?
有没有办法在 Tkinter Entry
小部件中添加撤消和重做功能,或者我必须使用单行Text
小部件对于这种类型的功能?
如果是后者,在配置 Text
小部件以充当 Entry
小部件时,我应该遵循哪些提示?
一些可能需要调整的功能包括捕获 Return
KeyPress
、将 Tab 键按下转换为更改焦点的请求,以及从剪贴板粘贴的文本中删除换行符。
Is there a way to add undo and redo capabilities in Tkinter Entry
widgets or must I use single line Text
widgets for this type of functionality?
If the latter, are there any tips I should follow when configuring a Text
widget to act as an Entry
widget?
Some features that might need tweaking include trapping the Return
KeyPress
, converting tab keypresses into a request to change focus, and removing newlines from text being pasted from the clipboard.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
检查 Tkinter 自定义条目。我添加了剪切、复制、粘贴上下文菜单和撤消重做功能。
Check the Tkinter Custom Entry. I have added Cut, Copy, Paste context menu, and undo redo functions.
免责声明:这些只是我想到的关于如何实施它的想法。
运行一个线程,每 X 秒(0.5?)保存一次条目的状态:
您还可以设置保存条目状态的事件,例如
Return
的压力。或
注意根据需要设置锁。
Disclaimer: these are just thoughts that come into my mind on how to implement it.
Run a thread that every X seconds (0.5?) save the state of the entry:
You can also set up events that save the Entry's status too, such as the pressure of
Return
.or
Beware to set locks as needed.
使用此方法进行撤消/重做的更新:
我正在创建一个包含大量框架的 GUI,每个框架至少包含十个或更多“条目”小部件。
我使用了 History 类,并为我拥有的每个输入字段创建了一个历史对象。我能够将所有条目小部件值存储在列表中,如此处所示。
我正在使用附加到每个条目小部件的“trace”方法,该方法将调用 History 类的“add”函数并存储每个更改。通过这种方式,我无需单独运行任何线程就可以做到这一点。
但这样做的最大缺点是,我们不能用这种方法进行多次撤消/重做。
问题:
当我跟踪条目小部件的每一个更改并将其添加到列表中时,它还会“跟踪”我们“撤消/重做”时发生的更改,这意味着我们不能再退一步。一旦您执行撤消操作,就会跟踪更改,因此“撤消”值将添加到列表的末尾。因此这不是正确的方法。
解决方案:
实现此目的的完美方法是为每个条目小部件创建两个堆栈。一种用于“撤消”,一种用于“重做”。当条目发生更改时,将该值推送到撤消堆栈中。当用户按下撤消键时,从撤消堆栈中弹出最后存储的值,重要的是将此值推入“重做堆栈”。因此,当用户按下重做时,从重做堆栈中弹出最后一个值。
Update on using this method for Undo/Redo:
I am creating a GUI with lot of frames and each contains at least ten or more 'entry' widgets.
I used the History class and created one history object for each entry field that I had. I was able to store all entry widgets values in a list as done here.
I am using 'trace' method attached to each entry widget which will call 'add' function of History class and store each changes. In this way, I was able to do it without running any thread separately.
But the biggest drawback of doing this is, we cannot do multiple undos/redos with this method.
Issue:
When I trace each and every change of the entry widget and add that to the list, it also 'traces' the change that happens when we 'undo/redo' which means we cannot go more one step back. once u do a undo, it is a change that will be traced and hence the 'undo' value will be added to the list at the end. Hence this is not the right method.
Solution:
Perfect way to do this is by creating two stacks for each entry widget. One for 'Undo' and one for 'redo'. When ever there is a change in entry, push that value into the undo stack. When user presses undo, pop the last stored value from the undo stack and importantly push this one to the 'redo stack'. hence, when the user presses redo, pop the last value from redo stack.
基于 Evgeny 使用自定义
Entry
的回答,但添加了一个 tkinterStringVar
以及对小部件的跟踪,以更准确地跟踪何时对其内容进行更改(而不仅仅是当任何内容发生更改时)按下按键,这似乎将空的撤消/重做项目添加到堆栈中)。还使用 Python 双端队列添加了最大深度。如果我们通过代码而不是键盘输入来更改 Entry 的内容,我们可以暂时禁用跟踪(例如,请参阅下面的
undo
方法)。代码:
Based on Evgeny's answer with a custom
Entry
, but added a tkinterStringVar
with a trace to the widget to more accurately track when changes are made to its contents (not just when any Key is pressed, which seemed to add empty Undo/Redo items to the stack). Also added a max depth using a Python deque.If we're changing the contents of the Entry via code rather than keyboard input, we can temporarily disable the trace (e.g. see in the
undo
method below).Code: