Bilderwechsel

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
valentinks
User
Beiträge: 20
Registriert: Sonntag 27. Juni 2021, 10:31
Wohnort: Kassel

Hallo Zusammen,
ja das Thema gab's schonmal, meine Frage ist aber anders.

Der Gedanke:
Ich will erreichen dass das ändern der Variablen »weather« in der Datei ›Wetter.py‹ sich das Bild »weatherpic« in der Datei ›UI.py‹ ändert. Es gibt ein Bild für kein Ereignis und für jede Wetterlage eins.

Die Schwierigkeiten
Es traten folgende Fehler auf.
  • Es passiert nichts
    Das Bild für kein Ergebnis bleibt.
  • Das bild für kein Ergebnis verschwindet
  • Das bild für kein Ergebnis verschwindet, es gibt die Fehlermeldung dass das geforderte Bild nicht existiert,
Meine Frage
Ich hab einen Weg gefunden der tatsächlich funktioniert. Wenn ich den Wechsel so:

Code: Alles auswählen

if weather == "01d":
	self.weatherpic.config(image=clear)
	command=UI.tada
ausführen lasse ändert sich das Bild wie gewünscht. Allerdings erfüllt command=UI.tada keinen Zweck.
Aber nur wenn dieser oder ein anderer Sinn freier aufruf erfolgt funktioniert es. Sinnfrei heißt es löst nichts aus.
Ich erhalte die Fehlermeldung: name 'UI' is not defined
Wenn ich ein »def« aufrufe die im selben Skript z.B. einfach nur per »print«-Befehl ein "OK" ausgeben soll erscheint zwar das "OK" aber das Bild für kein Ereignis verschwindet.

Warum geht das nur wenn ich die Fehlermeldung erhalte?
Was kann ich tun damit es funktioniert und kein Fehler auftaucht?

(Der Aufruf heißt »tada« weil mir nichts gescheites eingefallen ist für etwas das keinen zweck erfüllt)

Die Oberfläche (UI.py):

Code: Alles auswählen

#!/usr/bin/env python3

import json
from urllib.request import urlopen
from tkinter import(mainloop, Button, RIGHT, LEFT, E, W, N, Tk, Frame, RIDGE,
                    Label, Entry, Menu, PhotoImage)
from Wetter import *
from Menue import *


fgc='white'     # Schriftfarbe
bgc='darkred'   # Hintergrundfarbe
tl='Arial'      # Text der Label
sg=10           # Schriftgröße
sge=11          # Schriftgröße Button


