Dictionary, Button disabled wenn toplevel aktiv

Fragen zu Tkinter.
Antworten
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo,

hilfe, ich komme einfach nicht weiter.

Es soll nach betätigen von Buttons ein Toplevel-Fenster aktiviert und dann selbige Buttons deaktiviert werden.

Das Problem ist, das die Werte mehrfach aus einem Dictionary kommen und ich somit bei der u.a. Lösung nur einen Button deaktiviere.

Ich habe schon alles mögliche probiert und keine wirklich zufriedenstellende
Lösung gefunden.

Der Übersichtlichkeit halber habe ich hier ein Beispielcode:

Code: Alles auswählen

import Tkinter as tk

root = tk.Tk()

class Test(object):
    def __init__(self, alpha, beta):
        self.alpha = alpha
        self.beta = beta

    def toplevel(self):
        a.but.config(state = 'disabled')
        tk.Toplevel()

beispiel = {'eins' : Test(1, 1), 
                    'zwei' : Test(2, 2),  
                        'drei' : Test(3, 3)}

class Action(object):
    def button(self):
        for value in beispiel.values():
            self.but = tk.Button(text = ' - test - ', command = value.toplevel)
            self.but.grid()
            
a = Action()
a.button()

root.mainloop()
Hat jemand eine Idee?

Grüße

rai
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Deine Klassenauteilung ist total vermurkst. Erstmal machen die globalen Variablen den Code schwer zu lesen. Dann definierst du die Klasse Action, die auf Test-Instanzen und deren toplevel-Methode zugreift, aber die toplevel-Methode greift wieder auf eine Instanz der Klasse Action (naemlich a) zu...

Ausserdem ist ein Dictionary vlt. nicht die richtige Wahl, da ha hier die Reihenfolge verloren geht, deine Buttons also wild durcheinander auftauchen koennen.

Der konkrete Fehler liegt einfach darin, dass das Attribut but in der Klasse Action natuerlich genau den letzen Button enthaelt, da du in der for-Schleife dieses Attribut bei jedem Durchgang ueberschreibst, und genau diesen Button deaktivierst du dann in Zeile 11.

Hier ein Versuch, etwas Ordnung in die Sache zu bringen, haengt natuerlich auch davon ab, was genau du machen willst:

Code: Alles auswählen

import Tkinter as tk

class Test(object):
    def __init__(self, alpha, beta):
        self.alpha = alpha
        self.beta = beta
        self.button = tk.Button(text = ' - test - ', command = self.toplevel)
        self.button.grid()

    def toplevel(self):
        self.button.config(state = 'disabled')
        tk.Toplevel()


root = tk.Tk()
beispiel = (Test(1, 1), Test(2, 2), Test(3, 3))
root.mainloop()
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo Rebecca,

danke für die schnelle Antwort.

ich muss jetzt erstmal zur Arbeit. Ich schau es mir heute Abend an und meld mich wieder.

Grüße

rai
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo,

@ Rebecca :
Hm, es ist immer noch so, das nur ein Button ausgeht! Diesmal allerdings der obere! :D
Oder war der Vorschlag nur auf die vermurkste Klassenaufteilung bezogen?

Ich brauche auch die Key/Value Zuordnung.

Vielleicht gibt es doch eine Lösung.

Grüße

rai
schlangenbeschwörer
User
Beiträge: 419
Registriert: Sonntag 3. September 2006, 15:11
Wohnort: in den weiten von NRW
Kontaktdaten:

Was genau hast du gehegen, was genau willst du erreichen und was sind deine Überlegungen, die man austauschen kann?
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo,

ich setz einfach mal den code rein.

@ schlangenbeschwörer:
Ich hänge immer noch hartnäckig an meiner Bankkonto-Übung.
-----
Bevor ich weiter an dem Program arbeite, möchte ich, dass wenn die 'action-Buttons' angeklickt werden und sich das Toplevel-Fenster für weitere Eingaben öffnet, die Buttons deaktiviert sind.

Ich habe schon über mehrere Tage alles mögliche ausprobiert. Vielleicht ist der ganze Ansatz auch komplett daneben.
Ich weiß es nicht!

Grüße

Rai

Code: Alles auswählen

# bis Zeile-13 von: http://www.wspiegel.de/pykurs/kurs_index.htm
import Tkinter as tk

root = tk.Tk()

class Bankkonto(object):
    def __init__(self, startbetrag, kontonr):
        self.stand = float (startbetrag)
        self.kontonr = kontonr

    def einzahlung(self, betrag):
        self.stand = self.stand + betrag
       
    def auszahlung(self, betrag):
        self.stand = self.stand - betrag
        
    def ueberweisung(self, betrag, konto):
        self.auszahlung (betrag)
        konto.einzahlung (betrag)

    def transfer(self):   
        self.tk1 = tk.Toplevel()
        tk.Label (self.tk1, fg='blue', text="Konto Nr. " + str (self.kontonr) ).grid()
        
        tk.Label (self.tk1, text = "Einzahlung").grid()
        self.e = tk.Entry(self.tk1, bg="white")
        self.e.grid()
        #frm.frame.destroy()
        def einz():
            self.einzahlung (float(self.e.get()))
            frm.de_stroy()
            self.tk1.destroy()
        tk.Button (self.tk1, text = "OK", command = einz).grid()
       
        tk.Label(self.tk1, text = "Auszahlung").grid()
        self.e1 = tk.Entry(self.tk1, bg = "white")
        self.e1.grid()
        def ausz():
            self.auszahlung (float(self.e1.get()))
            frm.de_stroy()
            self.tk1.destroy()
        tk.Button (self.tk1, text = "OK", command = ausz).grid()
       
        tk.Label (self.tk1, text = "Ueberweisung").grid()
        self.e2=tk.Entry (self.tk1, bg = "white")
        self.e2.grid()
        tk.Label (self.tk1,  text = "auf Konto").grid()
        self.e3=tk.Entry (self.tk1, bg = "white")
        self.e3.grid()
        def ueberw():
            self.ueberweisung (float (self.e2.get()), konten.get(self.e3.get()))
            frm.de_stroy()
            self.tk1.destroy()
        tk.Button (self.tk1, text = "OK", command = ueberw).grid()

konten =   {'11': Bankkonto (1148.12, 11), 
                    '22': Bankkonto (217.98, 22), 
                        '33': Bankkonto (-99.28, 33)}
for value in konten.values():
    b = Bankkonto(value.stand, value.kontonr)

class Frames(Bankkonto):
    def fra_me(self, event = None):
        self.frame = tk.Frame()
        self.frame.grid()
        self.text = tk.Text(self.frame, width = 60, height = 1)
        self.text.grid()
        self.text.insert(tk.END, "%26s%24s" % ("Konto","Saldo"))
        self.text.config(state = 'disabled')
    
        for key, value in konten.items():  
            self.text2 = tk.Text(self.frame, width = 60, height = 2)
            self.text2.grid()
            if event:
                self.but.config(state = 'disabled')
            self.but = tk.Button (self.text2, text = "action", width = 5, fg = 'blue', command = value.transfer)
            #self.tk1.bind('<FocusIn>', frm.fra_me)
            self.text2.window_create(tk.END, window = self.but)
            self.text2.insert(tk.END, "%15d" % (value.kontonr))
                        #self.but.config(state = 'disabled')
    
            if value.stand >=0:
                self.text2.insert(tk.END, "%25.2f" % (value.stand) +"   H")
            
            else:
                self.text2.insert(tk.END, "%25.2f" % abs(value.stand) +"   S")
                self.text2.tag_add('one', '1.20', '1.45')
                self.text2.tag_configure('one', foreground="red")
    
        self.text2.config(state = 'disabled')
    
    def de_stroy(self):
        self.frame.destroy(),  
        frm.fra_me(), 
               
frm = Frames(value.stand, value.kontonr)
frm.fra_me()
root.mainloop()
BlackJack

