【问题标题】:Python Tkinter listbox text edit in GUIGUI中的Python Tkinter列表框文本编辑
【发布时间】:2021-02-12 23:47:44
【问题描述】:

有没有办法编辑列表框项而不是删除它?

我正在使用带有列表框的 tkinter GUI。现在我的列表框可以包含例如 10 个项目。如果我想更改一个项目的文本,有没有办法做到这一点?

我知道我可以创建一个按钮来删除单个项目,但是有没有办法同时编辑一个项目?

【问题讨论】:

  • 您是在问用户如何在列表框中键入内容,还是只是希望您的代码能够在中间插入或替换某些内容?插入和删除的方法都有记录。
  • 我想让用户编辑一个已经添加的项目(在 GUI 中而不是在代码中)因此我希望有一些东西可以用来创建一个函数,我可以链接到例如,一个编辑按钮左右。
  • 但是您是希望他们通过在列表框中输入来更改它,还是计划在列表框之外有一个他们可以输入的条目小部件?
  • 好的,如果他们喜欢双击(或覆盖)列表框中的条目并在那里进行编辑,那最好。希望避免向 GUI 添加更多输入字段。能够编辑列表中的项目而不是删除并重新添加应该只是 QoL 功能。
  • 无论如何,你无法避免删除它并重新添加

标签: python user-interface button tkinter listbox


【解决方案1】:

列表框不支持直接编辑列表框内的项目。您必须为用户提供一种输入数据的机制,然后您可以只替换列表框中的单个项目。

话虽如此,tkinter 为您提供了让用户双击项目并进行更改所需的所有工具。这是一个示例的快速破解。简而言之,当您双击时,它会在您单击的项目上叠加一个条目小部件,当您按下回车键时,它会将项目保存到列表框。

import tkinter as tk

class EditableListbox(tk.Listbox):
    """A listbox where you can directly edit an item via double-click"""
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        self.edit_item = None
        self.bind("<Double-1>", self._start_edit)

    def _start_edit(self, event):
        index = self.index(f"@{event.x},{event.y}")
        self.start_edit(index)
        return "break"

    def start_edit(self, index):
        self.edit_item = index
        text = self.get(index)
        y0 = self.bbox(index)[1]
        entry = tk.Entry(self, borderwidth=0, highlightthickness=1)
        entry.bind("<Return>", self.accept_edit)
        entry.bind("<Escape>", self.cancel_edit)

        entry.insert(0, text)
        entry.selection_from(0)
        entry.selection_to("end")
        entry.place(relx=0, y=y0, relwidth=1, width=-1)
        entry.focus_set()
        entry.grab_set()

    def cancel_edit(self, event):
        event.widget.destroy()

    def accept_edit(self, event):
        new_data = event.widget.get()
        self.delete(self.edit_item)
        self.insert(self.edit_item, new_data)
        event.widget.destroy()

root = tk.Tk()
lb = EditableListbox(root)
vsb = tk.Scrollbar(root, command=lb.yview)
lb.configure(yscrollcommand=vsb.set)

vsb.pack(side="right", fill="y")
lb.pack(side="left", fill="both", expand=True)

for i in range(100):
    lb.insert("end", f"Item #{i+1}")

root.mainloop()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多