Ich versuche, ein Bild anzuzeigen, ein Bild, das durch filialialog geöffnet ist. Meine aktuelle Methode initialisiert den Frame in Step1 mit "image1path", und dann möchte ich ihn auf einen vom Benutzer angegebenen "image2path" updaten. Ich versuche dies über das Attribut Data.currentJPEG zu erreichen.Pythonic Weg, um benutzerdefinierte Bild in Tkinter Rahmen hinzufügen
- Gibt es eine bessere Möglichkeit, die nicht mit einem "Dummy" Image zu initialisieren?
- Wenn dies der richtige Weg ist, warum kommen meine auskommentierten Zeilen unten zurück: "'str' Objekt hat kein Attribut '_bind'", wenn Step1 keine Zeichenkette ist. Ich dachte Step1 war, was es ermöglichte, dass self.bind auf der startPage arbeitete. Ist das nicht die richtige Methode, um das Bild im Bild zu aktualisieren?
- Bonus Seite Frage: wenn ich Gewicht = 100 zu Gewicht = 1 in den Start-Seitenzeilen ändern, warum skaliert die Open .jpg Taste überhaupt?
Dieser Code kann Struktur here
Ändern der Größe eines Bildes auf diese Weise gefunden zu verwenden, können here
Die Methode, die ich versuchen, folgt gefunden werden this answer, wo eine neue Funktion, die aufgerufen wird, wenn die Taste gedrückt wird Das aktualisiert das Bild. Ich glaube jedoch, dass ich auf Probleme stoße, weil mein Bild auch die Größenänderungsfunktion verwendet.
import os
import tkinter as tk
from PIL import Image, ImageTk
from tkinter import filedialog
image1path='mainGraphic.jpg'
cwd = os.getcwd()
# where opened file data with be stored
class Data():
# this sets initial values for the class attributes
def __init__(self):
self.currentJPEG=image1path
class program(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
self.title('program name')
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
# frames are laid ontop of each other, startPage shown first
self.frames = {}
for Frame in (StartPage, Step1):
frame = Frame(container, self)
self.frames[Frame] = frame
frame.grid(row = 0, column = 0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)
self.show_frame(StartPage)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
# scale rows and columns (make button scaling negligible)
self.rowconfigure(0,weight=0)
self.rowconfigure(1,weight=100) #bonus question refers to these 2 lines
self.columnconfigure(0,weight=100)
# button to open an image in Step 1,
# must pass program so app.showframe is available,
# must pass Step1 so the image attributes are available?
button = tk.Button(self, text='Open .jpg File in new frame',
command=lambda: Step1.openJPEG(program))
button.grid(row=0, column=0, sticky='ew')
# add the main graphic
self.canvas = tk.Canvas(self,bg='black')
self.canvas.grid(row=1, column=0, sticky='nsew')
self.img_copy = Image.open(image1path)
self.image = None #this is overriden every time the image is redrawn so there is no need to make it yet
self.bind("<Configure>",self.resizeImage)
def resizeImage(self,event):
origin = (0,0)
size = (event.width, event.height)
if self.bbox("bg") != origin + size:
self.canvas.delete("bg")
self.image = self.img_copy.resize(size)
self.background_image = ImageTk.PhotoImage(self.image)
self.canvas.create_image(*origin,anchor="nw",image=self.background_image,tags="bg")
self.canvas.tag_lower("bg","all")
class Step1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# give even weight to each subframe
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=100)
self.columnconfigure(1, weight=100)
# Frame1, this is on the left and empty
frame1 = tk.Frame(self, bg="grey")
frame1.grid(row=0, column=0, sticky='nsew')
# Frame2, this is where image preview is
frame2 = tk.Frame(self, bg="grey")
frame2.grid(row=0, column=1, sticky='nsew')
# scale rows and columns with equal weight
frame2.rowconfigure(0,weight=1)
frame2.columnconfigure(0,weight=100)
frame2.columnconfigure(1,weight=100)
# initialize where image preview will be in frame2
self.canvas = tk.Canvas(frame2,bg='black')
self.canvas.grid(row=0, column=1, sticky='nsew')
self.img_copy = Image.open(Data.currentJPEG)
self.image = None
self.bind("<Configure>",self.resizeImage)
def resizeImage(self,event):
origin = (0,0)
size = (event.width, event.height) # these need to get height/width of their frame, not Step1
if self.bbox("bg") != origin + size:
self.canvas.delete("bg")
self.image = self.img_copy.resize(size)
self.background_image = ImageTk.PhotoImage(self.image)
self.canvas.create_image(*origin,anchor="nw",image=self.background_image,tags="bg")
self.canvas.tag_lower("bg","all")
# update the image in frame2 using opened jpeg image
def openJPEG(program):
filePath = filedialog.askopenfilename(initialdir=cwd,
filetypes=(("JPEG",".jpg"),("All Files","*.*")),
title="Open JPEG")
try:
with open(filePath) as image: #***need a better 'try' statement for only jpeg is opened'
app.show_frame(Step1)
except:
print('could not open image')
return
## update image preview from mainGraphic to opened JPEG; these lines aren't working
Data.currentJPEG=filePath
#Step1.img_copy = Image.open(Data.currentJPEG)
#Step1.image = None
#Step1.bind("<Configure>",Step1.resizeImage)
# initalize data class
Data=Data()
# run program
app = program()
Das funktioniert gut, aber können Sie zeigen, wie Sie eine Taste verwenden, um openJPEG aus einer anderen Klasse auszuführen? In meinem Fall ist diese Schaltfläche für das Öffnen von Bildern auf der Startseite vorhanden, aber das Bild sollte im Rahmen von Schritt 1 geöffnet werden. Ich würde denken, Sie würden verwenden: command = Step1.openJPEG, aber das scheint nicht der Fall zu sein. Ich brauche auch Controller für den Frame-Switch übergeben werden. – theMostVersatileSnake
Ich habe meiner Antwort eine überarbeitete Version Ihres Codes hinzugefügt, um Ihnen zu zeigen, wie Sie zwischen verschiedenen Teilen Ihrer GUI in verschiedenen Klassen kommunizieren können, indem Sie eine gemeinsame "Controller" -Klasse verwenden. – Josselin
Ich beginne, diese Struktur ein bisschen besser zu verstehen. Können Sie unter Schritt 1 "self.controller = controller" näher erläutern? Ich dachte Controller wurde vererbt nur mit __init __ (selbst, Eltern, Controller). Vielen Dank für Ihre Hilfe! – theMostVersatileSnake