Warum verhält sich alles in einer Klasse anders? (Tkinter)

Fragen zu Tkinter.
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Hallo,

Warum ist das so? Warum verhält sich die Anordnung von verschiedene Labels in einer Klasse anders als nicht in einer Klasse, obwohl es sich 1:1 um den selben Code handelt? Und wie kann ich das Problem lösen? :?:

Beispiel 1:
Label mit Text ist alleinstehend ohne Klasse zentriert im Fenster und in einer Klasse leicht versetzt.

Beispie 2:
Ein Photo, welches ohne Klasse angezeigt wird, wird in einer Klasse nicht angezeigt.

Ich hoffe man kann mich ein bisschen verstehen.

Lg
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, das ist leider nicht verständlich. Bitte zeige und den Code.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@l30n100: man muß immer eine Referenz auf die Image-Instanz behalten, weil sonst der Speicher des Bildes freigegeben wird.
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Sirius3 hat geschrieben:@l30n100: man muß immer eine Referenz auf die Image-Instanz behalten, weil sonst der Speicher des Bildes freigegeben wird.
Wie soll ich das verstehen? :K tut mir leid der Nachfrage. :?

Lg
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

ups...
Zuletzt geändert von l30n100 am Montag 5. März 2018, 11:44, insgesamt 1-mal geändert.
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

__deets__ hat geschrieben:Nein, das ist leider nicht verständlich. Bitte zeige und den Code.

Code: Alles auswählen

class Hallo:
    def __init__(self):
        #Haupseite
        self.main = tkinter.Tk()
        self.main.geometry("1000x580")

        #Begrüßungstext
         self.hallo = tkinter.Label(self.main, text = """
         ...
         ...
         ...
         """)
        self.hallo.pack()
        self.hallo["font"] = "Arial 20"
        ...
        self.main.mainloop()

class Menu:
    def __init__(self):
        self.menu = tkinter.Toplevel()
        ...
        #Startbild
        self.head = tkinter.Label(self.headmenu)
        self.im = tkinter.PhotoImage(file="F:\\...")
        self.head["image"] = self.im
        self.head.pack()
Das ist in etwa so aufgebaut. Das problem ist das der Begrüßungstext schief angzeigt und das Startbild wird gar nicht angezeigt. Wenn man das 1:1 so nicht in einer Klasse schreibt ist es nicht so.

Lg
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da das nicht lauffaehig ist, und die Anweisung da was 1:1 rueber zu kopieren dementsprechend auch nicht so viel bringt, kann man da leider immer noch nix zu sagen. Das sollten schon lauffaehige kleine Beispiele sein fuer *beides*. Ein Bild bekommt man sicher irgendwoher.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi l30n100

Ein Bild muss in Tkinter sowie in der Kunstgalerie an einem Nagel aufgehängt werden. Sonst fällt es runter und wird von Aufräumequipe in die Mulde entsorgt. In Python ist die Aufräumequipe als Garbage Collector bekannt. Diese(r) räumt alles weg was herumliegt und arbeitet unsichtbar im Hintergrund. Folgende Code-Beispiele sollen dies etwas mehr über dieses Verhalten zeigen:

1. Auf Modulebene. Direktzuweisung der Bilddaten an die image-Option des Labels. Das Bild wird im Label nicht angezeigt!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
        
app_win = tk.Tk()

head = tk.Label(app_win)
head.pack()
head["image"] = tk.PhotoImage(file="my_image.gif")

app_win.mainloop()
2. Auf Modulebene. Zuweisung der Bilddaten an eine Variable (der Nagel) auf Modulebenen. Dann Übergabe der Variable an die image-Option des Labels. Jetzt wird das Bild im angezeigt!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
        
        
app_win = tk.Tk()

my_image = tk.PhotoImage(file="my_image.gif")
head = tk.Label(app_win)
head.pack()
head["image"] = my_image

app_win.mainloop()
3. In der Klasse. Direktzuweisung der Bilddaten an die image-Option des Labels. Das Bild wird im Label nicht angezeigt!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class Menu:
    def __init__(self):
        self.menu = tk.Toplevel()

        #Startbild 
        self.head = tk.Label(self.menu)
        self.head.pack()
        self.head["image"] = tk.PhotoImage(file="my_image.gif")
        
        
