Tkinter Entry 元件中的撤銷和重做


使用 Tkinter 在 Python 中開發圖形使用者介面 (GUI) 時,務必為使用者提供高效且直觀的編輯功能,包括撤消和重做在文字輸入欄位中所做的更改的能力。雖然 Tkinter 的 Entry 元件本身並不支援撤銷和重做功能,但我們可以使用稍微不同的方法來實現它。

在本文中,我們將探討如何使用內建的 Text 元件並自定義其行為,在 Tkinter Entry 元件中整合撤銷和重做操作。

瞭解 Tkinter 中的 Entry 元件:在深入探討實現細節之前,讓我們首先了解 Tkinter 中的 Entry 元件。Entry 元件是用於單行文字輸入的標準 Tkinter 元件。預設情況下,Entry 元件不提供對撤銷和重做操作的內建支援。但是,我們可以利用支援撤銷和重做的 Text 元件,並對其進行自定義以使其行為類似於單行 Entry 元件。

實現撤銷和重做功能

為了在 Tkinter Entry 元件中啟用撤銷和重做操作,我們將建立一個從 Text 元件繼承並覆蓋某些方法以實現所需功能的自定義元件類。

步驟 1:匯入所需的模組

首先,從 Tkinter 匯入必要的模組。

import tkinter as tk

步驟 2:建立自定義 Entry 元件類

接下來,建立一個從 Text 元件繼承並覆蓋特定方法的自定義 Entry 元件類。

class UndoableEntry(tk.Text):
   def __init__(self, master=None, **kwargs):
      super().__init__(master, **kwargs)
      self.bind("<Control-z>", self.undo)
      self.bind("<Control-y>", self.redo)
      self.bind("<Key>", self.on_key_press)

      self.undo_stack = []
      self.redo_stack = []

   def undo(self, event=None):
      if self.undo_stack:
         text = self.undo_stack.pop()
         self.redo_stack.append(self.get("1.0", "end"))
         self.delete("1.0", "end")
         self.insert("1.0", text)

   def redo(self, event=None):
      if self.redo_stack:
         text = self.redo_stack.pop()
         self.undo_stack.append(self.get("1.0", "end"))
         self.delete("1.0", "end")
         self.insert("1.0", text)

   def on_key_press(self, event):
      if event.keysym not in ["Control_L", "Control_R", "z", "y"]:
         self.undo_stack.append(self.get("1.0", "end"))
         self.redo_stack.clear()

在這個自定義的 UndoableEntry 類中,我們覆蓋了三個方法:undo、redo 和 on_key_press。

當用戶按下 Ctrl+Z 時,會觸發 undo 方法。它檢查撤銷堆疊中是否有任何專案,如果有,則檢索最後的狀態,將當前狀態儲存在重做堆疊中,清除 Entry 元件,然後插入檢索到的文字。

當用戶按下 Ctrl+Y 時,會觸發 redo 方法。它檢查重做堆疊中是否有任何專案,如果有,則檢索最後的狀態,將當前狀態儲存在撤銷堆疊中,清除 Entry 元件,然後插入檢索到的文字。

on_key_press 方法在按下任何鍵(不包括撤銷和重做鍵組合)時呼叫。它將當前狀態儲存在撤銷堆疊中,並清除重做堆疊,允許使用者在鍵入或刪除文字時建立多個撤銷點。

步驟 3:使用自定義 Entry 元件實現 GUI

現在,讓我們建立一個包含自定義 UndoableEntry 元件的 GUI。

def main():
   root = tk.Tk()

   entry = UndoableEntry(root, height=1)
   entry.pack()

   root.mainloop()

if __name__ == "__main__":
   main()

在這個示例中,我們建立自定義 UndoableEntry 元件的例項,並將其打包到主視窗中。

示例

import tkinter as tk

class UndoableEntry(tk.Text):
   def __init__(self, master=None, **kwargs):
      super().__init__(master, **kwargs)
      self.bind("<Control-z>", self.undo)
      self.bind("<Control-y>", self.redo)
      self.bind("<Key>", self.on_key_press)

      self.undo_stack = []
      self.redo_stack = []

   def undo(self, event=None):
      if self.undo_stack:
         text = self.undo_stack.pop()
         self.redo_stack.append(self.get("1.0", "end"))
         self.delete("1.0", "end")
         self.insert("1.0", text)

   def redo(self, event=None):
      if self.redo_stack:
         text = self.redo_stack.pop()
         self.undo_stack.append(self.get("1.0", "end"))
         self.delete("1.0", "end")
         self.insert("1.0", text)

    def on_key_press(self, event):
      if event.keysym not in ["Control_L", "Control_R", "z", "y"]:
         self.undo_stack.append(self.get("1.0", "end"))
         self.redo_stack.clear()
def main():
   root = tk.Tk()
   root.title("Undo and Redo in a Tkinter Entry Widget")
   root.geometry("720x250")

   entry = UndoableEntry(root, height=1)
   entry.pack()

   root.mainloop()

if __name__ == "__main__":
   main()

輸出

使用者可以使用 **Ctrl+Z** 組合鍵撤銷更改,使用 **Ctrl+Y** 組合鍵重做更改。此外,文字的常規鍵入和刪除操作會自動建立撤銷點,允許使用者逐步撤消更改。

結論

在 Tkinter Entry 元件中整合撤銷和重做功能需要自定義不同元件(例如 Text 元件)的行為,以模擬單行 Entry 元件的功能。透過遵循本文中概述的步驟,您可以在 Tkinter GUI 中實現撤銷和重做操作,使使用者能夠撤消和重做在文字輸入欄位中所做的更改。這增強了文字編輯體驗,併為使用者在使用您的應用程式時提供了更大的控制和靈活性。

更新於:2023年12月6日

820 次瀏覽

開啟您的 職業生涯

完成課程獲得認證

開始學習
廣告