pyimage2 doesn't exist

Fragen zu Tkinter.
Antworten
cbesi
User
Beiträge: 41
Registriert: Dienstag 11. August 2020, 22:04

Hallo,

ich habe mich dran versucht mir eine Klasse zu bauen welche mir in meinem Programm weitere Fenster nach einem gleichen Schema erstellen soll.
Leider scheitere ich am Logo, Label etc. funktionieren.

Ich bekomme immer beim Aufruf des 2. Fensters die Meldung pyimage2 doesn't exist.

Beim googlen habe ich gefunden das es irgendwas damit auf sich hat, das ich TK nur einmal initialisieren kann , und tk.Toplevel nutzen muss.
Ich checke es leider nicht.

Hier mein Klasse:

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk as ttk
#import ttkbootstrap as ttk
from tkinter.messagebox import showinfo
import tkinter.font as font
from tkinter import font as tkFont
from PIL import ImageTk, Image



#Mainwindow

class App(tk.Tk):
  def __init__(self,windowname,labelname,fullscreen):
    super().__init__()

    # configure the root window
    self.title(windowname)
    self.geometry('800x600')
    if fullscreen == "true":
        self.attributes('-fullscreen', True)
    self.bind("<Escape>", self.quitFullScreen)
    self.bind("<F11>", self.toggleFullScreen)

    # label
    myfontlabel = font.Font(family='Helvetica')
    self.label = ttk.Label(self, text=labelname, background='darkgray' )
    self.label['font'] = myfontlabel
    self.label.place(x=1, y=1, width=5000, height=78)

    # load picture
    # Read image
    img = Image.open("Logo.png")
    self.bild = ImageTk.PhotoImage(img,self)
    self.label1 = ttk.Label(self, image=self.bild)
    # Position image
    #self.label1.place(x= 1500, y = 1)
    self.label1.pack(anchor="ne")

  def toggleFullScreen(self, event):
    self.fullScreenState = not self.fullScreenState
    self.attributes("-fullscreen", self.fullScreenState)

  def quitFullScreen(self, event):
    self.fullScreenState = False
    self.attributes("-fullscreen", self.fullScreenState)

app = App(Testapp","Testbezeichnung","true")


app.mainloop()

Wenn ich anstelle

Code: Alles auswählen

class App(tk.Toplevel):
einsetze funktioniert es im Grunde, aber es öffnen Sich beim Start immer noch ein weiteres Fenster (Standardfenster TK).

(Im Codebeispiel meiner Klasse wird das 2. Fenster nicht aufgerufen, dies mache ich bei klick auf einen Button.)
cbesi
User
Beiträge: 41
Registriert: Dienstag 11. August 2020, 22:04

Es scheint nach weiterem googlen, habe ich es verstanden.

Mein Hauptfenster = tk.TK meine weiteren Fenster tk.Toplevel ?

Habe ein Beispiel beim googeln, gefunden und aufgegriffen:

Für weitere Fenster habe ich mir nun noch eine Klasse zugefügt:

Code: Alles auswählen


class Window(tk.Toplevel):
    def __init__(self):
        super().__init__()

        self.geometry('300x100')
        self.title('Toplevel Window')

        ttk.Button(self,
                text='Close',
                command=self.destroy).pack(expand=True)
                
mal sehen ob das nun auch funktioniert wenn ich mir wieder das Logo lade ;-)
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@cbesi: Bei Ausnahmen nicht irgendwie umschreiben was das war, sondern am besten den kompletten Traceback 1:1 zeigen. Dann sieht man die konkrete Ausnahme, wo genau die im Code auftritt, und auch die Aufrufhierarchie die zu diesem Punkt im Programm geführt hat.

Der gezeigte Quelltext kompiliert nicht, weil da ein Syntaxfehler drin ist. Beim erstellen des `App`-Objekts fehlen die führenden Anführungszeichen der Zeichenkette die als erstes Argument übergeben wird.

Der Code der das `App`-Exemplar erstellt sollte auch in einer Funktion stehen.