app_win = tk.Tk()

menu = Menu()

app_win.mainloop()
4. In der Klasse. Zuweisung der Bilddaten an eine Variable die ohne Referenz (self) an die Klasse gebunden ist. Dann Übergabe der so nicht referenzierten Variable an die image-Option des Labels. Das Bild wird im Label nicht angezeigt!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class Menu:
    def __init__(self):
        self.menu = tk.Toplevel()

        #Startbild
        my_image = tk.PhotoImage(file="my_image.gif")
        self.head = tk.Label(self.menu)
        self.head.pack()
        self.head["image"] = my_image
        
        
app_win = tk.Tk()

menu = Menu()

app_win.mainloop()
5. In der Klasse. Zuweisung der Bilddaten an ein Attribut (der Nagel) eine Variabel mit (self) an die Klasse gebundenen Referenz). Übergabe des Klassenattribut an die image-Option des Labels. Jetzt wird das Bild im angezeigt!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class Menu:
    def __init__(self):
        self.menu = tk.Toplevel()

        #Startbild
        self.my_image = tk.PhotoImage(file="my_image.gif")
        self.head = tk.Label(self.menu)
        self.head.pack()
        self.head["image"] = self.my_image
        
        
app_win = tk.Tk()

menu = Menu()

app_win.mainloop()
Hoffe das bringt ein wenig Licht in die Kammer. Sonst müssen mir unsere Topexperten __deets__ und Sirtus3 zu Hilfe kommen.

Gruss wuf :wink:
Take it easy Mates!
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Hallo wuf,
vielen dank für die ausführliche Antwort, aber ich komme irgendwie immer noch nicht zu einem Ergebnis.

Code: Alles auswählen

import tkinter

class HeadMenuWindow:

    def __init__(self):

        self.headmenu = tkinter.Toplevel()
        self.headmenu.title("Kopfrechentrainer - Auswahl")
        self.headmenu.geometry("1000x580")
        self.headmenu.iconbitmap("F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Icon.ico")

        #Titelbild
        self.image = tkinter.PhotoImage(file="F:\\...")
        self.head = tkinter.Label(self.headmenu)
        self.head.pack()
        self.head["image"] = self.image

test = HeadMenuWindow
test()
Das ist jetzt der Anfang von meiner Klasse und das Bild wird immer noch nicht angezeigt. Ich glaube ich sehe meinen eigenen Fehler einfach nicht.

Lg
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi l30n100

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class HeadMenuWindow():
 
    def __init__(self):
 
        self.headmenu = tk.Toplevel()
        self.headmenu.title("Kopfrechentrainer - Auswahl")
        self.headmenu.geometry("1000x580")
        self.headmenu.iconbitmap("F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Icon.ico")
 
        #Titelbild
        self.image = tk.PhotoImage(file=file="F:\\...")
        self.head = tk.Label(self.headmenu)
        self.head.pack()
        self.head["image"] = self.image


app_win = tk.Tk()
test = HeadMenuWindow()
app_win.mainloop()
Das sollte aber funktionieren.

Gruss wuf :wink:
Take it easy Mates!
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Ne leider wieder ohne Erfolg. Auch wenn ich das hier aus dem Forum Kopiere Klappt das nicht. Kann es daran liegen, dass die Klasse über eine Methode von einer anderen Klasse geöffnet wird? Weil wenn ich die Klasse als allein stehende Klasse habe funktioniert das bei mir. :?:

lg
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@l30n100: dann zeig doch was Du WIRKLICH für Code hast, und beschreibe genau, was passiert und was Du so nicht erwartest. Sonst ist das nur ein Rumgerate.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi
Die Zeile:

Code: Alles auswählen

self.image = tk.PhotoImage(file=file="F:\\...")
sollte natürlich wie folgt heissen:

Code: Alles auswählen

self.image = tk.PhotoImage(file="F:\\...")
Wie lautet der Name deiner Bilddatei?
"F:\\..." kann es sicher nicht sein.

Gruss wuf :wink:
Take it easy Mates!
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Sirius3 hat geschrieben:@l30n100: dann zeig doch was Du WIRKLICH für Code hast, und beschreibe genau, was passiert und was Du so nicht erwartest. Sonst ist das nur ein Rumgerate.