class GUI:
    def __init__(self):
        self.oberfläche()

    def oberfläche(self):
        self.fenster=Tk()
        self.fenster.title("Wetter Weltweit")
        self.fenster.config(bg='darkred')

        snow=PhotoImage(file='weather-snow.png')
        clouds=PhotoImage(file='weather-few-clouds.png')
        cloudsn=PhotoImage(file='weather-few-clouds-night.png')
        clear=PhotoImage(file='weather-clear.png')
        clearn=PhotoImage(file='weather-clear-night.png')
        mist=PhotoImage(file='weather-fog.png')
        rain=PhotoImage(file='weather-showers.png')
        drizzle=PhotoImage(file='weather-showers-scattered.png')
        cloudy=PhotoImage(file='weather-overcast.png')
        thunder=PhotoImage(file='weather-storm.png')
        world=PhotoImage(file='world.png')
        wetterbild=world
        #self.wetterbild=StringVar()       
        
        #self.fenster.iconbitmap('@symbolw.xbm')
        self.rahmen = Frame(master=self.fenster, relief=RIDGE, bd=4,
                            padx=5,pady=5, bg=bgc)
        self.title = Label(master=self.rahmen, width=25, bg=bgc, fg=fgc,
                           text="Wetter aktuell", font=("Courier", 14))
        self.rahmen.grid()
        self.title.grid(column=0, row=0, columnspan=3)
        
        self._addMenueleiste()
        self._addHilfemenue()

        label1=PhotoImage(file='snow.png')
    # Suche
        self.sucheLabel=Label(master=self.rahmen, bg=bgc, fg=fgc,
                              text="Ort/Stadt:")
        self.sucheEntry=Entry(master=self.rahmen, width=20, justify=RIGHT)
        
        self.fenster.bind('<KeyPress-Return>', self.button)
        self.fenster.bind('<KeyPress-KP_Enter>', self.button)
        self.sucheEntry.focus()
        self.sucheLabel.grid(column=0, row=1)
        self.sucheEntry.grid(column=1, row=1, columnspan= 2, pady=5, sticky=W)
        
    # Ausgabe Ort
        self.ortLabel=Label(master=self.rahmen, bg=bgc, fg=fgc,
                            text="Ort: ")
        self.ortOut=Label(master=self.rahmen, width=20)
        # Layout
        self.ortLabel.grid(column=0, row=2)
        self.ortOut.grid(column=1, row=2, columnspan=2, sticky=W)

    # Temperatur
        self.tempLabel=Label(master=self.rahmen, bg=bgc, fg=fgc,
                             text="Temperatur:")
        self.tempOut=Label(master=self.rahmen, width=10, justify=RIGHT)
        
        self.feelLabel=Label(master=self.rahmen, bg=bgc, fg=fgc,
                                text="Gefühlt:")
        self.feelOut=Label(master=self.rahmen, width=10, justify=RIGHT)

        # Layout
        self.tempLabel.grid(column=0, row=3)
        self.tempOut.grid(column=1, row=3, pady=5, sticky=W)
        self.feelLabel.grid(column=0, row=4)
        self.feelOut.grid(column=1, row=4, sticky=W)

    # Feuchtigkeit
        self.humiLabel=Label(master=self.rahmen, bg=bgc, fg=fgc,
                             text="Luftfeuchtigkeit:")
        self.humiOut=Label(master=self.rahmen, width=10, justify=RIGHT)
        
        #Layout
        self.humiLabel.grid(column=0, row=5)
        self.humiOut.grid(column=1, row=5, pady=5, sticky=W)
        
    # Wind
        self.windLabel=Label(master=self.rahmen, bg=bgc, fg=fgc,
                             text="Windgeschwindigkeit:")
        self.windOut=Label(master=self.rahmen, width=10, justify=RIGHT)
        self.windSpeed=Label(master=self.rahmen, bg=bgc, fg=fgc,
                             text="km/h")
        self.direct=Label(master=self.rahmen, bg=bgc, fg=fgc,
                              text="Windrichtung:")
        self.directOut=Label(master=self.rahmen, width=10, justify=RIGHT)
        self.directDirect=Label(master=self.rahmen, bg=bgc, fg=fgc,
                                    text="°")
        self.staerke=Label(master=self.rahmen, bg=bgc, fg=fgc,
                               text="Windstärke:")
        self.staerkeOut=Label(master=self.rahmen, width=20, justify=RIGHT)
        # Layout
        self.windLabel.grid(column=0, row=6)
        self.windOut.grid(column=1, row=6, sticky=W)
        self.windSpeed.grid(column=2, row=6, sticky=W)
        self.direct.grid(column=0, row=7)
        self.directOut.grid(column=1, row=7, pady=5, sticky=W)
        self.directDirect.grid(column=2, row=7, sticky=W)
        self.staerke.grid(column=0, row=8)
        self.staerkeOut.grid(column=1, row=8, columnspan=2, sticky=W)

    # Land
        self.countryLabel=Label(master=self.rahmen, bg=bgc, fg=fgc,
                                text="Ländercode")
        self.countryEntry=Entry(master=self.rahmen, width=8)
        self.countryEntry.insert(0,"deu")

        self.countryLabel.grid(column=0, row=9)
        self.countryEntry.grid(column=1, row=9, pady=5, sticky=W)

    # Wetterbild
        self.weatherpic=Label(master=self.rahmen, bg=bgc,
                              image=wetterbild)
        self.weatherpic.grid(column=2, row=3, rowspan=3, padx=5)
        self.weatherpic1=Label(master=self.rahmen, bg=bgc, image=clouds)
        #self.weatherpic1.grid(column=2, row=10)
    # Wetterlage
        self.wetterlage=Label(master=self.rahmen, width=10)
        #self.wetterlage.grid(column=1, row=10)

        self.fenster.mainloop()

    #def buttonS(self):
     #   command=Wetter.auswertung(self)
    def button(self, event):
        command=Wetter.auswertung(self)

# Menüleiste
    def _addMenueleiste(self):
        self.menueleiste=Menu(self.fenster)
        self.fenster.configure(menu=self.menueleiste)

    def _addHilfemenue(self):
        self.hilfemenue=Menu(master=self.menueleiste)
        self.menueleiste.add_cascade(label="Hilfe",
                                     menu=self.hilfemenue)
        self.hilfemenue.add_command(label="Über",
                                        command=self.ueber)
    def ueber(self):
        command=Menue.ueber(self)

    def tada(self):
        print("ja")

g=GUI()
w=Wetter()
m=Menue()
Die Datei die die Daten abruft und verarbeitet (Wetter.py):

Code: Alles auswählen

import json
from urllib.request import urlopen
from tkinter import PhotoImage


ID = "6052e99753d39f75c9fa3f11cf0d1d8e"     #1
URL = """
http://api.openweathermap.org/data/2.5/weather?q={},{}&APPID={}&units=metric&lang=de
"""                                         #2

class Wetter:
    def auswertung(self):
        snow=PhotoImage(file='weather-snow.png')
        clouds=PhotoImage(file='weather-few-clouds.png')
        cloudsn=PhotoImage(file='weather-few-clouds-night.png')
        mist=PhotoImage(file='weather-fog.png')
        clear=PhotoImage(file='weather-clear.png')
        clearn=PhotoImage(file='weather-clear-night.png')
        rain=PhotoImage(file='weather-showers.png')
        drizzle=PhotoImage(file='weather-showers-scattered.png')
        cloudy=PhotoImage(file='weather-overcast.png')
        thunder=PhotoImage(file='weather-storm.png')
        z=0                                 #3
        while z < 1:
            city = self.sucheEntry.get()
            city = city.replace(" ", "%20") #4
            city = city.replace("ö", "oe")
            city = city.replace("ü", "ue")
            city = city.replace("ä", "ae")
            city = city.replace("ß", "ss")
            country_code = self.countryEntry.get()
            CC = country_code.replace(" ", "")
            if not city:
                break
            with urlopen(URL.format(city, CC, ID)) as file: #5
                data = json.load(file)
            city_name = data["name"]
            temperature = data["main"]["temp"]
            pressure = data["main"]["pressure"]
            humidity = data["main"]["humidity"]
            feels_like = data["main"]["feels_like"]
            speed = data["wind"]["speed"]
            deg = data["wind"]["deg"]
            weather = data["weather"][0]["icon"]            #10
            visibility = data["visibility"]
            speedkmh = speed * 3.6       # Umrechnung von m/s in km/h            print(weather)
            print(URL.format(city, CC, ID))

