2016-12-20 3 views
0

Ich arbeite immer noch mit den gestapelten Frames, die für eine Tkinter-App eingerichtet wurden, und ziemlich neu für OOP und Tkinter. Ich habe den folgenden Code von einer anderen SO-Frage kopiert und leicht abgeändert. Was ich nicht bekomme: Ich möchte das Label2 auf der StartPage basierend auf dem Klick auf Button2 auf PageTwo von "Hallo" auf "5" aktualisieren. Aber das Update findet nicht statt. Was muss ich anders machen, um meine Aufgabe zu erfüllen? Vielen Dank im VorausTkinter aktualisiert Etiketten in gestapelten Rahmenfenstern

import tkinter as tk 

TITLE_FONT = ("Helvetica", 18, "bold") 

class SampleApp(tk.Tk): 

    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 
     self.var = tk.StringVar() 
     self.var.set('Hello') 
     container = tk.Frame(self) 
     container.pack(side="top", fill="both", expand=True) 
     container.grid_rowconfigure(0, weight=1) 
     container.grid_columnconfigure(0, weight=1) 

     self.frames = {} 
     for F in (StartPage, PageTwo): 
      page_name = F.__name__ 
      frame = F(parent=container, controller=self) 
      self.frames[page_name] = frame 
      frame.grid(row=0, column=0, sticky="nsew") 

     self.show_frame("StartPage") 

    def show_frame(self, page_name):  
     frame = self.frames[page_name] 
     frame.tkraise() 


class StartPage(tk.Frame): 

    def __init__(self, parent, controller): 
     tk.Frame.__init__(self, parent) 
     self.controller = controller 
     label = tk.Label(self, text="This is the start page", font=TITLE_FONT) 
     label.pack(side="top", fill="x", pady=10) 

     label2 = tk.Label(self, textvariable=self.controller.var, font=TITLE_FONT) 
     label2.pack(side="top", fill="x", pady=10) 
     label2.config(text=self.controller.var) 

     button2 = tk.Button(self, text="Go to Page Two", 
          command=lambda: controller.show_frame("PageTwo")) 
     button2.pack() 

class PageTwo(tk.Frame): 

    def __init__(self, parent, controller): 
     tk.Frame.__init__(self, parent) 
     self.controller = controller 
     label = tk.Label(self, text="This is page 2", font=TITLE_FONT) 
     label.pack(side="top", fill="x", pady=10) 
     button = tk.Button(self, text="Go to the start page", 
          command=lambda: controller.show_frame("StartPage")) 
     button.pack() 
     button2 = tk.Button(self, text="Change X", 
          command=lambda: self.calculate()) 
     button2.pack() 

    def calculate(self): 
     self.controller.var = 5 
     return self.controller.var 

if __name__ == "__main__": 
    app = SampleApp() 
    app.mainloop() 

Antwort

1

Es gibt viele Möglichkeiten zu erreichen, was Sie wollen. Da Sie ein StringVar für das Label verwenden Sie ändern möchten, ist die einfachste Lösung, die Variable mit dem neuen Wert zu aktualisieren:

def calculate(self): 
    self.controller.var.set(5) 

Diese Lösung eng Paare die Steuerung und die andere Klasse. Das heißt, Ihr PageTwo muss wissen, dass der Controller ein mit diesem Label assoziiert. Wenn Sie den Controller ändern, um einen anderen Mechanismus zu verwenden, müssen Sie jede andere Klasse ändern, die versucht, diese Variable festzulegen.

Eine Möglichkeit, lose Kopplung bereitzustellen, ist die Bereitstellung einer API zur Änderung des Werts durch den Controller. In gewissem Sinne gibt es deshalb Controller - Steuerelement den Informationsfluss zwischen den Seiten. Die Details, wie genau dieser Wert gespeichert und angezeigt wird, sind vor den anderen Klassen verborgen.

Zum Beispiel:

class SampleApp(...): 
    ... 
    def set_label(self, value): 
     self.var.set(value) 

class PageTwo(...): 
    ... 
    def calculate(self): 
     self.controller.set_label(5) 

Der Vorteil der obigen ist, dass es lose Kopplung zwischen den beiden Klassen bietet. Die anderen Seiten müssen nicht wissen, dass das Etikett mit einem StringVar oder einem Label Widget implementiert ist. Der Controller stellt einfach eine Schnittstelle bereit, die besagt: "Wenn Sie die Variable X ändern müssen, rufen Sie diese Funktion auf". Solange der Controller diese Funktion beibehält, können Sie die Implementierung ändern, ohne jede andere Klasse ändern zu müssen, die diese Bezeichnung möglicherweise ändern muss.

Siehe What is the difference between loose coupling and tight coupling in the object oriented paradigm? für weitere Informationen über den Unterschied zwischen loser Kopplung und enge Kopplung.

+0

vielen dank @Bryan Oakley, da Sie es erwähnen, was wäre Ihre bevorzugte Art, es zu tun? Ihr Vorschlag funktioniert für ein einfaches Label-Update. In Wirklichkeit kommen die aktualisierten Werte über ein Tupel verschiedener Wörter, die in verschiedene Etiketten aufgeteilt werden müssen. Die StringVar() Lösung, die ich versuchte, scheint nicht die effizienteste Lösung dafür zu sein. –

+0

Ich kann nicht antworten, was mein bevorzugter Weg ist. Es hängt von Ihren tatsächlichen Daten ab und was Sie tatsächlich erreichen wollen. Was ich mit einem kleinen Demo-Programm machen würde, ist ganz anders als das, was ich mit einer echten Anwendung machen würde. –

+0

Ich habe versucht, es mit einer globalen Variablen zu tun, bin aber steckengeblieben, weil die Seitenklassen statisch sind und die globalen Variablenwerte nicht übernehmen. Zumindest habe ich noch nicht herausgefunden, wie man sie dazu bringt, die Werte hoch zu wählen. –

Verwandte Themen