Code: Alles auswählen

import tkinter


class MainWindow:
    
    def __init__(self, menu):

        self.menu = menu

        def sonstiges1():
            self.menu

        #Login Window
        def loginwindow():
        	        #pwtest
            def pwkopf():
                self.eingabe = self.e2.get() #Passwort
                self.eingabe1 = self.e1.get() #Nutzername
                if self.eingabe == "123" and self.eingabe1 == "123":
                    self.login.destroy()
                    self.main.withdraw()
                    self.menu()
                else:
                    self.verweigern["text"] = "Zugang verweigert!"
                    self.verweigern["font"] = "Arial 10"
                    self.verweigern["fg"] = "#FF0000"
            
            self.login = tkinter.Toplevel()
            self.login.title("Anmeldung")
            self.login.geometry("261x130")
            self.login.iconbitmap("F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Icon.ico")
            #Widgets
            self.logintxt1 = tkinter.Label(self.login, text = "Bitte melden Sie sich an")
            self.logintxt1["font"] = "Arial 10 bold"
            self.logintxt1.place(relx = 0.5, y = 6, anchor = "n")
    
            self.logintxt2 = tkinter.Label(self.login, text = "Benutzername:")
            self.logintxt2["font"] = "Arial 10"
            self.logintxt2.place(x = 10, y = 30, anchor = "nw")
    
            self.e1 = tkinter.Entry(self.login)
            self.e1.place(x = 120, y = 33, anchor = "nw")

            self.logintxt3 = tkinter.Label(self.login, text = "Passwort:")
            self.logintxt3["font"] = "Arial 10"
            self.logintxt3.place(x = 10, y = 60, anchor = "nw")
        
            self.e2 = tkinter.Entry(self.login, show = "*")
            self.e2.place(x = 120, y = 60, anchor = "nw")

            #Extras
            def abbruch():
                self.login.destroy()
        
            self.abbruch_button = tkinter.Button(self.login, text = "Abbruch", command = abbruch)
            self.abbruch_button.place(x = 188, y = 90, anchor = "nw")

            self.los = tkinter.Button(self.login, text = "Login", command = pwkopf)
            self.los.place(x = 135, y = 90, anchor = "nw")

            self.verweigern = tkinter.Label(self.login)
            self.verweigern.place(x = 14, y = 91)
        
        #Haupseite
        self.main = tkinter.Tk()
        self.main.geometry("1000x580")
        
        #Titelbild
        self.head = tkinter.Label(self.main)
        self.im = tkinter.PhotoImage(file="F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Startseite(klein).png")
        self.head["image"] = self.im
        self.head.pack()

        #Begrüßungstext
        self.hallo = tkinter.Label(self.main, text = """
        Hallo,
        mein Name ist Fiete P..

        ...
        """)
        self.hallo.pack()
        self.hallo["font"] = "Arial 20"

        #...
        self.meister = tkinter.Label(self.main, text = "...!")
        self.meister.pack()
        self.meister["font"] = "Arial 30"

        #Button 1
        self.kopf = tkinter.Button(self.main, text  = "Button 1", command = loginwindow)
        self.kopf["bg"] = "#14ADA0"
        self.kopf["fg"] = "#FFFFFF"
        self.kopf["relief"] = "flat"
        self.kopf["height"] = 3
        self.kopf["width"] = 29
        self.kopf["font"] = "Arial 15 bold"
        self.kopf.pack(padx = 70, pady = 20, side = "left")

        #Button 2
        self.blatt = tkinter.Button(self.main, text  = "Button 2")
        self.blatt["bg"] = "#1894CE"
        self.blatt["fg"] = "#FFFFFF"
        self.blatt["relief"] = "flat"
        self.blatt["height"] = 3
        self.blatt["width"] = 29
        self.blatt["font"] = "Arial 15 bold"
        self.blatt.pack(padx = 70, pady = 20, side = "right")


        #Window Icon Set
        self.main.iconbitmap("F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Icon.ico")
        self.main.title("Fiete Pauker")

        #mainloop
        self.main.mainloop()
    
