2016-04-28 3 views
0

Ich bin ein Anfänger in Python, Tkinter. Ich habe einen Code geschrieben, der normalerweise ein Bild in einem Canvas anzeigen soll.Anzeigen eines Bildes in Python über Button und Canvas

Was passiert ist, dass der Hauptrahmen (gui) mit der Menüleiste angezeigt wird, wenn ich dann auf Bild laden klicke, verkleinert sich das GUI-Fenster (auf 100x100), aber nichts wird angezeigt.

Könnten Sie mir bitte erklären, warum das passiert, damit ich verstehen kann, wo der Fehler auftritt und wie Sie ihn korrigieren können?

# -*- coding:utf-8 -*- 
# Imports 
from tkinter import Tk, Menu, Canvas 
from PIL import Image, ImageTk 

# Function definitions 
def deleteImage(canvas): 
    canvas.delete("all") 
    return 

def loadImage(canvas, img): 
    filename = ImageTk.PhotoImage(img) 
    canvas.image = filename 
    canvas.create_image(0,0,anchor='nw',image=filename) 
    return 

def quitProgram(): 
    gui.destroy() 
# Main window 
gui = Tk() 

# Inside the main gui window 
#Creating an object containing an image 
# A canvas with borders that adapt to the image within it 
img = Image.open("fleur.jpg") 
canvas = Canvas(gui,height=img.size[0],width=img.size[0]) 
canvas.pack() 

# Menu bar 
menubar = Menu(gui) 
# Adding a cascade to the menu bar: 
filemenu = Menu(menubar, tearoff=0) 
menubar.add_cascade(label="Files", menu=filemenu) 
# Adding a load image button to the cascade menu "File" 
filemenu.add_command(label="Load an image", command=loadImage) 
# Adding a delete image button to the cascade menu "File" 
filemenu.add_command(label="Delete image", command=deleteImage) 
filemenu.add_separator() 
filemenu.add_command(label="Quit", command=quitProgram) 
menubar.add_separator() 
menubar.add_cascade(label="?") 

# Display the menu bar 
gui.config(menu=menubar) 
gui.mainloop() 

EDIT: Das zweite Problem ist, dass ich eine Leinwand und das Bild im Haupt gui Fenster erstellen möchten, und geben sie als Argumente für den Menütasten (siehe oben stehenden Code, wo img und Leinwand geschaffen getrennt von der Funktion loadImage). Das Einfügen von Klammern in die command=loadImage() verursachte ein Problem für sich.

Ein weiterer Punkt, der eine Frage in meinem Kopf aufwirft: In Bezug auf das erste Problem, das durch einen Verweis auf die filename=ImageTk.PhotoImage(img) gelöst wurde. Wäre es nicht sinnlos, einen Verweis innerhalb der Funktion zu behalten, da es sich ohnehin um eine lokale Variable handelt?

+0

Zum Hinzufügen eines Parameters zu Ihrem Befehl, überprüfen Sie bitte hier. http://stackoverflow.com/questions/6920302/how-to-pass-arguments-to-a-button-command-in-tkinter – Lafexlos

+0

Ja, obwohl nicht durch die erste Lösung. Ich musste die partielle from functools-Bibliothek verwenden, die so funktionierte: 'file menu.add_command (label =" Lade ein Bild ", command = partially (loadImage, canvas, img))' – Aetos

Antwort

1

Wie in der Seite PhotoImage von effbot angegeben, müssen Sie einen Verweis auf Ihr Bild behalten, um sicherzustellen, dass es nicht Müll gesammelt wird.

Sie müssen einen Verweis auf das Bildobjekt in Ihrem Python-Programm halten, entweder, indem sie in einer globalen Variablen zu speichern, oder indem es ein anderes Objekt zu befestigen.

Hinweis: Wenn ein Photobild Objekt Garbage Collection von Python (zB , wenn Sie von einer Funktion zurückzugeben, die ein Bild in einem lokalen Variable gespeichert), wird das Bild gelöscht, selbst wenn sie von einem angezeigt Seine Tkinter-Widget

Um dies zu vermeiden, muss das Programm einen zusätzlichen Verweis auf das Bildobjekt behalten. Ein einfacher Weg, dies zu tun ist, um das Bild zu einem Widget Attribut zuweisen, wie folgt aus:

Ihre loadImage() Methode wie folgt aussehen sollte.

def loadImage(): 
    img = Image.open("fleur.jpg") 
    filename = ImageTk.PhotoImage(img) 
    canvas = Canvas(gui,height=100,width=100) 
    canvas.image = filename # <--- keep reference of your image 
    canvas.create_image(0,0,anchor='nw',image=filename) 
    canvas.pack() 
+0

Danke für deine Antwort, es ist informativ, aber leider produziert es nicht das gewünschte Ergebnis. Jetzt wird das Bild von Anfang an geladen, was ich möchte, ist ein Bild zu laden, wenn ich auf den Button "Bild laden" klicke. – Aetos

+0

@Aetos Können Sie bitte überprüfen, ob Sie in der Datei 'file menu.add_command (..., command = loadImage)' neben Ihrem 'loadImage' eine Paranthese haben? Normalerweise sollte diese Zeile so aussehen. nicht 'file menu.add_command (..., command = loadImage())'. – Lafexlos

+0

Spot on :) jetzt werde ich den Thread bearbeiten, um ein paar Ergänzungen zu integrieren. – Aetos