Hallo liebe Python Gemeinde,
ich habe in kleines Problem bei meiner Erstellung einer GUI für ein Projekt. Leider bin ich auch nur ein Anfänger mit ein paar Grundkenntnissen.
Und zwar habe ich das Problem das ich einen Dateinamen aufrufe mit dem Code: os.path.basename. Dieser wird in die Variable Name gespeichert.
Jetzt möchte ich diesen Name aber in die GUI einfügen, sodass der Name über einem Bild steht zum Beispiel. Nur das funktioniert einfach nicht.
Ich habe auch schon im Internet viel nachgeschaut aber nie was passendes gefunden, dass das Problem gelöst hat.
Ich hoffe es kann mir einer bei dem Problem helfen.
Vielen Dank schon mal im Voraus
GUI-Problem mit Dateinamen
- __blackjack__
- User
- Beiträge: 14033
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Tschibasi: Also eigentlich ist das ja nur ein GUI-Problem. Mit Dateinamen hat das nix zu tun, denn wo die Zeichenkette her kommt, die über dem Bild angezeigt werden soll, ist letztlich ja egal.
Über welches GUI-Rahmenwerk reden wir eigentlich? Und beinhaltet das „schon viel im Internet nachgeschaut“ auch die Dokumentation vom verwendeten GUI-Rahmenwerk?
Über welches GUI-Rahmenwerk reden wir eigentlich? Und beinhaltet das „schon viel im Internet nachgeschaut“ auch die Dokumentation vom verwendeten GUI-Rahmenwerk?
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Ich habe es mit Tkinter gemacht und habe viel im Internet dazu auch gelesen. Aber ich bringe es einfach nicht hin.
Das ist der Code dazu:
from tkinter import *
from tkinter import ttk
import os.path
import sys
fenster=Tk()
fenster.wm_title("Cocktailmaschine powered by Tschibasi")
fenster.config(background="#E0FFFF")
fenster.geometry("1024x600")
Überschrift= Label(text="Cocktailname: ", bg="light cyan", fg="black")
Überschrift.place(x=75,y=50)
Name=os.path.basename(r"#Pfad von meiner Datei")
print (""+str(Name))
logo = PhotoImage(file="#Pfad von meiner Datei")
w=Label(fenster,
compound=LEFT,
image=logo).pack(side="left")
fenster.mainloop()
Das print habe ich nur zum Testen eingefügt um zu schauen ob der Name der Datei auch in die Variable gespeichert wird.
Das ist der Code dazu:
from tkinter import *
from tkinter import ttk
import os.path
import sys
fenster=Tk()
fenster.wm_title("Cocktailmaschine powered by Tschibasi")
fenster.config(background="#E0FFFF")
fenster.geometry("1024x600")
Überschrift= Label(text="Cocktailname: ", bg="light cyan", fg="black")
Überschrift.place(x=75,y=50)
Name=os.path.basename(r"#Pfad von meiner Datei")
print (""+str(Name))
logo = PhotoImage(file="#Pfad von meiner Datei")
w=Label(fenster,
compound=LEFT,
image=logo).pack(side="left")
fenster.mainloop()
Das print habe ich nur zum Testen eingefügt um zu schauen ob der Name der Datei auch in die Variable gespeichert wird.
- __blackjack__
- User
- Beiträge: 14033
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Tschibasi: Naja, Du sagst ja auch nirgends was als Text neben dem Bild in dem `Label` angezeigt werden soll. Wenn man das `compound`-Argument übergibt, dann muss man ein Bild *und* einen Text für das Label angeben. Der Rechner kann ja nicht hellsehen oder gedankenlesen. 
Weitere Anmerkungen zum Code: Sternchen-Importe solltest Du Dir gar nicht erst angewöhnen. Der von `tkinter` holt Dir fast 190 Namen in das Modul von denen Du nur einen ganz kleinen Bruchteil tatsächlich verwendest. So etwas wird schnell unübersichtlich und kann auch zu Namenskollisionen führen.
`ttk` und `sys` werden importiert aber nicht verwendet.
Bei `os.path` muss man nur `os` importieren. `path` ist ein normales Attribut dieses Moduls.
Statt `wm_title()` würde ich nur `title()` verwenden. Das ist zwar letztendlich die gleiche Methode, aber der `wm_`-Präfix bringt einem Leser hier keinen Mehrwert. Das ist eher ein Tk-Interna was hier unnötigerweise nach aussen sichtbar ist.
`place()` ist so gar keine gute Idee, die noch schlechter wird wenn man auch noch andere Layoutmanager im gleichen Containerwidget verwendet. Ich habe hier lokal ein Beispielbild verwendet das so gross ist, das die Überschrift dahinter verschwindet, also nicht sichtbar ist. Vergiss `place()` am besten gleich wieder.
Namenskonvention in Python ist klein_mit_unterstrichen für alles ausser Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). `Name` sollte also `name` heissen.
Umlaute würde ich in Namen nicht verwenden, auch wenn Python damit umgehen kann, gibt es diverse Werkzeuge die darüber immer noch stolpern. Zum Beispiel statische Analyse für Tests oder Autovervollständigung.
Abkürzungen sollte man nur verwenden wenn sie allgemein bekannt sind, oder wenn der Gültigkeitsbereich des Namens sehr klein ist. Beispielwsweise in „comprehensions“ oder bei ``lambda``-Ausdrücken. Das `w` ist eindeutig zu kurz und nichtssagend. Und es ist unnötig weil es sowieso nur an den Wert `None` gebunden wird. Das ist nämlich der Rückgabewert der `pack()`-Methode. `Überschrift` wird auch nicht wirklich benötigt.
Redundanz in Code und Daten sollte man vermeiden. Der Pfad zu dem Bild sollte nicht mehrfach im Quelltext stehen. Das erhöht die Gefahr das beide Werte nicht exakt gleich sind. Entweder weil man sich beim ersten mal schon vertippt hat, oder weil man einen Fehler macht wenn man diesen Wert irgendwann einmal ändert.
Das `print()`-Argument ist ziemlich schräg. `Name` ist bereits eine Zeichenkette, der `str()`-Aufruf bewirkt also gar nichts. Und es bringt auch nichts wenn man eine leere Zeichenkette mit einer anderen Zeichenkette verbindet. Das ist also würde man 0 zu einer Zahl addieren — da kommt nur wieder die gleiche Zahl bei heraus. Was war denn die Absicht hinter diesen beiden Operationen?
Falls ein Argument bei `print()` keine Zeichenkette sein sollte, sorgt zudem `print()` selbst schon dafür das der Wert in einer Zeichenkette umgewandelt wird.
Zwischenstand:
Noch eine kleine Warnung: Defaultwert für `side` bei `pack()` ist `tk.TOP`. Ich habe das hier mal so gelassen, aber es kann zu schwierig vorhersehbaren Layouts kommen wenn man die Richtungen/Seiten bei `pack()` innerhalb des gleichen Containerwidgets mischt.

Weitere Anmerkungen zum Code: Sternchen-Importe solltest Du Dir gar nicht erst angewöhnen. Der von `tkinter` holt Dir fast 190 Namen in das Modul von denen Du nur einen ganz kleinen Bruchteil tatsächlich verwendest. So etwas wird schnell unübersichtlich und kann auch zu Namenskollisionen führen.
`ttk` und `sys` werden importiert aber nicht verwendet.
Bei `os.path` muss man nur `os` importieren. `path` ist ein normales Attribut dieses Moduls.
Statt `wm_title()` würde ich nur `title()` verwenden. Das ist zwar letztendlich die gleiche Methode, aber der `wm_`-Präfix bringt einem Leser hier keinen Mehrwert. Das ist eher ein Tk-Interna was hier unnötigerweise nach aussen sichtbar ist.
`place()` ist so gar keine gute Idee, die noch schlechter wird wenn man auch noch andere Layoutmanager im gleichen Containerwidget verwendet. Ich habe hier lokal ein Beispielbild verwendet das so gross ist, das die Überschrift dahinter verschwindet, also nicht sichtbar ist. Vergiss `place()` am besten gleich wieder.
Namenskonvention in Python ist klein_mit_unterstrichen für alles ausser Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). `Name` sollte also `name` heissen.
Umlaute würde ich in Namen nicht verwenden, auch wenn Python damit umgehen kann, gibt es diverse Werkzeuge die darüber immer noch stolpern. Zum Beispiel statische Analyse für Tests oder Autovervollständigung.
Abkürzungen sollte man nur verwenden wenn sie allgemein bekannt sind, oder wenn der Gültigkeitsbereich des Namens sehr klein ist. Beispielwsweise in „comprehensions“ oder bei ``lambda``-Ausdrücken. Das `w` ist eindeutig zu kurz und nichtssagend. Und es ist unnötig weil es sowieso nur an den Wert `None` gebunden wird. Das ist nämlich der Rückgabewert der `pack()`-Methode. `Überschrift` wird auch nicht wirklich benötigt.
Redundanz in Code und Daten sollte man vermeiden. Der Pfad zu dem Bild sollte nicht mehrfach im Quelltext stehen. Das erhöht die Gefahr das beide Werte nicht exakt gleich sind. Entweder weil man sich beim ersten mal schon vertippt hat, oder weil man einen Fehler macht wenn man diesen Wert irgendwann einmal ändert.
Das `print()`-Argument ist ziemlich schräg. `Name` ist bereits eine Zeichenkette, der `str()`-Aufruf bewirkt also gar nichts. Und es bringt auch nichts wenn man eine leere Zeichenkette mit einer anderen Zeichenkette verbindet. Das ist also würde man 0 zu einer Zahl addieren — da kommt nur wieder die gleiche Zahl bei heraus. Was war denn die Absicht hinter diesen beiden Operationen?
Falls ein Argument bei `print()` keine Zeichenkette sein sollte, sorgt zudem `print()` selbst schon dafür das der Wert in einer Zeichenkette umgewandelt wird.
Zwischenstand:
Code: Alles auswählen
#!/usr/bin/env python3
import tkinter as tk
import os
def main():
root = tk.Tk()
root.title('Cocktailmaschine powered by Tschibasi')
root.config(background='#E0FFFF')
root.geometry('1024x600')
tk.Label(text='Cocktailname: ', bg='light cyan', fg='black').pack()
logo_path = r'test.png'
name = os.path.basename(logo_path)
print(name)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
root, compound=tk.LEFT, text=name, image=logo
).pack(side=tk.LEFT)
root.mainloop()
if __name__ == '__main__':
main()
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Hey
Danke für die Anmerkungen und für die Verbesserungen.
Zu deiner Frage was die beiden Operationen machen sollen:
Ich will einfach nur ein Bild aufrufen und kommentieren was auf dem Bild zu sehen ist.
Ich schreibe nähmlich diesen Code für mein Projekt in dem ich eine Cocktailmaschine baue und diese mit einem Raspberry steuere. Zudem wollte ich einfach eine Oberfläche programmieren in der ich alles Aufrufen kann.
Danke für die Anmerkungen und für die Verbesserungen.
Zu deiner Frage was die beiden Operationen machen sollen:
Ich will einfach nur ein Bild aufrufen und kommentieren was auf dem Bild zu sehen ist.
Ich schreibe nähmlich diesen Code für mein Projekt in dem ich eine Cocktailmaschine baue und diese mit einem Raspberry steuere. Zudem wollte ich einfach eine Oberfläche programmieren in der ich alles Aufrufen kann.
Hey jetzt habe ich nochmals alles überarbeitet und habe nun ein anderes Problem.
Es kommt jetzt nur immer grauer Hintergrund aber das Bild wird nicht geladen.
[code]
import tkinter as tk
import os
import sys
def bild_screwdriver():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
def bild_touchdown():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
def bild_sexonthebeach():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
def bild_tequilasunrise():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
fenster=tk.Tk()
fenster.title("Cocktailmaschine powered by Tschibasi")
fenster.config(background="#E0FFFF")
fenster.geometry("800x480")
titel=tk.Label(text="Cocktail: ", bg="light cyan", fg="black")
titel.grid(row=0, column=0)
titel.config(font="Arial 20")
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
button_screwdriver=tk.Button(fenster, text="Screwdriver", command=bild_screwdriver)
button_screwdriver.grid(row=0, column=1)
button_screwdriver.config(width=20)
button_touchdown=tk.Button(fenster, text="Touchdown", command=bild_touchdown)
button_touchdown.grid(row=0, column=2)
button_touchdown.config(width=20)
button_sexonthebeach=tk.Button(fenster, text="Sex on the Beach", command=bild_sexonthebeach)
button_sexonthebeach.grid(row=1, column=2, padx=5)
button_sexonthebeach.config(width=20)
button_tequilasunrise=tk.Button(fenster,text="Tequila Sunrise", command=bild_tequilasunrise)
button_tequilasunrise.grid(row=1, column=1)
button_tequilasunrise.config(width=20)
button_schließen=tk.Button(fenster, text="Schließen", command=fenster.destroy)
button_schließen.grid(row=5, column=5)
button_schließen.config(width=20)
fenster.mainloop()
[/code]
Kann mir einer sagen warum sie nicht geladen werden?
Alle Pfade sind richtig im Programm eingegeben!
Danke schon mal
Es kommt jetzt nur immer grauer Hintergrund aber das Bild wird nicht geladen.
[code]
import tkinter as tk
import os
import sys
def bild_screwdriver():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
def bild_touchdown():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
def bild_sexonthebeach():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
def bild_tequilasunrise():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
fenster=tk.Tk()
fenster.title("Cocktailmaschine powered by Tschibasi")
fenster.config(background="#E0FFFF")
fenster.geometry("800x480")
titel=tk.Label(text="Cocktail: ", bg="light cyan", fg="black")
titel.grid(row=0, column=0)
titel.config(font="Arial 20")
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
tk.Label(
fenster, compound=tk.BOTTOM, text=name, image=logo, font="Arial 16",
).grid(row=1, column=0)
button_screwdriver=tk.Button(fenster, text="Screwdriver", command=bild_screwdriver)
button_screwdriver.grid(row=0, column=1)
button_screwdriver.config(width=20)
button_touchdown=tk.Button(fenster, text="Touchdown", command=bild_touchdown)
button_touchdown.grid(row=0, column=2)
button_touchdown.config(width=20)
button_sexonthebeach=tk.Button(fenster, text="Sex on the Beach", command=bild_sexonthebeach)
button_sexonthebeach.grid(row=1, column=2, padx=5)
button_sexonthebeach.config(width=20)
button_tequilasunrise=tk.Button(fenster,text="Tequila Sunrise", command=bild_tequilasunrise)
button_tequilasunrise.grid(row=1, column=1)
button_tequilasunrise.config(width=20)
button_schließen=tk.Button(fenster, text="Schließen", command=fenster.destroy)
button_schließen.grid(row=5, column=5)
button_schließen.config(width=20)
fenster.mainloop()
[/code]
Kann mir einer sagen warum sie nicht geladen werden?
Alle Pfade sind richtig im Programm eingegeben!
Danke schon mal
Die vier Funktionen, die alle das selbe machen, kann man auch in einer mit Parameter schreiben. Alle Elemente sollten beim Erstellen des Fensters schon miterstellt werden und später nur noch das Bild im Label geändert werden. Um Bilder anzuzeigen, muß immer noch eine Referenz auf das PhotoImage-Objekt gemerkt werden, am einfachsten als Attribut auf dem Label:
Code: Alles auswählen
logo = tk.PhotoImage(file=logo_path)
bild_label['image'] = logo
bild_label.image = logo
@Sirius3
Wie meinst du das mit einer mit Parameter?
Das heißt ich schreibe einfach einmal eine "def bild_erstellen" zum beispiel die jeder Button ausführt?
Und wie kann dann welchen Button sein jeweiliges Bild zuweisen?
Wie meinst du das mit einer mit Parameter?
Das heißt ich schreibe einfach einmal eine "def bild_erstellen" zum beispiel die jeder Button ausführt?
Und wie kann dann welchen Button sein jeweiliges Bild zuweisen?
- __blackjack__
- User
- Beiträge: 14033
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@Tschibasi: Schau Dir mal `functools.partial()` an.
Wobei auch wichtig ist was Sirius3 über die Erstellung von den `Label`-Objekten gesagt hat. Das erstellt man *einmal* am Anfang, zum Beispiel ohne Text und Bild oder mit einem Platzhalter und dann ändert man auf Knopfdruck nur noch den Text und das Bild und erstellt das nicht jedes mal neu. Das verbraucht sonst immer mehr Speicher und macht das Programm immer langsamer, weil jedes mal alle `Label` übereinandergezeichnet werden müssen, obwohl man nur das letzte, obere am Ende sieht.
Wobei auch wichtig ist was Sirius3 über die Erstellung von den `Label`-Objekten gesagt hat. Das erstellt man *einmal* am Anfang, zum Beispiel ohne Text und Bild oder mit einem Platzhalter und dann ändert man auf Knopfdruck nur noch den Text und das Bild und erstellt das nicht jedes mal neu. Das verbraucht sonst immer mehr Speicher und macht das Programm immer langsamer, weil jedes mal alle `Label` übereinandergezeichnet werden müssen, obwohl man nur das letzte, obere am Ende sieht.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Könnte jemand vielleicht ein Beispiel mit diesem functools.partial einfügen und ein kleine Erklärung dazu schreiben?
Irgendwie steig ich nicht so ganz dahinter, wie ich dieses Tool hier anwenden kann.
Danke für die Verbesserung mit dem Label. Ich habe es jetzt nochmal ein bisschen umgeschrieben und nur ein Label eingefügt. Nur weiß ich jetzt halt nicht wie ich das mit der Verbindung zwischen Bildpfad, Button und dem Label machen soll.
Zwischenstand:
Ich habe nur eins der def´s eingefügt da es ja eigentlich immer das selbe ist und dort wahrscheinlich das Problem bzw. die Lösung meines Problems ist.
Vielen Dank
Irgendwie steig ich nicht so ganz dahinter, wie ich dieses Tool hier anwenden kann.
Danke für die Verbesserung mit dem Label. Ich habe es jetzt nochmal ein bisschen umgeschrieben und nur ein Label eingefügt. Nur weiß ich jetzt halt nicht wie ich das mit der Verbindung zwischen Bildpfad, Button und dem Label machen soll.
Zwischenstand:
Code: Alles auswählen
echo
import tkinter as tk
import os
def bild_screwdriver():
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
fenster=tk.Tk()
fenster.title("Cocktailmaschine powered by Tschibasi")
fenster.config(background="#E0FFFF")
fenster.geometry("800x480")
rechte_seite=tk.Frame(fenster, width=200,height=430, bg="lemon chiffon")
rechte_seite.grid(row=0,column=0, pady=25,padx=5)
linke_seite=tk.Frame(fenster, width=575, height=430, bg="salmon")
linke_seite.grid(row=0,column=1, pady=25, padx=10)
titel_rechts=tk.Label(rechte_seite, text="Cocktail: ", bg="lemon chiffon")
titel_rechts.grid(row=0, column=0)
titel_rechts.config(font="Arial 20")
logo_path = r"Mein Pfad"
name = os.path.basename(logo_path)
logo = tk.PhotoImage(file=logo_path)
platzhalter=tk.Label(rechte_seite, compound=tk.BOTTOM,text=name, image=logo, bg="lemon chiffon")
platzhalter.grid(row=1, column=0)
platzhalter.config(font="Arial 16")
button_screwdriver=tk.Button(linke_seite, text="Screwdriver", command=bild_screwdriver)
button_screwdriver.grid(row=0, column=1, pady=5, padx=5)
button_screwdriver.config(width=20)
button_touchdown=tk.Button(linke_seite, text="Touchdown", command=bild_touchdown)
button_touchdown.grid(row=0, column=2)
button_touchdown.config(width=20)
button_sexonthebeach=tk.Button(linke_seite, text="Sex on the Beach", command=bild_sexonthebeach)
button_sexonthebeach.grid(row=1, column=2)
button_sexonthebeach.config(width=20)
button_tequilasunrise=tk.Button(linke_seite,text="Tequila Sunrise", command=bild_tequilasunrise)
button_tequilasunrise.grid(row=1, column=1)
button_tequilasunrise.config(width=20)
button_schließen=tk.Button(linke_seite, text="Schließen", command=fenster.destroy)
button_schließen.grid(row=5, column=5)
button_schließen.config(width=20)
fenster.mainloop()
;
Vielen Dank