Image in Fenster laden mal geht es mal nicht

Fragen zu Tkinter.
Antworten
Papa Brummbär
User
Beiträge: 4
Registriert: Montag 20. März 2023, 22:32

Hallo Python-Pros,

ich bin neu im Forum und gerade dabei Python zu lernen, Ziel ist es einige Astroprogramme zur Bildauswertung zu schreiben (spez. Fits-Dateien). Jetzt kämpfe ich noch damit die Python-Systematik zu erlernen und lauffähigen Programmcode zu schreiben. Ich habe Anaconda3 installiert und benutze Spyder (Python3.9)

Folgende Zeilen laufen ohne Fehler alleinstehend:

Code: Alles auswählen

from tkinter import *
import tkinter as aHF

HFb = 625 
HFh = 418
HFx = 10
HFy = 10

HF = aHF.Tk()
HF.title("TEXT")
HF.geometry("%dx%d" % (HFb, HFh))   
HF.geometry("+%d+%d" % (HFx, HFy)) 


logo = PhotoImage(file="D:/neu.png") 
w1 = Label(HF, image=logo).pack(side="left")

HF.mainloop()
Ich habe folgende Zeilen und möchte das o.g. geschriebene einfügen

Code: Alles auswählen

from tkinter import *

import tkinter as aHF
import tkinter as aZF
import tkinter as aCF
import tkinter as aMF
#HF = Tk()

def mausli(event):
    #print("Pos = "+ str(event.x)+ " - "+ str(event.y))
    x, y = event.x, event.y
    T.delete('0.0', 'end')
    T.insert (END,'linksClick\n')
    T.insert (END,'X= {},Y= {}'.format(x, y))
    
def mausra(event):
    x, y = event.x, event.y
    T.delete('0.0', 'end')
    T.insert (END,'RadClick\n')
    T.insert (END,'X= {},Y= {}'.format(x, y))

def mausre(event):
    x, y = event.x, event.y
    T.delete('0.0', 'end')
    T.insert (END,'rechtsClick\n')
    T.insert (END,'X= {},Y= {}'.format(x, y))

def mausro(event):
    x, y = event.x, event.y
    T.delete('0.0', 'end')
    T.insert (END,'RadRoll\n')
    T.insert (END,'X= {},Y= {}'.format(x, y))
 
def bewegung(event):
    x, y = event.x, event.y
    print('{}, {}'.format(x, y))
    T.delete('0.0', 'end')
    T.insert (END, 'X= {},Y= {}'.format(x, y))

# Menü Datei
def alleszu():
    MF.quit()
    MF.destroy()
    CF.quit()
    CF.destroy()
    ZF.quit()
    ZF.destroy()
    HF.quit()
    HF.destroy()
    
# Menü MyMenü    funkt noch nicht!!
def bildladen():
    logo = PhotoImage(file="C:/neu.png") 
    w1 = Label(HF, image=logo).pack(side="left")
    T.delete('0.0', 'end')
    T.insert (END, "Bild geladen")
    

#Fenstergrößen
HFb = 625
HFh = 418
CFb = HFb
CFh = 250
MFb = 100
MFh = 100
ZFb = 63*5
ZFh = 42*5


#Fensterposition Monitor
abstand = 5
menu = 30
CFx = abstand
CFy = abstand
HFx = CFx
HFy = CFh + abstand * 2 + menu
MFx = abstand + HFb + abstand
MFy = abstand
ZFx = MFx
ZFy = abstand + MFh + menu + abstand 


#Fenster Einblenden
CF = aCF.Tk()
CF.title("Control-Fenster CF")
CF.geometry("%dx%d" % (CFb, CFh))
CF.geometry("+%d+%d"  % (CFx, CFy))

HF = aHF.Tk()
HF.title("AstroProg V1.0")
HF.geometry("%dx%d" % (HFb, HFh))   #Fenstergröße
HF.geometry("+%d+%d" % (HFx, HFy))  #Fensterposition

MF = aMF.Tk()
MF.title("Maus-Fenster MF")
MF.geometry("%dx%d" % (MFb, MFh))
MF.geometry("+%d+%d"  % (MFx, MFy))

ZF = aZF.Tk()
ZF.title("Zoom-Fenster ZF")
ZF.geometry("%dx%d" % (ZFb, ZFh))
ZF.geometry("+%d+%d"  % (ZFx, ZFy))

#Fenstergröße für XY-Werte Ausgabe
T = Text(CF, height=2, width=15)
T.place(x=100, y=120, )                          #???
T.pack() 							   #???

#Maustasten erkennen
HF.bind("<Button-1>", mausli)
HF.bind("<Button-2>", mausra)
HF.bind("<Button-3>", mausre)
HF.bind("<MouseWheel>", mausro)
HF.bind("<Enter>", mausli)
HF.bind("<Leave>", mausli)
#HF.bind("<Motion>", mausli) # Mausbewegung
HF.bind('<Motion>', bewegung)

menuleiste = Menu(HF)

datei_menu = Menu(menuleiste, tearoff=0)
help_menu = Menu(menuleiste, tearoff=0)
mymenu_menu = Menu(menuleiste, tearoff=0)

datei_menu.add_command(label="ENDE", command=alleszu)
mymenu_menu.add_command(label="Bild laden", command=bildladen)

menuleiste.add_cascade(label="Datei", menu=datei_menu)
menuleiste.add_cascade(label="Help", menu=help_menu)
menuleiste.add_cascade(label="MyMenu", menu=mymenu_menu)

HF.config(menu=menuleiste)

HF.mainloop()
Ich möchte über das Menü "Bild laden" ein Image-Datei öffnen und im Fenster abbilden aber egal was ich mache bekomme ich das nicht hin, kann mir jemand schreiben woran das liegt.
Oder habe ich da einen grundsätzlichen Fehler?

Fehleranzeige Console:
self.tk.call(
_tkinter.TclError: image "pyimage1" doesn't exist

Vielen Dank im Voraus LG
Hampo
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Jedes GUI-Programm, das über absolute Trivialität hinaus geht, benötigt Objektorientierte Programmierung. Du wirst dich also früher oder später damit auseinander setzen müssen, wie das in Python funktioniert.

Man benutzt generell keine *-Importe. Damit holt man sich, gerade bei tkinter, unglaublich viele Namen in den Namensraum. Das möchte man nicht.
Etabliert hat sich ein "import tkinter as tk" und danach greigt man mit tk. auf den entsprechenedn Namensraum zu.

Ich befürchte, dass da noch etwas Verständnis fehlt, was "import" eigentlich tut. Denn du machst nicht nur alle Namen aus tkinter, du importierst zudem noch das Modul tkinter unter 4 verschiedenen Namen. Das macht keinen Sinn.

Es darf in einem Programm nur ein einziges TK-Objekt geben. Du versuchst dir das hier irgendwie herbeizuschummeln, dass du das Modul unter verschiedenen Namen imporierst. Das ist aber definitiv falsch. Wenn du mehr als ein Fenster möchtest, verwendet man dafür "toplevel".

Namen schreibt man in Python klein_mit_unterstrich. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Namen von Klassen (PascalCase).
Verwende sprechende Namen, die du und andere verstehen. Verwende nicht krude Abkürzungen.

Auch und gerade bei GUI-Programmierung:
Auf Modulebene (also ohne Einrückung) stehen nur die Importe, die Definitionen von Funktionen, Klassen und Konstanten und das folgende am Ende der Datei, um eine Funktion aufzurufen, in der dein Programm startet. In der Regel heißt diese Funktion main:

Code: Alles auswählen

if __name__ == "__main__":
    main()
Wenn du das konsquent umsetzt, wirst du keine globalem Variablen mehr haben.

Fenstergrößen sollte man nie definieren. Die ergeben sich aus dem Inhalt.
Den Inhalt sollte man niemals mit .place setzen. Dafür haben GUI-Frameworks LayoutManager, die das übernehmen. Denn wie groß welches Element ist, hängt von verschiedenen Faktoren ab, die du nicht beeinflussen kannst. Was auf deinem System einigermaßen richtig aussieht, kann auf einem anderen komplett anders aussehen.

Was dein spezielles Problem angeht: Sieht so aus, als würde Python dein Image beim Aufräumen aus dem Speicher entfernen. Ich bin mir nur gerade nicht sicher, ob sich das nur vermeiden lässt, indem du den Status des Objektes aufhebst - und dafür brauchst du Objektorierntierte Programmierung - udn ob das daran liegt, dass du mehr als ein Tk-Objekt in deiner Anwendung hast. Denn wenn nicht anders angegeben, wird das immer an das erste Tk-Objekt gebunden.
Papa Brummbär
User
Beiträge: 4
Registriert: Montag 20. März 2023, 22:32

Hallo 'sparrow',

vielen Dank für Deine schnelle Antwort, also Deine Antwort hat mir gezeigt, dass die Bücher die ich habe und das was im Netz steht nicht das sind was Du mir geantwortet hast. Also da muss ich wohl noch einiges noch lernen. Ich habe mir schon gedacht dass ich da etwas falsch mache, denn das Problem sitzt gewöhnlich vor dem PC. Aber noch ein Paar fragen:

Wenn ich die Astrobilder mit tkinter "lade" dann sind die so groß, dass das Fenster über den Monitor hinaus geht. Mein Monitor hat 3840x1080pixel. Also dachte ich Fenstergröße festlegen, Bildladen und danach Bild an Fenster anpassen.

Also ich hab viel früher mal unter Visual Basic etwas programmiert, da war es so man hat ein Fenster gemacht und konnte dann im Fenster mehrere Frames setzen die Frames waren dann wie Subs. Soll das in tkinter auch so gemacht werden?

So da heißt es wohl noch etwas Python studieren und forschen,
also nochmals vielen Dank

LG
Hampo
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Papa Brummbär: Inhalte die für ein Fenster zu gross sind, werden üblicherweise mit Scrollbalken versehen. Und zusätzlich kann man dann noch eine Option zum verkleinern (und vielleicht auch vergrössern) einbauen.

In Tk kann man auch Frames in Fenster oder auch andere Frames setzen um den Inhalt zu strukturieren.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten