Fenster vom Fenster: StringVar-Labels werden nicht angezeigt

Fragen zu Tkinter.
Antworten
fatrat
User
Beiträge: 8
Registriert: Mittwoch 3. Dezember 2008, 11:03

Schönen Gruß,

ich habe eine Oberfläche, von der ich eine weitere Oberfläche mit Hilfe eines Buttons starte. Im zweiten Fenster möchte ich verschiedene Auswertungen darstellen. Komischerweise werden nur "normale" Labels, nicht aber die StringVar-Labels angezeigt. Starte ich das Fenster direkt geht es.

Noch etwas: wie kann ich verhindern, dass bei neuerlichem "Klick" eine weitere Instanz des Fensters aufgeht, wenn eine erste schon da ist?

Für einen Hinweis wär ich dankbar. Hier der Code:

Code: Alles auswählen

from Tkinter import *

class Eins(object):
    def __init__(self):
        self.fenster = Tk()
        self.button=Button(self.fenster,text="Klick",command=self.klick)
        self.button.pack()
        self.fenster.mainloop()

    def klick(self):
        a=Statistik()

class Statistik(object):
    def __init__(self):

        self.fenster = Tk()
        
        self.frame_info = Frame(self.fenster,relief=RIDGE,bd=2)
        self.frame_info.grid(column=0,row=1,padx=5,pady=5)
        
        self.frame_stat = Frame(self.frame_info,relief=RIDGE,bd=2)
        self.frame_stat.grid(column=0,row=0,padx=5,pady=5)
        
        self.label_tti = Label(self.frame_stat,text="Gesamt: ")
        self.label_tti.grid(column=0,row=0,padx=5,pady=5)
        self.cvar_tt = StringVar()
        self.cvar_tt.set("##")
        self.label_tt = Label(self.frame_stat,textvariable=self.cvar_tt)
        self.label_tt.grid(column=1,row=0,padx=5,pady=5)

        self.label_wini = Label(self.frame_stat,text="Gewinner: ")
        self.label_wini.grid(column=0,row=1,padx=5,pady=5)
        self.cvar_win = StringVar()
        self.cvar_win.set("##")
        self.label_win = Label(self.frame_stat,textvariable=self.cvar_win)
        self.label_win.grid(column=1,row=1,padx=5,pady=5)
        
        self.fenster.mainloop()


e=Eins()
s=Statistik()

yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Hallo fatrat,
beim Ausführen Deines Programmes werden
gleich 2 Tk() Instanzen mit 2 Mainloops erzeugt.
Das kann nur zu Kuddelmuddel führen.
(Lohnt sich gar nicht, im Kopf durchzutracen, was da
im einzelnen passiert.)

Soll nur 1 Instanz des 2. Fensters erzeugt werden,
so lässt sich das mit einer Schaltervariablen
(bei mir 'self.only_one') überprüfen.

Hier die berichtigte Version:
http://paste.pocoo.org/show/109329/

:wink:
yipyip
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Hallo fatrat,
was Du brauchst ist:
1 Root-Window + 1 Toplevel-Window + 1 Mainloop

Du erzeugst aber mit Zeile 41:
1 Root-Window + 1 Mainloop + (1 Root-Window + 1 Mainloop) * #Klicks

Ist diese Zeile abgearbeitet werden danach nochmals in Zeile 42
1 Root-Window + 1 Mainloop
erzeugt.

(Wollte meine obige Ausführung nur etwas verbessern und
ergänzen.)

:wink:
yipyip
fatrat
User
Beiträge: 8
Registriert: Mittwoch 3. Dezember 2008, 11:03

Lieber yipyip,

vielen Dank für Deine klasse Hilfe. Du verwendest in Deinem Code ein paar Konzepte, die mir so noch nicht geläufig sind. Daher hätte ich ein paar Nachfragen, damit ich verstehe, was da vor sich geht.

- was genau tut die Lambda-Form; sie ruft das Kommando "self.klick" auf, übergibt den Parameter "parent", der auf "self" zeigt, oder? Ist "parent" ein feststehender Begriff in Python oder in dem Fall einfach ein neues Objekt bzw. eine Variable?
- warum benötigt man eine "run"-Funktion in der Klasse Eins? Ich instanziere die Objekte immer mit irgendeinem Namen bislang
- warum importierst du Tkinger als "tk" - hat das einen bestimmten Grund? Ich importiere bislang immer mit "from xx import *"
- was ist "Toplevel"? (hat sich geklärt, hab nachgesehen, schön, dass es das gibt).
- die if-Abfrage am Ende verstehe ich leider überhaupt nicht.

Du musst nicht ausführlich antworten; ein paar Hinweise oder Links reichen. Nochmal Danke für Deine Mühe!

fatrat
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Ich fange mal von hinten an:

http://diveintopython.org/getting_to_kn ... dules.html
http://effbot.org/pyfaq/tutor-what-is-i ... in-for.htm

Dort u.a. kannst Du etwas über den sogenannten 'if-Trick'
erfahren. (Sonst weitergoogeln...)

"import Tkinter as tk"

ist (hier) mittlerweile Konvention, damit der
Tkinter-Namensraum von den anderen (eigenen) auseinandergehalten werden kann.
(Gibt hier auch genügend Postings dazu.)

Die run()-Methode dient einfach nur dazu, den
mainloop()-Aufruf zu kapseln, das erweist sich bei
umfangreicheren Programmen, die z.B. nach dem Model-View-Controller Prinzip organisiert sind, als sinnvoll.
(siehe auch: http://www.python-forum.de/post-113896.html#113896)

Ich hätte auch einfach:

Code: Alles auswählen

self.button = tk.Button(self.fenster,text="Klick",  command=lambda : self.klick(self))
schreiben können, dachte nur das andere wäre verständlicher.
'parent' ist ein beliebiger Variablenname, es hätte auch
'mirfaelltgradnixein' heissen können.

Die command-Option erwartet etwas, das aufgerufen werden kann
(eine Funktion oder Methode, in diesem Fall das 'lambda', das dann bei 'Klick' die __init__() Methode von 'Statistik' aufruft).

Eine Instanz von 'Statistik' erhält somit eine Instanz von der sie aufrufenden 'Eins', weil bestimmte Informationen weitergegeben werden sollen.

(Ich belasse es erstmal hierbei...)

:wink:
yipyip
Antworten