繁体   English   中英

子类化 Tkinter.Text 以创建自定义小部件

[英]Subclassing Tkinter.Text to create a custom widget

我正在尝试创建一个带有垂直滚动条的文本小部件,同时保留Tkinter.Text所有方法/功能。

到目前为止,我有以下代码:

class ScrollableTextWidget(Tkinter.Text):
    def __init__(self, parent):
        self.parent = parent
        self.Frame = ttk.Frame(self.parent)
        Tkinter.Text.__init__(self, self.Frame, width=1, height=1)
        self.__initWidget()

    def __initWidget(self):
        self.Frame.grid(sticky="NSEW")
        self.ScrollbarY = ttk.Scrollbar(self.Frame, orient="vertical", 
                                        command=self.yview)
        self.configure(yscrollcommand=self.ScrollbarY.set)
        self.grid(column=0, row=0, sticky="NSEW")
        self.ScrollbarY.grid(column=1, row=0, sticky="NS")
        self.Frame.columnconfigure(0, weight=1)
        self.Frame.rowconfigure(0, weight=1)

像这样创建我的自定义小部件是否可以,或者我应该将它放在Tkinter.frame并编写我自己的方法?

将小部件子类化以创建自定义小部件是很正常的。 但是,如果此自定义小部件由多个小部件组成,您通常会将Frame子类化。 例如,要创建一个带有滚动条的文本小部件,我将执行以下操作:

import Tkinter as tk

class ScrolledText(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent)
        self.text = tk.Text(self, *args, **kwargs)
        self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)
        self.vsb.pack(side="right", fill="y")
        self.text.pack(side="left", fill="both", expand=True)

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.scrolled_text = ScrolledText(self)
        self.scrolled_text.pack(side="top", fill="both", expand=True)
        with open(__file__, "r") as f:
            self.scrolled_text.text.insert("1.0", f.read())

root = tk.Tk()
Example(root).pack(side="top", fill="both", expand=True)
root.mainloop()

使用这种方法,请注意在插入文本时需要如何引用内部文本小部件。 如果您希望这个小部件看起来更像一个真正的文本小部件,您可以创建一个到部分或全部文本小部件功能的映射。 例如:

import Tkinter as tk

class ScrolledText(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent)
        self.text = tk.Text(self, *args, **kwargs)
        self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)
        self.vsb.pack(side="right", fill="y")
        self.text.pack(side="left", fill="both", expand=True)

        # expose some text methods as methods on this object
        self.insert = self.text.insert
        self.delete = self.text.delete
        self.mark_set = self.text.mark_set
        self.get = self.text.get
        self.index = self.text.index
        self.search = self.text.search

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.scrolled_text = ScrolledText(self)
        self.scrolled_text.pack(side="top", fill="both", expand=True)
        with open(__file__, "r") as f:
            self.scrolled_text.insert("1.0", f.read())

root = tk.Tk()
Example(root).pack(side="top", fill="both", expand=True)
root.mainloop()

我会在未来的中型、大型项目或有支持的项目中使用子类,因为子类化可以很容易地替换或更新。 在任何情况下,子类化的成本都很小。 但是,如果您的任务是一次性的,那就做得又脏又快。

在这种情况下,我将从 Frame 继承子类,因为它是最通用的小部件,不需要覆盖packgrid和其他方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM