我试图让一个框架显示一个通过filedialog打开的图像。我当前的方法使用“image1path”初始化Step1中的帧,然后我想将其更新为用户指定的某个“image2path”。我试图通过Data.currentJPEG属性执行此操作。
可以找到此代码结构here
可以通过这种方式调整图像大小here
我尝试使用的方法遵循this answer,其中按下按钮时会调用新函数来更新图像。但是,我认为我遇到了问题,因为我的图像也使用了调整大小功能。
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()
答案 0 :(得分:0)
如果你想做的只是让你的用户手动选择一个文件,然后让你的tkinter GUI显示它,你只需要Button
和Canvas
。
<强>代码强>:
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.image as mpimg
from tkinter import filedialog
import tkinter as tk
import os
class program(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# Create a button to load a jpg
self.button = tk.Button(self, text="Load image", command=self.openJPEG)
self.button.pack()
# Create a canvas on which to show the jpg
self.frame = tk.Frame(self)
self.frame.pack(fill=tk.BOTH, expand=1)
self.create_canvas()
def openJPEG(self):
# Display a dialog for the user to select a jpg file,
filePath = filedialog.askopenfilename(initialdir=os.getcwd(),
filetypes=(("JPEG",".jpg"),
("All Files","*.*")),
title="Open JPEG")
# Show the selected jpg on the canvas
img = mpimg.imread(filePath)
self.ax1.imshow(img)
self.canvas1.draw()
def create_canvas(self):
""" Add a canvas to plot images """
self.fig1 = Figure(frameon=False, figsize=(6, 4.5))
self.canvas1 = FigureCanvasTkAgg(self.fig1, master=self.frame)
self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=1)
self.ax1 = self.fig1.add_axes([0, 0, 1, 1])
self.ax1.axis('off')
# Run program
app = program()
app.mainloop()
如果您想保留多个类结构,则必须更好地利用GUI的根部分(在子帧中称为controller
)来进行不同的通信帧。请参阅以下代码以帮助您入门:
import os
import tkinter as tk
from PIL import Image, ImageTk
from tkinter import filedialog
# where opened file data with be stored
class Data():
# this sets initial values for the class attributes
def __init__(self):
self.currentJPEG=""
class program(tk.Tk):
def __init__(self, Data):
tk.Tk.__init__(self)
self.Data = Data
container = tk.Frame(self)
container.pack(fill="both", expand=True)
# 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")
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)
self.controller = controller
# button to open an image in Step 1,
button = tk.Button(self, text='Open .jpg File in new frame',
command= self.openJPEG)
button.grid(row=0, column=0, sticky='ew')
# add empty canvas
self.canvas = tk.Canvas(self,bg='black')
self.canvas.grid(row=1, column=0, sticky='nsew')
def openJPEG(self):
self.openJPEG
filePath = filedialog.askopenfilename(initialdir=os.getcwd(),
filetypes=(("JPEG",".jpg"),
("All Files","*.*")),
title="Open JPEG")
# Update the image in Step1 frame
self.controller.Data.currentJPEG = filePath
self.controller.frames[Step1].show_current_image()
# Show Step1 frame
self.controller.show_frame(Step1)
class Step1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
# Frame2, this is where image preview is
frame2 = tk.Frame(self, bg="grey")
frame2.grid(row=0, column=1, sticky='nsew')
# initialize where image preview will be in frame2
self.canvas = tk.Canvas(frame2,bg='black')
self.canvas.grid(row=0, column=1, sticky='nsew')
def show_current_image(self):
self.image = Image.open(self.controller.Data.currentJPEG)
self.background_image = ImageTk.PhotoImage(self.image)
self.canvas.create_image(0, 0, anchor="nw", image=self.background_image,
tags="bg")
# initalize data class
Data = Data()
# run program
app = program(Data)
app.mainloop()