2017-07-13 5 views
1

Ich habe eine tkinter-basierte GUI mit vielen Instanzen einer Klasse in einer ttk.LabelFrame gruppiert. Die Klasse erbt von ttk.Frame und wird unter Verwendung von .grid() in LabelFrame platziert. Die LabelFrame enthält auch ttk.Labels.Wie kann ich eine Methode für jede Instanz einer einzelnen Klasse verwenden?

Bitte sehen Sie diese sehr vereinfachtes Beispiel:

import tkinter as tk 
from tkinter import ttk 

class MyClass(tk.Frame): 
    def __init__(self, parent): 
     super().__init__(parent) 
    def MyMethod(self): 
     print(tk.Widget.winfo_name(self)) 

root = tk.Tk() 
frame = ttk.LabelFrame(root, text="frame") 
label = ttk.Label(frame, text="label") 
class1 = MyClass(frame) 
class2 = MyClass(frame) 

print("class.MyMethod() calls:") 
class1.MyMethod() 
class2.MyMethod() 

print("\ntkinter.Widget.nwinfo_children(frame):") 
childlist = tk.Widget.winfo_children(frame) 
print(childlist) 

Die Ausgabe sieht wie folgt aus:

class.MyMethod() calls: 
49250736 
49252752 

tkinter.Widget.nwinfo_children(frame): 
[<tkinter.ttk.Label object .49250672.49252880>, 
<__main__.MyClass object .49250672.49250736>, 
<__main__.MyClass object .49250672.49252752>] 

Ich will es so etwas wie:

for child in childlist: 
    child.MyMethod() 

Was nicht tut Arbeit wegen der Etiketten. Oder vielleicht:

for child in childlist: 
    {if this is a MyClass instance}: 
     child.MyMethod() 

Aber ich weiß nicht, ob das in die richtige Richtung geht.

Gibt es einen sauberen Weg zu tun, was ich will?

+2

es ist keine Antwort wert 'ifinstance (Kind, MyClass):' ist, was Sie wollen, ich denke –

+0

eine Alternative wäre 'getattr (Kind," MyMethod ", Lambda: 1)()' das könnte tatsächlich besser sein –

+0

FWIW du kannst 'self.winfo_name()' anstelle von 'tk.Widget.winfo_name (self)' –

Antwort

2

Hier @Joran Beasley Kommentar, prall-out:

import tkinter as tk 
from tkinter import ttk 

class MyClass(tk.Frame): 
    def __init__(self, parent): 
     super().__init__(parent) 
    def MyMethod(self): 
     print(self.winfo_name()) 

root = tk.Tk() 
frame = ttk.LabelFrame(root, text="frame") 
label = ttk.Label(frame, text="label") 
class1 = MyClass(frame) 
class2 = MyClass(frame) 

print("class.MyMethod() calls:") 
class1.MyMethod() 
class2.MyMethod() 

print("\ntkinter.Widget.nwinfo_children(frame):") 
childlist = tk.Widget.winfo_children(frame) 
print(childlist) 

for child in childlist: 
    if isinstance(child, MyClass): 
     child.MyMethod() 

Ausgang:

class.MyMethod() calls: 
!myclass 
!myclass2 

tkinter.Widget.nwinfo_children(frame): 
[<tkinter.ttk.Label object .!labelframe.!label>, <__main__.MyClass object .!labelframe.!myclass>, <__main__.MyClass object .!labelframe.!myclass2>] 
!myclass 
!myclass2 

Oder vielleicht ein wenig kurz und bündig:

my_class_children = [child for child in tk.Widget.winfo_children(frame) 
         if isinstance(child, MyClass)] 
print(my_class_children) 
for child in my_class_children: 
    child.MyMethod() 

Ausgang:

[<__main__.MyClass object .!labelframe.!myclass>, <__main__.MyClass object .!labelframe.!myclass2>] 
!myclass 
!myclass2 
+1

Danke, dass du das geschrieben und ausgearbeitet hast. Ihr "prägnantes" Beispiel dient mir sehr gut. :) – bitsmack

+0

bitsmack: Freut mich zu hören, dass es geholfen hat. Beachten Sie auch, dass die Dinge durch die Verwendung von 'all (child.MyMethod() ist None für child in my_class_children)' noch etwas knapper sein kann, obwohl es leicht irreführend ist, da der Rückgabewert von 'all()' ignoriert wird. – martineau

Verwandte Themen