# Anfang Übergabe in UI
    # Windgeschwindigkeit                                   #6
            if speedkmh > 117:
                self.staerkeOut.config(text="12 Orkan")
            elif speedkmh > 102:
                self.staerkeOut.config(text="11 orkanartiger Sturm")
            elif speedkmh > 88:
                self.staerkeOut.config(text="10 schwerer Sturm")
            elif speedkmh > 74:
                self.staerkeOut.config(text="9 Sturm")
            elif speedkmh > 61:
                self.staerkeOut.config(text="8 stürmischer Wind ")
            elif speedkmh > 49:
                self.staerkeOut.config(text="7 steifer Wind")
            elif speedkmh > 38:
                self.staerkeOut.config(text="6 starker Wind")
            elif speedkmh > 28:
                self.staerkeOut.config(text="5 frische Brise")
            elif speedkmh > 19:
                self.staerkeOut.config(text="4 mäßige Brise")
            elif speedkmh > 11:
                self.staerkeOut.config(text="3 schwche Brise")
            elif speedkmh > 5:
                self.staerkeOut.config(text="2 leichte Briese")
            else:
                self.staerkeOut.config(text="0 - 1")
    # Windrichtung                                          #7
            if 340 > deg >= 290:
                self.directDirect.config(text="NW")  
            elif 290 > deg >= 250:
                self.directDirect.config(text="W")
            elif 250 > deg >= 200:
                self.directDirect.config(text="SW")
            elif 200 > deg >= 160:
                self.directDirect.config(text="S")
            elif 160 > deg >= 110:
                self.directDirect.config(text="SE")
            elif 110 > deg >= 70:
                self.directDirect.config(text="E")
            elif 70 > deg >= 20:
                self.directDirect.config(text="NE")
            else:
                self.directDirect.config(text="N")
    # Farbskalen                                            #8
        # Wind
            if speedkmh < 117:
                self.staerkeOut.config(bg='red')
                if speedkmh < 89:
                    self.staerkeOut.config(bg='orange')
                    if speedkmh < 62:
                        self.staerkeOut.config(bg='yellow')
                        if speedkmh < 29:
                            self.staerkeOut.config(bg='lightgreen')
            else: self.staerkeOut.config(bg='purple')
        # Temperatur
            if temperature < 32:
                self.tempOut.config(bg='orange')
                if temperature < 26:
                    self.tempOut.config(bg='yellow')
                    if temperature < 20:
                        self.tempOut.config(bg='lightgreen')
                        if temperature < 13:
                            self.tempOut.config(bg='turquoise')
                            if temperature < 6:
                                self.tempOut.config(bg='darkturquoise')
                                if temperature < 1:
                                    self.tempOut.config(bg='blue')
                                    if temperature < -5:
                                        self.tempOut.config(bg='violet')
            else: self.tempOut.config(bg='red')
    # Werte                                                     #9
            self.ortOut.config(text=city_name)
            self.tempOut.config(text=(temperature, "°C"))
            self.feelOut.config(text=(feels_like, "°C"))
            self.humiOut.config(text=(humidity, "%"))
            self.windOut.config(text=format(speedkmh, ",.2f"))
            self.directOut.config(text=(deg,"°"))
            self.wetterlage.config(text=weather)
    # Wetterbilder
            if weather == "01d":
                self.weatherpic.config(image=clear)
                command=UI.tada
            elif weather == "01n":
                self.weatherpic.config(image=clearn)
                command=UI.tada
            elif weather == "02d":
                self.weatherpic.config(image=clouds)
                command=UI.tada
            elif weather == "02n":
                self.weatherpic.config(image=cloudsn)
                command=UI.tada
            elif "03d" <= weather <= "04n":
                self.weatherpic.config(image=cloudy)
                command=UI.tada
            elif weather == "09d":
                self.weatherpic.config(image=rain)
                command=UI.tada
            elif "10d" <= weather <= "10nd":
                self.weatherpic.config(image=drizzle)
                command=UI.tada
            elif "11d" <= weather <= "11n":
                self.weatherpic.config(image=thunder)
                command=UI.tada
            elif "13d" <= weather <= "13n":
                self.weatherpic.config(image=snow)
                command=UI.tada
            elif "50d" <= weather <= "50n":
                self.weatherpic.config(image=mist)
                command=UI.tada
# Ende Übergabe

            z=z+1    

Die Datei Menue.py existiert, hier hab ich sie aber weggelassen.
Die Verwendeten Bilddateien befinden sich bei Ubuntu im Ordner: /usr/share/icons/gnome/48x48/status/

Schon mal Danke fürs lesen und nachdenken

Gruß
Valentin
__deets__
User
Beiträge: 14538
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist garantiert das uebliche Problem bei PhotoImages: die muss man explizit aufheben, damit sie nicht abgeraeumt werden, und dann eben nix dargestellt wird.

Code: Alles auswählen

self._images = {}
for name ["snow", "few-clouds", ...]:
    self._images[name] = PhotoImage(file=f'weather-{name}.png')
Und schon kannst du via dem Namen auf ein Image zugreifen.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Klasse `Wetter` ist keine Klasse. Du missbrauchst hier auch `self`. Du solltest das lesen der Webseite von der Anzeige trennen, den ersten Teil in eine eigene Funktion auslagern, und die Anpassung der GUI in die GUI-Klasse als Methode packen.
Statt sieben mal die Farbe der temperatur zu ändern, solltest Du auch hier elif benutzen, und das ganz in eine Funktion auslagern, die eine Temperatur in eine Farbe umwandelt.

