Bild wird nur im Hauptfenster, nicht im "neuen" Fenster geöffnet.

Fragen zu Tkinter.
Antworten
Fretschi
User
Beiträge: 1
Registriert: Mittwoch 14. Dezember 2022, 19:33

Hallo,

folgender Code sorgt dafür, dass das Bild nur im Hauptfenster nicht im geöffneten Fenster zu sehen ist.

Wäre dankbar für Hilfe :-)

Grüße

Code: Alles auswählen

from tkinter import *


def createNewWindow():
    newWindow = Toplevel(app)
    newWindow.geometry('500x500')
    canvas2 = Canvas(newWindow, width=500, height=500)
    canvas2.pack()
    img = PhotoImage(file="2_putafi.gif")
    canvas2.create_image(20, 20, anchor=NW, image=img)


app = Tk()
app.geometry('500x600')
buttonExample = Button(app,
                       text="Create new window",
                       command=createNewWindow)
buttonExample.pack()

canvas = Canvas(app, width=500, height=500)
canvas.pack()
img = PhotoImage(file="2_putafi.gif")
canvas.create_image(20, 20, anchor=NW, image=img)

app.mainloop()
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Fretschi: Python bekommt nicht mit wie lange ein Bild auf Tk-Seite benötigt wird und löscht das Bild, sobald das Objekt auf Python-Seite nicht mehr erreichbar ist. Also zumindest kann es ab da jederzeit abgeräumt werden. Die letzte Referenz aus Python-Sicht verschwindet mit Ende der Funktion.

Sonstige Anmerkungen zum Quelltext:

Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 140 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. Der Name soll dem Leser vermitteln was der Wert dahinter im Programm bedeutet, nicht zum rätseln zwingen.

Man nummeriert keine Namen. Dann will man sich entweder bessere Namen überlegen, oder gar keine Einzelnamen/-werte verwenden, sondern eine Datenstruktur. Oft eine Liste. Konkret macht die 2 bei `canvas2` aber auch gar keinen Sinn, denn das ist in der Funktion ja der einzige `Canvas`.

Alles was eine Funktion oder Methode ausser Konstanten benötigt wird als Argument(e) übergben. Die Funktion die neue Fenster erstellt braucht das `master`-Argument und das nicht einfach so aus dem ”Nichts” kommen, denn das ist keine Konstante. Daraus folgt, dass jede nicht-triviale GUI objektorientierte Programmierung (OOP) benötigt. Also man sollte vor GUI-Programmierung am besten schon mit Klassen vertraut sein, denn dafür braucht man die dann.

Man gibt keine `geometry()` vor wenn die sich aus dem Inhalt ergibt, denn dann kann es ja sein, dass das am Ende gar nicht passt. Der Code geht beispielsweise davon aus, dass etwa 100 Pixel ausreichen werden um einen Button darzustellen. Das hängt aber von Faktoren ab die man gar nicht weiss, beispielsweise der Bildschirmauflösung und der Schriftgrösse, die der Benutzer eingestellt hat.

Code: Alles auswählen

import tkinter as tk
from functools import partial


def create_new_window(master):
    canvas = tk.Canvas(tk.Toplevel(master), width=500, height=500)
    canvas.pack()
    image = tk.PhotoImage(file="2_putafi.gif")
    canvas.create_image(20, 20, anchor=tk.NW, image=image)
    canvas.image = image


def main():
    app = tk.Tk()
    tk.Button(
        app, text="Create new window", command=partial(create_new_window, app)
    ).pack()
    canvas = tk.Canvas(app, width=500, height=500)
    canvas.pack()
    image = tk.PhotoImage(file="2_putafi.gif")
    canvas.create_image(20, 20, anchor=tk.NW, image=image)
    app.mainloop()


if __name__ == "__main__":
    main()
Falls das Bild so ungefähr den Canvas füllt, würde man hier auch keinen Canvas verwenden, denn dem muss man ja auch eine Grösse vorgeben, was man sich sparen kann, wenn man das in ein `Label` packt, dessen Grösse sich automatisch nach dem enthaltenen Bild richtet. Und die Codewiederholung würde man besser herausziehen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten