2013-09-30 12 views
6

zobacz następujący kod: (ja w zasadzie próbuje utworzyć widget tekstowy z pionowym pasku przewijania zachowując wszystkie metody/funkcji z Tkinter.Text w mojej klasie)Utworzenie podklasy Tkinter aby utworzyć niestandardowy Widget

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) 

Czy mogę utworzyć mój niestandardowy widget w ten sposób, czy raczej powinienem umieścić go w ramce i napisać własne metody?

Odpowiedz

2

Chciałbym użyć podklasy dla średniego, dużego projektu lub dla projektu z obsługą w przyszłości, ponieważ podklasy można łatwo wymienić lub zaktualizować. W każdym przypadku koszty podklasy są niewielkie. Ale jeśli twoje zadanie jest jednorazowe, rób to brudno i szybko.

W tym przypadku poddałbym podklasy z ramki, ponieważ jest to najbardziej ogólny widget i nie trzeba zastępować pack, grid i innych metod.

+0

Próbuję zadać to, czy jest to dobra praktyka, aby podklasy Tkinter.Text (lub dowolny inny widżet, aby zachować to metody i funkcje), aby utworzyć własny widget. W tym przypadku podklasuję Tkinter.Text, umieszczając go na pasku przewijania na ramce w mojej klasie. Czy powinienem podklasować klatkę i umieścić bezpośrednio na niej widżet tekstowy i pasek przewijania oraz tworzyć własne metody i funkcje? – user2830098

+0

Zobacz aktualizację mojej odpowiedzi –

16

Podklas widgetu jest bardzo normalny, aby utworzyć niestandardowy. Jeśli jednak ten niestandardowy widget składa się z więcej niż jednego widżetu, zwykle należy podklasę Frame. Na przykład, aby utworzyć widget, który jest widget tekst z paska przewijania chciałbym zrobić coś takiego:

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() 

Dzięki takiemu podejściu, zauważyć, jak trzeba odwoływać wewnętrzną widget tekstowy podczas wstawiania tekstu. Jeśli chcesz, aby ten widget wyglądał bardziej jak prawdziwy widget tekstowy, możesz utworzyć mapowanie do niektórych lub wszystkich funkcji widżetu tekstowego. Na przykład:

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() 
+0

Dziękuję, to było naprawdę pomocne. Próbowałem głosować/przyjąć twoją odpowiedź, ale niestety moja reputacja jest zbyt niska. Inną rzeczą jest to, w jaki sposób chciałbym utworzyć widok ttk.Treeview w ten sam sposób i być w stanie powiązać zdarzenie z nim ?, Czy powinienem wystawiać i używać instancji treeview w ramce? – user2830098

+1

Problem z rozwiązaniem polega właśnie na tym, że musisz ręcznie ujawniać metody składające się z elementów tekstowych, a OP ma nadzieję uzyskać to za darmo. W związku z tym domyślam się, że jego pierwotny pomysł na podklasowanie tekstu był właściwą drogą. Opracowanie mojego Tkintera jest zbyt płytkie, aby odpowiedzieć na to pytanie, ale byłbym zadowolony, gdyby ktoś mógł to zrobić. – quickbug

Powiązane problemy