1

I am trying to incorporate matplotlib into tkinter by having multiple frames. I need to pass the entry inputs from StartPage frame to update the plot in GraphPage once the button in StartPage is clicked. Therefore, I'm trying to bind the update function of GraphPage to the button in StartPage, but the update function requires self parameter which I can't get. Here's the set up of my code right now:

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import tkinter as tk
from tkinter import ttk


class PeakFitting(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

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

        self.frames = {}

        for F in (StartPage, GraphPage):

            frame = F(container, self)

            self.frames[F] = frame

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

        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]

        frame.tkraise()

    def get_page(self, classname):
    '''Returns an instance of a page given it's class name as a string'''
        for page in self.frames.values():
            if str(page.__class__.__name__) == classname:
                return page
        return None

class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        self.controller = controller

       # Setting up frame and widget

        self.entry1 = tk.Entry(self)
        self.entry1.grid(row=4, column=1)

        button3 = ttk.Button(self, text="Graph Page",
                         command=self.gpUpdate())
        button3.grid(row=7, columnspan=2)

    def gpUpdate(self):
        graphPage = self.controller.get_page("GraphPage")
        GraphPage.update(graphPage)
        self.controller.show_frame("GraphPage")

class GraphPage(tk.Frame):
    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        self.controller = controller

        fig = Figure(figsize=(5, 5), dpi=100)
        self.a = fig.add_subplot()

        canvas = FigureCanvasTkAgg(fig, self)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)

        toolbar = NavigationToolbar2TkAgg(canvas, self)
        toolbar.update()
        canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        startpage = self.controller.get_page("StartPage")


    def update(self):

        startpage = self.controller.get_page("StartPage")
        self.iso = startpage.entry1.get()

##Calculation code for analysis not needed for question

app = PeakFitting()
app.mainloop()

for gpUpdate function in StartPage, I tried to pass graphPage as self, but got an Error that it's a NoneType. I also tried GraphPage.update(GraphPage) but get 'type object 'GraphPage' has no attribute 'controller'' Error.

I'm very sorry if my explanation wasn't clear, but I am very new to Python and has been struggling for weeks now to pass the entries to GraphPage class after the button is clicked but still can't do it... Can anyone please help me with this problem?

Thank you so much!!!

EDIT: I guess my main problem is how to call a function of one class in another class, because I don't know what the self parameter should be :(

EDIT2: Changes to code thanks to suggestion:

def gpUpdate(self):
    self.parent = PeakFitting()
    self.grpage = GraphPage(self.parent.container, self.parent)
    self.grpage.update()
    self.controller.show_frame(GraphPage)

However, when I input something in the entry and hit the button, the self.iso field still remains empty...

Linh Phan
  • 83
  • 1
  • 9
  • Possible duplicate of [Switch between two frames in tkinter](http://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter) – Parviz Karimli Aug 24 '16 at 22:14
  • @ParvizKarimli That post tells me how to switch between frames which I already did... It was the calling a function of one frame from another frame that I have problem with :( – Linh Phan Aug 24 '16 at 22:21

1 Answers1

3

This is the problem:

GraphPage.update(graphPage)

You call the method on the class itself. You need to create an instance of that class and then call the update method with a parent and a controller, for example:

self.grpage = GraphPage(parent, controller)

And then:

self.grpage.update()

Aside from this, you have another problem in button3- change this:

command=self.gpUpdate()

to this:

command=self.gpUpdate

without parenthesis. This is a function that you pass to the button, and will be invoked upon button click.

Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
  • Thank you so much! That did get rid of the errors, which is just fantastic!!! However, now that the `update` function in `GraphPage` runs, for some reason the `self.iso` field still remains empty string even if I've input a string before hitting button. What could be wrong? Thank you so much!!! (I've put update of code up on edit section :) ) – Linh Phan Aug 24 '16 at 22:58
  • Did you change `command=self.gpUpdate()` to `command=self.gpUpdate()`? – Israel Unterman Aug 25 '16 at 08:40
  • If you meant to `self.gpUpdate`, then yes I have. I just don't know what the problem is at this point :( – Linh Phan Aug 26 '16 at 21:43