#Kopfrechen - Auswahlmenü
class HeadMenuWindow:

    def __init__(self):
        #Standard
        self.headmenu = tkinter.Toplevel()
        self.headmenu.title("Auswahl")
        self.headmenu.geometry("1000x580")
        self.headmenu.iconbitmap("F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Icon.ico")
 
        #Titelbild
        self.image = tkinter.PhotoImage(file="F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Kopfrechen\\Kopfrechen Menu(neu).png")
        self.head = tkinter.Label(self.headmenu)
        self.head.pack()
        self.head["image"] = self.image

        #Angemeldet als
        self.login_as = tkinter.Label(self.headmenu, text = "...")
        self.login_as["fg"] = "#000000"
        self.login_as["bg"] = "#FFFFFF"
        self.login_as["font"] = "Arial 15"
        self.login_as.place(rely = 0.33, relx = 0.83)

        #Abmelden
        self.logout = tkinter.Button(self.headmenu, text = "Abmelden")
        self.logout["font"] = "Arial 15 bold"
        self.logout["relief"] = "flat"
        self.logout["bg"] = "#D1D1D1"
        self.logout["fg"] = "#FFFFFF"
        self.logout["height"] = 1
        self.logout["width"] = 12
        self.logout.place(rely = 0.912, relx = 0.834)

        #2
        self.result = tkinter.Button(self.headmenu, text = "...")
        self.result["font"] = "Arial 15 bold"
        self.result["relief"] = "flat"
        self.result["bg"] = "#ff0000"
        self.result["fg"] = "#FFFFFF"
        self.result["height"] = 7
        self.result["width"] = 14
        self.result.place(rely = 0.27, relx = 0.05)

        #1
        self.quad = tkinter.Button(self.headmenu, text = "...")
        self.quad["relief"] = "flat"
        self.quad["height"] = 2
        self.quad["width"] = 16
        self.quad["fg"] = "#FFFFFF"
        self.quad["bg"] = "#ffe500"
        self.quad["font"] = "Arial 15 bold"
        self.quad.place(rely = 0.82, relx = 0.054)

    
menu = HeadMenuWindow

startseite = MainWindow

startseite(menu)

So. Der ganze Code.
Lg
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi l30n100

Bei mir läuft dein Skript und das Bild wird angezeigt. Gut ich habe für meinen Versuch unter Linux Ubuntu 16.04 die Zeilen bei welchen Icons Icon.ico eingelesen werden ausgeblendet und die Bilddatei Startseite(klein).png um welche es eigentlich geht im Arbeitsverzeichnis abgelegt. Wirft dein Skript dann keine Fehlermeldungen?
Gruss wuf :wink:
Take it easy Mates!
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Hi wuf,

ne, es wird keine Fehlermeldung ausgegeben. :K

Lg
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

OK l30n100

Zeigt das folgende Skript bei dir das Bild an?:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk
        
        
app_win = tk.Tk()

my_image = tk.PhotoImage(file="F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Startseite(klein).png")
head = tk.Label(app_win)
head.pack()
head["image"] = my_image

app_win.mainloop()
Gruss wuf :wink:
Take it easy Mates!
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Ja, in diesem Skript wird das Bild angezeigt.

Lg
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

OK l30n100

Schritt-02:
Wird bei diesem Skript das Bild auch angezeigt? Achtung das Bild wird nicht im grossen Hauptfenster sondern im zweiten kleinen Zusatzfenster (Toplevel) sichtbar!:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk


class Menu:
    def __init__(self):
        self.menu = tk.Toplevel()

        #Startbild
        self.my_image = tk.PhotoImage(file="F:\\Python\\Projekte\\Fiete Pauker\\Fiete Pauker\\Startseite\\Startseite(klein).png")
        self.head = tk.Label(self.menu)
        self.head.pack()
        self.head["image"] = self.my_image
        
        
app_win = tk.Tk()

menu = Menu()

app_win.mainloop()
Gruss wuf :wink:
Take it easy Mates!
l30n100
User
Beiträge: 19
Registriert: Sonntag 18. Februar 2018, 14:15

Ja, hier wird das Bild wieder sichtbar. Diesmal aber wie du beschrieben hast im Toplevel.

Lg
Antworten