2017-05-02 9 views
0

私は、filedialogで開いた画像をフレームで表示しようとしています。私の現在のメソッドは、Step1のフレームを "image1path"で初期化し、それをユーザーが指定した "image2path"に更新したいと思います。私はこれをData.currentJPEG属性を通じて実行しようとしています。ユーザー定義の画像をtkinterフレームに追加するPythonの方法

  1. "ダミー"イメージで初期化しない方が良いでしょうか?
  2. これが正しければ、私のコメントアウトされた行の一番下の部分はなぜ戻りますか?Step1が文字列でない場合、 "'str'オブジェクトには '_bind'属性がありません。私はStep1がself.bindがstartPageで動くことを許可したものだと思った。これはフレーム内の画像を更新する正しい方法ではありませんか?
  3. ボーナス側の質問:開始ページの行で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() 

答えて

0

は、あなただけのButtonCanvas必要です。

コード

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() 

あなた複数のクラス構造を維持したい場合は、あなたが通信するために(あなたのサブフレームでcontrollerと呼ばれる)あなたのGUIの根元部分のより有効に活用する必要があります異なるフレームの間。

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() 
+0

これはうまくいきますが、ボタンを使って別のクラスのopenJPEGを実行する方法を示すことができますか?私の場合は、その開いているイメージボタンがstartPageに存在しますが、イメージはStep1フレームで開く必要があります。私はあなたが使用すると思います:command = Step1.openJPEGしかし、これはそうではないようです。私はまた、コントローラがフレームスイッチのために渡される必要があります。 – theMostVersatileSnake

+0

共通の 'controller'クラスを使用して、異なるクラスのGUIの異なる部分間のやりとりの仕方を示すために、私の答えにあなたのコードを書き直したバージョンを追加しました。 – Josselin

+1

私はこの構造をもう少し理解し始めています。 Step1の下で "self.controller = controller"について詳しく説明できますか?私はコントローラーが__init __(self、parent、controller)を使うだけで継承されたと考えました。あなたの助けを借りてありがとう! – theMostVersatileSnake

関連する問題