AttributeError bei Button config Änderung in try Verzweigung

Fragen zu Tkinter.
Antworten
rfe
User
Beiträge: 6
Registriert: Dienstag 9. Januar 2018, 06:52

Hallo Zusammen,
ich bin ziemlich neu in der Python Community und habe folgendes Problem:
Ich habe eine Tkinter Applikation geschrieben und soweit funktioniert diese. Jetzt möchte ich aber die Werte in den
Eingabefeldern auf Plausibilität prüfen und den "Start" Button erst aktiv setzen wenn alle Werte plausibel sind.

Dazu habe ich mit einer try/except Verzweigung gearbeitet und bei einfachen print ausgaben funktioniert diese auch.
Will ich jetzt aber in der try Verzweigung die Button Konfiguration ändern bekomme ich einen AttributeError: object has no attribute 'buttonStart'
in der except Verzweigung funktioniert dies aber problemlos.

Versteh das nicht ganz und wäre sehr froh wenn mir von euch jemand weiterhelfen könnte.

Danke!

Code: Alles auswählen

   

def cmdSetMaxImages(self, *args):       # max time changed     
        try:
            self.tempMaxImages = self.varMaxImages.get()
            self.controller.setMaxImages(self.tempMaxImages)
            self.checkMaxImg = 1
            #self.checkStartEnable()
            print("good value")
        except tk.TclError:
            self.checkMaxImg = 0
            self.checkStartEnable()
            print("bad value")

    def checkStartEnable(self):
        if  self.checkMaxImg == 1:
            self.button.config(relief = tk.RAISED)
            self.button.config(state = tk.ACTIVE)  
        else:
            self.buttonStart.config(relief = tk.SUNKEN)
            self.buttonStart.config(state = tk.DISABLED)  
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@rfe: Du benutzt einmal `buttonStart` und einmal `button` aber die Fehlermeldung ist gerade umgekehrt zu dem, was du behauptest. Zum Code: laut Konvention werden Variablen, Attribute und Funktionen klein_mit_unterstrich geschrieben. Ein Attribut `tempMaxImages` (ist das die Maximaltemperatur der Bilder?) macht keinen Sinn. Man muß nicht alles an Attribute binden, hier würde ich sogar gar keine eigene Variable nehmen und den Wert gleich direkt an die Funktion setMaxImages übergeben. Ebenso `checkMaxImg` wäre wohl besser ein Parameter der Funktion `checkStartEnable`, die wohl besser `enable_button_startcheck` hieße. Statt 1 und 0 benutzt man True und False. Hier wäre der Aufruf von checkStartEnable besser nach dem try-except-Block.

Code: Alles auswählen

    def cmdSetMaxImages(self, *args):       # max time changed    
        try:
            max_images = self.varMaxImages.get()
            self.controller.setMaxImages(max_images)
            enabled = True
            print("good value")
        except tk.TclError:
            enabled = False
            print("bad value")
        self.checkStartEnable(enabled)
 
    def enable_button_startcheck(self, enabled):
        if enabled:
            attributes = {"relief": tk.RAISED, "state": tk.ACTIVE}
        else:
            attributes = {"relief": tk.SUNKEN, "state": tk.DISABLED}
        self.button.config(**attributes)
rfe
User
Beiträge: 6
Registriert: Dienstag 9. Januar 2018, 06:52

Hallo Sirius3,
danke für deine schnelle Antwort!

sorry beim button bzw. buttonStart hab ich mich vertippt, soll natürlich beides buttonStart heißen.
das temp... soll für temporär stehen, die variable benutze ich nur um den wert aus der tk.IntVar zu lesen.
Gibt es bzgl. Notation irgendwelche Richtlinien oder sind das wie beschrieben Konventionen der Python Programmierer?
Die eigene Variable habe ich verwendet, weil noch mehrere hinzukommen, der buttonStart darf dann nur aktiv sein wenn alle Eingaben korrekt sind.

aber das beste an allem, wenn ich die checkStartEnable Methode nach dem try/except block aufrufe klappts. Gib es einen bestimmten Grund, warum dies innerhalb der try Verzweigung nicht klappt?

Danke!
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@rfe: nein, denn das kann nicht sein. Zeig doch den kompletten Traceback. Eine temporäre Variable wird nicht als Attribut geschrieben und alle lokalen Variablen sind temporär, so dass ein Präfix temp unsinnig ist.
rfe
User
Beiträge: 6
Registriert: Dienstag 9. Januar 2018, 06:52

Eben das verwirrt mich auch! buttonStart ist as tk.Button definiert.

Traceback ist folgender:

Exception in Tkinter callback
Traceback (most recent call last):
File "/Users/rfe/anaconda/lib/python3.5/tkinter/__init__.py", line 1559, in __call__
return self.func(*args)
File "/Users/rfe/Documents/002_Ausarbeitung/005_Software/src/view/sidepanel.py", line 230, in cmdSetMaxImages
self.checkStartEnable()
File "/Users/rfe/Documents/002_Ausarbeitung/005_Software/src/view/sidepanel.py", line 245, in checkStartEnable
self.buttonStart.config(relief = tk.RAISED)
AttributeError: 'sidepanel' object has no attribute 'buttonStart'
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da dieser Traceback zu nichts passt, was du zeigst, wirst du nicht umhinkommen, uns den ganzen Code zu zeigen. So kann man nur sagen du hast den Button halt nicht da eingehangen, wo du glaubst ihn eingehangen zu haben.
rfe
User
Beiträge: 6
Registriert: Dienstag 9. Januar 2018, 06:52

Den buttonStart habe ich im Konstruktor definiert:

self.buttonStart = tk.Button(self.frame, test = "START", borderwidth = 2, relief = tk.RAISED, command = self.cmdSetStart)
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Punkt ist, das das self (also das Objekt) das du befragst nicht das ist, an das du dein Attribut gebunden hast. Das ist die glasklare Aussage des Fehlers. Aber WARUM es so ist, kann man ohne Code nicht verstehen.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@rfe: nochmal zur Namenskonvention: Klassen schreibt man mit GrossBuchstaben, also SidePanel. Konstruktoren werden in Python selten verwendet; hast Du also `buttonStart` im __init__ von `sidepanel` oder wo anders definiert?
rfe
User
Beiträge: 6
Registriert: Dienstag 9. Januar 2018, 06:52

Habs gefunden, danke für eure Hilfe,

habe im Konstruktor die Methode schon einmal aufgerufen und an dieser Stelle war der buttonStart noch nicht definiert!!

Vielen Dank!
rfe
User
Beiträge: 6
Registriert: Dienstag 9. Januar 2018, 06:52

ja, habe in der __init__ vom sidepanel den Button definiert.

gibt es irgend einen hilfreichen link oder ein Dokument zur Namenskonvention?
Antworten