Im Bankkonto sollte kein GUI-Code sein.

`Frames` sollte einen passenderen Namen bekommen. Und eine `__init__()`-Methode haben, die im Grunde die Aufgaben der `fra_me()`-Methode hat. Womit ich bei der Frage wäre: was sollen die scheinbar zufällig gesetzten Unterstriche in den Namen `fra_me` und `de_stroy`?

Was sollen die Kommata in `de_stroy()`? Und die Methode sollte weder über den Namen `frm` auf *sich selbst* zugreifen, noch auf diese Weise sich rekursiv neu starten.

Die Buttons solltest Du nicht einzeln deaktivieren, sondern wenn das Toplevel angezeigt wird, mit `grab_set()` und `wait_window()` einen modalen Dialog aus dem Toplevel machen. Das wird zum Beispiel hier beschrieben: http://www.pythonware.com/library/tkint ... indows.htm
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo,

Sorry! Ich hab ausversehen den falschen Code reingesetzt. :oops:

Da sind viele Sachen drin, die da nicht stehen sollten!
z.B. die Kommata in 'de_stroy', Argumente in den Instanzen der Klassen u.s.w.

@ Black Jack
Die Unterstriche in den Namen habe ich nur der Übersichlichkeit halber gesetzt.
Die Klassenbezeichnung war mir erstmal nicht so wichtig. Wahrscheinlich ist es aber besser, das sofort zu ändern und nicht erst im Nachhinein.

Ich werde jetzt erstmal versuchen, den Gui-Code vom Bankkonto zu trennen und die weiteren Anregungen umzusetzen.

Danke für die Vorschläge! Meld mich wieder.

Grüße

Rai
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

raibel hat geschrieben:Hm, es ist immer noch so, das nur ein Button ausgeht! Diesmal allerdings der obere! :D
Bei mir geht es. Hab extra nochmal den Code von oben kopiert.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo Rebecca,
Bei mir geht es. Hab extra nochmal den Code von oben kopiert.
Ich habe das gestern bei der Arbeit auf einem XP-Rechner laufen lassen, dann Zuhause mit Linux +Eric4 und jetzt nochmal in der Konsole.

Es geht immer nur 1x Button aus!
--
Aber Danke für den geänderten Testcode. Jetzt weiß ich, das ich das Dictionary nicht nur über die for-Anweisung, sondern auch über den Konstruktor auslesen kann.

@ Black Jack:
Im Bankkonto sollte kein GUI-Code sein.
Wenn ich das trenne und aus der Methode 'transfer' eine Klasse mache, wie komme ich dann an die Konstruktordefinitionen der Klasse 'Bankkonto'?
Die Instanz der Klasse 'Bankkonto' ist ja in dem Fall ein Dictionary.

Grüße

Rai
BlackJack

Wieso sollte man aus der Methode `transfer()` eine Klasse machen? Was meinst Du mit Konstruktordefinition? Und eine Instanz von `Bankkonto` ist kein Dictionary, jedenfalls nicht solange `Bankkonto` nicht von `dict` erbt.

Ich steige durch den Quelltext ehrlich gesagt nicht so ganz durch. In `transfer()` wird bei Überweisungen auch wieder über das globale `frm` irgendein Frame `de_stroy()`\t. Lass am besten erst einmal sämtlichen Code auf Modulebene in einer `main()`-Funktion verschwinden. Dann kommt man gar nicht erst in Versuchung so etwas zu machen.
raibel
User
Beiträge: 30
Registriert: Mittwoch 15. November 2006, 22:03

Hallo,

ich glaube, ich bin jetzt einfach mal überfordert. :?

Im Moment ist es so, das eure Antworten bei mir als Anfänger nur neue Fragen aufwerfen.
Ich werd mich jetzt zurücklehnen, in Ruhe eure bisherigen Antworten anschauen und Grundlagen -und Begriffsforschung betreiben.

Aber - ich melde mich wieder! :)

Grüße

Rai
Antworten