Eingerückt wird per Konvention vier Leerzeichen pro Ebene und nicht nur zwei.

``as`` bei importen ist zum umbenennen. Weder bei `ttk` noch bei `font` wird irgendetwas umbenannt.

`tkFont` und `showinfo()` werden importiert, aber nirgends verwendet. `tkFont` ist zudem das gleiche Objekt das auch schon unter dem Namen `font` importiert wurde. Letztlich wird das `tkinter.font.Font`-Objekt welches da erstellt wird, auch nicht wirklich sinnvoll verwendet. Man könnte das auch einfach als Zeichenkette angeben. Und auch schon beim erstellen des `Label`-Objekts und nicht extra gleich in der nächsten Anweisung nach dem erstellen.

Die Fenstergrösse sollte man nicht absolut und hart vorgeben. Die ergibt sich aus dem Fensterinhalt.

`fullscreen` ist ein Wahrheitswert, da übergibt man nicht die Zeichenkette "true" für „wahr“ und irgendetwas beliebiges anderes für „unwahr“, sondern einen Wahrheitswert `True` oder `False`. Und gegen den braucht man dann auch nicht zu testen, sondern gibt den einfach so wie er ist an den `attributes()`-Aufruf weiter.

Namen von allem ausser Klassen und Konstanten werden klein_mit_unterstrichen geschrieben und nicht mixedCase.

Was ausserhalb der `__init__()` nicht mehr gebraucht wird, sollte man nicht an ein Attribut binden. Allerdings sollten alle Attribute eines Objekts nach abarbeiten der `__init__()`-Methode existieren. Die ist dazu da das Objekt in einem benutzbaren, initialisierten Zustand zu hinterlassen. `toggleFullScreen()` ist aber kaputt, weil das in ein `AttributeError` läuft, wenn man vorher nicht `quitFullScreen()` aufgerufen hat.

Das Attribut `fullScreenState` ist aber letztlich überflüssig, weil man sich den aktuellen Zustand nicht redundant selbst noch mal merken muss, sondern per `attributes()` auch einfach wieder abfragen kann.

Das zweite Argument bei `ImageTk.PhotoImage()` ist unsinnig. Das wird einfach ignoriert wenn das erste Argument kein „mode string“ war. Wäre es das gewesen, dann ist `self` — ein Fenster — kein sinnvoller Wert für ein Argument das die Bildgrösse angeben soll.

Für Zeichenketten die eine besondere Bedeutung haben und als Konstanten im `tkinter`-Modul definiert sind, würde ich diese Konstanten verwenden.

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
from tkinter import ttk

from PIL import Image, ImageTk


class App(tk.Tk):
    def __init__(self, title, label_text, fullscreen):
        super().__init__()
        self.title(title)
        self.attributes("-fullscreen", fullscreen)
        self.bind("<Escape>", self.quit_fullscreen)
        self.bind("<F11>", self.toggle_fullscreen)

        ttk.Label(
            self, text=label_text, background="darkgray", font="Helvetica"
        ).place(x=1, y=1, width=5000, height=78)

        self.bild = ImageTk.PhotoImage(Image.open("Logo.png"))
        ttk.Label(self, image=self.bild).pack(anchor=tk.NE)

    def toggle_fullscreen(self, _event=None):
        self.attributes("-fullscreen", not self.attributes("-fullscreen"))

    def quit_fullscreen(self, _event=None):
        self.attributes("-fullscreen", False)


def main():
    app = App("Testapp", "Testbezeichnung", True)
    app.mainloop()


if __name__ == "__main__":
    main()

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
cbesi
User
Beiträge: 41
Registriert: Dienstag 11. August 2020, 22:04

Danke blackjack... wenn du das so schreibst sieht es so einfach aus :-) wenn man es aber selber versucht, steht man sich oft selber im Weg. Die Hürden sind dann doch größer als man meint.
Super ist deine ausführliche Beschreibung, damit man es beim nächsten mal auch besser machen kann.
Antworten