0

I'm creating a multiframe tkinter application and I want user input on one frame subclass to update an image displayed on another frame subclass widget.

The only method capable of updating an image I've found is through .config(). I understand loose or tight coupling is the answer, I'm just having trouble executing.

Goal: Change Button image from another subclass


from tkinter import *

class GUI(Tk):  # Main Tk SubClass
    def __init__(self, *args, **kwargs):
        Tk.__init__(self, *args, **kwargs)

        # Photo Instances
        self.PI1= PhotoImage(file='Image1.png')
        self.PI2= PhotoImage(file='Image2.png')

        # Frame Control
        container = Frame(self)  
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        container.pack(side="top",fill="both", expand=1)

        self.frames = {}

        for F in (Page_1, Page_2):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.showFrame("Page_1")


    def showFrame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()


class Page_1(Frame): # I/P SubClass
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.controller = controller


        def Input():
            # Page_2.tbut.config(image='pyimage2') ?????
            pass

        Button(self, text='ChangeImage', command =lambda: Input()).pack()


        #Access Page 2
        Button(self, text='Go to Page 2', command=lambda: self.controller.showFrame("Page_2")).pack()



class Page_2(Frame): # O/P SubClass                                                             
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.controller = controller

        self.tbut=Button(self, image='pyimage1', height=45, width=45)
        self.tbut.pack()

        #Access Page 1
        Button(self, text='Go to Page 1', command=lambda: self.controller.showFrame("Page_1")).pack()

app = GUI()
app.mainloop()

Many thanks for the help!

Community
  • 1
  • 1
  • I suggest you read accepted answer to [Best way to structure a tkinter application?](https://stackoverflow.com/questions/17466561/best-way-to-structure-a-tkinter-application) Also, this [Calling functions from a Tkinter Frame to an other](https://stackoverflow.com/questions/48731097/calling-functions-from-a-tkinter-frame-to-an-other) may answer your question more directly. – martineau May 26 '19 at 17:33
  • @martineau I've read it. Because my application requires multiple windows to be stacked, I have organized my pages into frame subclasses to be shown when switching. I still don't know how to access another frame subclass widget. My organization is based on Sentdex's system https://www.youtube.com/watch?v=jBUpjijYtCk&. – Drew Collins May 26 '19 at 17:48
  • 1
    Create a function in the controller to return whatever page you need. – Bryan Oakley May 26 '19 at 18:11
  • 1
    Drew, that "Sentdex" system is based on a stackoverflow answer which he didn't write. That original answer has links to many related questions. See this answer: https://stackoverflow.com/a/7557028/7432 – Bryan Oakley May 26 '19 at 18:14
  • In a nutshell, @Bryan Oakley's [answer](https://stackoverflow.com/a/48732947/355230) to the second linked question, means that since each of your `Frame` subclasses receives a `controller` argument (which is an instance of your `GUI` class), it should be possible for you to add methods (and perhaps attributes) to that class that the various `Frame` subclasses can use to do what you want. – martineau May 26 '19 at 18:15
  • @BryanOakley thank you. Your tkinter frame organization in that stackoverflow answer is incredibly useful. I appreciate the help. – Drew Collins May 26 '19 at 18:52
  • @martineau [Calling functions from a Tkinter Frame to an other](https://stackoverflow.com/questions/48731097/calling-functions-from-a-tkinter-frame-to-an-other) answered my question, thank you. The controller method get_page that allows you to reference a page instance is exactly what I needed. – Drew Collins May 28 '19 at 00:01

0 Answers0