Die Methode oberfläche ist unnötig, weil in __init__ nur diese eine Methode aufgerufen wird, das könnte auch alles direkt in __init__ stehen.
__init__ ist zum Initialisieren da, nicht dass die Methode ewig läuft, denn dann arbeitest Du die ganze Zeit mit einem nicht fertig initialisierten Objekt: das mainloop gehört in die main-Funktion, die Du auch noch schreiben mußt.
g ist ein schlechter Variablennamen, weil einbuchstabig, w und m werden nie verwendet, können also weg (weil das ja eh keine sinnvollen Klassen sind).

Statt selbst einzelne Zeichen per %xy zu escapen, sollte man eine passende Funktion (urllib.parse.urlencode) verwenden, statt die Parameter der URL mit Format reinzuschreiben.
valentinks
User
Beiträge: 20
Registriert: Sonntag 27. Juni 2021, 10:31
Wohnort: Kassel

@ Sirius3
Danke für die Antwort, leider wirft sie neue Fragen auf.
  • Warum "missbrauche" ich self?
  • Das Ändern der Anzeige in die GUI zupacken hatte ich schon, nur wollte mir das nicht gelingen.
  • Das mit der __init__ ist verwirrend. An anderer Stelle hatte ich schon mal das ganze Aussehen in der __init__ da schrieb __blackjack__: Nachdem die `__init__()` durchgelaufen ist, sollte man ein benutzbares Objekt haben. In die `__init__()` gehört deshalb nicht der komplette Programmablauf, denn momentan kehrt die `__init__()` erst zum Aufrufer zurück wenn der Benutzer die GUI geschlossen hat. Dann kann man aber mit dem `Rechner`-Objekt nichts mehr anfangen.
  • Da es hier im Buch nicht "die" main-Funktion gibt und der mainloop immer sitzt wo ich ihn hingeschrieben habe, verstehe ich das nicht.
  • g=GUI() ist doch nur dafür da das ganz zu starten.
  • In urllib.parse.urlencode muss ich erstmal was zulesen, das mit den Parameter per Format reinschreiben ist orginal Buchtext, nur das mit den Umlauten und Leerzeichen stammt von mir (aber auch der Austausch der Umlaute wird an anderer Stelle im Buch vorgenommen da dann über HTML = {ord("ä"): "&auml;", ord("ö"): "&ouml;", ...}ist das eleganter als replace?
Gibt es eine empfehlenswerte Lektüre um Python zu lernen?

Danke nochmal für die Mühe.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@valentinks: `self` ist der Name für das Objekt auf dem die Methode aufgerufen wird. Und das ist vom Typ der Klasse auf der die Methode definiert ist. Das müsste also ein `Wetter`-Objekt sein. Ist es aber nicht, weil Du die ”Methode” wie eine Funktion verwendest und da ein `GUI`-Objekt als `self` übergibst. Was total unerwartet und damit falsch ist.

Meine Anmerkung bezüglich der `__init__()` gilt auch weiterhin für diesen Code. Das alles nicht mehr in der `__init__()` *direkt* steht, sondern in eine weitere Methode verschoben wurde, ändert an der Anmerkung ja nichts. Wenn die `__init__()` aufgerufen wird, läuft das gesamte Programm ab, und wenn der Aufruf zurückkehrt ist das erstellte GUI-Objekt nutzlos weil die Show schon vorbei ist.

Re `main()`-Funktion: Schreib eine `main()`-Funktion und dort das Hauptprogramm rein. So wirklich viel mehr gibt es da nicht zu verstehen.

Was mit „g=GUI() ist doch nur dafür da das ganz zu starten.“ gemeint ist verstehe ich jetzt nicht. Es sollte halt so nicht sein. Siehe den Punkt mit der `__init__()`. Das startet nicht nur etwas, das führt alles aus. Das heisst daran sieht man auch sehr schön das die beiden Definitionen die danach kommen komplett sinnfrei sind, denn das passiert ja nachdem der Benutzer die GUI *beendet* hat.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
valentinks
User
Beiträge: 20
Registriert: Sonntag 27. Juni 2021, 10:31
Wohnort: Kassel

@ __blackjack__
Das Problem ist dass ich nicht verstehe was die main()-Funktion sein soll. Ist das eine »def main(self):«? Is meine »def oberfläche(self):« keine main()-Funktion?
Ich hab noch kein Skript gesehen in der eine Funktion den Namen ›main‹ hat. Im Buch sind in der __init__ die tk, die fenster, rahmen und Button. Dann folgen die Funktionen. Da das aber nicht sein soll und die __init__ auch nicht die »def oberfläche:« aufrufen soll verstehe ich nicht welchen Weg ich nehmen soll.

g=GUI() ist doch nur dafür da das zu starten heißt: Ohne diese Zeile läuft es nicht. Da öffnet sich kein Fenster. Im Buch ist die Erklärung für diese Zeile: Eine Instanz der Klasse GUI wird erzeugt

Hat jemand mal ein Beispiel Skript an dem ich erkenne wie die __init__ aussehen soll und wie danach die Oberfläche und die main() erstellt wird?

Ein Beispiel aus dem Buch:

Code: Alles auswählen

class Vokabeltrainer(object):
  def __init__(self, datei):
    # neuen Karteikasten anlegen und erste Karte ziehen
    self.gelernt = 0 
    self.datei = datei                                   
    self.k = Karteikasten(datei)                      #1   
    self.aktVokabel = self.k.getNeueVokabel()
          
    # Widgets instanzieren
    self.fenster = Tk()    
    self.vokabel = StringVar()                        #2 
    self.vokabel.set(self.aktVokabel[0])
    self.titel = Label(master=self.fenster,
                    text='Vokabeltrainer',
                    font=('Comic Sans MS',14),fg='blue')
    self.rahmen = Frame(master=self.fenster,
                      relief=RIDGE,bd=2)
    self.englischLabel = Label(master=self.rahmen,
                        textvariable=self.vokabel,    #3
                        font=('Arial',14))
    self.deutschLabel = Label(master=self.rahmen,
                        text='Deutsch:')
    self.entry = Entry(master=self.rahmen, width=15)
    self.okButton = Button(master=self.rahmen,text='ok',
                           command=self.ok)           #4
    self.gelerntLabel = Label(master=self.fenster, 
                      width=10, bg='yellow',
                      text=str(self.gelernt)+' gelernt')
    self.rfLabel = Label(master=self.fenster, width=20)
    self.nochmalButton = Button(master=self.fenster,
                              text='noch einmal',
                              command=self.nochmal)   #5
    self.layout()
    self.fenster.mainloop()
   
     def layout(self):
    # Layout der Widgets  
    self.titel.pack()
    self.englischLabel.pack()
    self.deutschLabel.pack(side=LEFT)
    self.entry.pack(side=LEFT, padx=10, pady=10)
    self.okButton.pack(side=RIGHT, padx=10, pady=10)
    self.rahmen.pack()
    self.gelerntLabel.pack(side=LEFT, padx=10, pady=10)
    self.rfLabel.pack(side=LEFT)
    self.nochmalButton.pack(side=RIGHT,
                            padx=10, pady=10)

  def nochmal(self):
    self.k = Karteikasten(self.datei)                 #1
 
    self.aktVokabel = self.k.getNeueVokabel()         #2
    self.vokabel.set(self.aktVokabel[0])              #3
    self.gelernt = 0
    self.gelerntLabel.config(
        text = str(self.gelernt) + ' gelernt')        #4         
    self.rfLabel.config(text='')                      #5

  def ok(self):
    if self.entry.get() in self.aktVokabel[1:]:       #6
        self.rfLabel.config(text='Richtig!')
        self.k.lerne()
        self.fenster.after(1000, self.loeschen) 
        self.gelernt += 1
        self.gelerntLabel.config(
            text=str(self.gelernt) + ' gelernt') 

    else:                                             #7
        ausgabe = 'Falsch! Richtig ist:\n'
        ausgabe += ' '.join(self.aktVokabel[1:])
        self.rfLabel.config(text=ausgabe)
        self.k.legeNachHinten()
        self.fenster.after(3000, self.loeschen)

  def loeschen(self):                                 #8
      self.rfLabel.config(text='')
      self.entry.delete(0,15)
      self.aktVokabel = self.k.getNeueVokabel()
      if self.aktVokabel:
          self.vokabel.set(self.aktVokabel[0])
      else:
         self.rfLabel.config(text='Alles gelernt!') 

# Hauptprogramm
 
v = Vokabeltrainer('vokabeln.txt')
    
Ja das ist 1:1 so im Buch, mit den Einzügen. Bei anderen Skripten steht auch mal nichts in den Klammern der letzten Zeile. Die Klammern in den Klassen sind auch manchmal leer.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Auf oberster Ebene dürfen nur Definitionen stehen, deshalb muß das g=GUI in eine Funktion wandern, die halt main genannt wird, weil sie als erstes ausgeführt wird und damit das Hauptprogramm ist. Ansonsten ist das eine ganz normaler Funktion.

Code: Alles auswählen

class GUI:
    ...

def main():
    gui = GUI()
    gui.fenster.mainloop()

if __name__ == "__main__":
    main()
wobei man nicht von außen auf gui.fenster zugreifen würde, sondern das in einer Methode von GUI verschieben würde, oder gleich GUI von tk.Tk erben lassen würde.

Bücher bringen einem meist nicht guten Programmierstil bei, und wie man hier sieht, halten sich nicht einmal an die simpelsten Konventionen.
valentinks
User
Beiträge: 20
Registriert: Sonntag 27. Juni 2021, 10:31
Wohnort: Kassel

Danke erstmal für die erklärung der main() @Sirius3. Auch @ __blackjack__ für die Erklärungen.
Leider ist meine ursprüngliche Frage unbeantwortet. Ich wollte nicht wissen warum der Fehler auftritt,
die Frage warum funktioniert der Bildwechsel nur mit dem Fehler, kein Fehler = keine Funktion.
Das ist die große Frage, ohne den Aufruf der sinnlosen Zeile gibt es keinen Bilderwechsel.

Das noch soviel mehr falsch war hatte ich nicht gefürchtet. Die aktuelle aufteilung ist so weil ich es nicht geschafft habe die Werte aus Wetter in die UI zuholen. Auch jetzt, bekomme ich die Werte zwar in den Feldern angezeigt, eine Weiterverarbeitung klappt leider nicht.

Seit der Änderung gibt es ein neues Problem, das Öffnen über den Starter auf dem Desktop klappt nicht mehr.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@valentinks: Durch die Ausnahme, wo auch der Traceback, und damit alle beteiligten lokalen Namensräume von den Funktionsaufrufen dran hängen, leben diese Namensräume und ihr Inhalt solange es die Ausnahme als Objekt gibt. Und damit in diesem Fall auch das Bildobjekt welches sonst am normalen Ende der Funktion abgeräumt worden wäre.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
valentinks
User
Beiträge: 20
Registriert: Sonntag 27. Juni 2021, 10:31
Wohnort: Kassel

__deets__ hat geschrieben: Mittwoch 8. Dezember 2021, 13:21 Das ist garantiert das uebliche Problem bei PhotoImages: die muss man explizit aufheben, damit sie nicht abgeraeumt werden, und dann eben nix dargestellt wird.

Code: Alles auswählen

self._images = {}
for name ["snow", "few-clouds", ...]:
    self._images[name] = PhotoImage(file=f'weather-{name}.png')
Und schon kannst du via dem Namen auf ein Image zugreifen.
@ __deets__ auch dir Danke für die unterstützung. Allerdings stehe ich vor dem Problem das der Doppelpunkt zu der Fehlermeldung »invalid syntax« führt. Da stehe ich leider gerade auf dem Schlauch.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@valentinks: Grundlagen ``for``-Schleifen — da fehlt halt noch was.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
valentinks
User
Beiträge: 20
Registriert: Sonntag 27. Juni 2021, 10:31
Wohnort: Kassel

Hab es dann gestern früh geschafft.
Danke für eure Unterstützung
Antworten