私は、filedialogで開いた画像をフレームで表示しようとしています。私の現在のメソッドは、Step1のフレームを "image1path"で初期化し、それをユーザーが指定した "image2path"に更新したいと思います。私はこれをData.currentJPEG属性を通じて実行しようとしています。ユーザー定義の画像をtkinterフレームに追加するPythonの方法
- "ダミー"イメージで初期化しない方が良いでしょうか?
- これが正しければ、私のコメントアウトされた行の一番下の部分はなぜ戻りますか?Step1が文字列でない場合、 "'str'オブジェクトには '_bind'属性がありません。私はStep1がself.bindがstartPageで動くことを許可したものだと思った。これはフレーム内の画像を更新する正しい方法ではありませんか?
- ボーナス側の質問:開始ページの行でweight = 100からweight = 1に変更すると、開いている.jpgボタンの位置のスケールはどうしてですか?
このコード構造は、この方法は、私が使用しようとするhere
方法は、ボタンが押されたときに新しい関数が呼び出されるthis answerを、以下見出すことができる画像のサイズを変更here
を見出すことができますイメージを更新します。しかし、画像にはリサイズ機能も使用されているので、問題にぶつかっていると思います。あなたがしたいすべてがあなたのユーザーが手動でファイルを選択し、あなたのTkinterのGUIは、それを表示させることである場合
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()
これはうまくいきますが、ボタンを使って別のクラスのopenJPEGを実行する方法を示すことができますか?私の場合は、その開いているイメージボタンがstartPageに存在しますが、イメージはStep1フレームで開く必要があります。私はあなたが使用すると思います:command = Step1.openJPEGしかし、これはそうではないようです。私はまた、コントローラがフレームスイッチのために渡される必要があります。 – theMostVersatileSnake
共通の 'controller'クラスを使用して、異なるクラスのGUIの異なる部分間のやりとりの仕方を示すために、私の答えにあなたのコードを書き直したバージョンを追加しました。 – Josselin
私はこの構造をもう少し理解し始めています。 Step1の下で "self.controller = controller"について詳しく説明できますか?私はコントローラーが__init __(self、parent、controller)を使うだけで継承されたと考えました。あなたの助けを借りてありがとう! – theMostVersatileSnake