Python Forum

Full Version: problem with refresh UI in tkinter app
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi
I am not sure I am approaching this the best way but I require a 2 page UI one that the users can use to select buttons whos names are controlled by the user and do various other things as part of the program.
There are alot of buttons to control but I have used 2 as an example in the code below.
Basically I am saving the data to a pickle file so when the user opens the app it will get the data based on the last session settings via the ini file.

The setup page is to allow the user to change these button names then save them to the pickle file but what I am looking for is for the app to save to pickle file and then update the userpage when they move back to the userpage without having to re-start the program.

Ive looked at refresh and idle but it does not seem to work or I have been putting it in the wrong place.

Any help will be appreciated

Thanks

import tkinter as tk                # python 3
from tkinter import font  as tkfont # python 3
import pickle

#on app open load previous pickle file data (this loads all my previous settings)
def loaddata():
    with open('sender2_ini.pkl', 'rb') as f:
        Mydata = pickle.load(f)
        return Mydata

Mydata = loaddata()

class MainApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.title('Userpage')

        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 (Userpage, Setup):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            # put all of the pages in the same location; the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("Userpage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()

    def capture_asset(self):
        print("get the name of button pressed and store global variable for later use")

class Userpage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, background="#b22222")
        self.controller = controller
        Mydata = loaddata()
        data1 = tk.StringVar(value=Mydata[0])
        data2 = tk.StringVar(value=Mydata[1])

        button1 = tk.Button(self, textvariable =data1, width=8)
        button1.grid(row=2, column=1, padx =5, pady =5)
        button2 = tk.Button(self, textvariable = data2, width=8)
        button2.grid(row=2, column=2, padx =5, pady =5)
        button3 = tk.Button(self, text="Setup", command=lambda: controller.show_frame("Setup"))
        button3.grid(row=6, column=3)

class Setup(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, width=500, height=500, background="bisque")
        self.controller = controller
        self.Mydata = loaddata()

        data1 = tk.Entry(self, textvariable = tk.StringVar(value=self.Mydata[0]))
        data1.grid(row=4, column=0)
        data2 = tk.Entry(self, textvariable = tk.StringVar(value=self.Mydata[1]))
        data2.grid(row=4, column=1)

        def setup_update():
            Mydata = [data1.get(), data2.get()]
            with open('sender2_ini.pkl', 'wb') as f:
                pickle.dump(Mydata, f)

        SaveButton = tk.Button(self, text='Save', width=25, command = setup_update)
        SaveButton.grid(row=5, column=0)

        senderbutton = tk.Button(self, text="Back to Userpage", command=lambda: controller.show_frame("Userpage"))
        senderbutton.grid(row=8, column=0)

if __name__ == "__main__":
    app = MainApp()
    app.mainloop()
Perhaps a notebook widget?
or just a couple of frames on main window, as containers for your other pages.
IF you really want multiple windows, use Toplevel
think I am almost there with all of this now everything is working but I just cannot get it to update the user page buttons when I change and save them on my setup page basically because there in 2 different classes. Ive tried using globals but this of course will not refresh my user page?
IS there a way to close my app completely after save then re-open it from scratch that way it will update as it will read them from the pickle file?
(Feb-06-2018, 12:34 PM)Philbot Wrote: [ -> ]IS there a way to close my app completely after save then re-open it from scratch that way it will update as it will read them from the pickle file?
well, this would make current poor design even worse....
at the moment you have Mydata on line#11 that you don't use anywhere
then in class Setup you have self.Mydata that again reads from external file via loaddata() (on line #65)
then in lines 72-75 you update Mydata that is local for setup_update function and thus different from previous Mydata and self.Mydata

EDIT: Oh, I missed Mydata, reading from file again on line #49 :-)
Not to mention using pkl file, when simple ini and config parser would do...
Tried to tidy this up a little now and yes too many Mydata, that me thinking I can solve the issue with the classes lol.

I still load it at the beginning for it to get last session and the other place I use it is to reset the list when changes are made to then save to the pkl file

Still doesnt update my user page so Im just not getting this class mularky, its like trying to talk to a guy in another building and we have no wifi connection

import tkinter as tk                # python 3
from tkinter import font  as tkfont # python 3
import pickle
 
#on app open load previous pickle file data (this loads all my previous settings)
def loaddata():
    with open('sender2_ini.pkl', 'rb') as f:
        Mydata = pickle.load(f)
        return Mydata
 
Mydata = loaddata()

 
class MainApp(tk.Tk):
 
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.title('Userpage')
 
        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 (Userpage, Setup):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame
 
            # put all of the pages in the same location; the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")
 
        self.show_frame("Userpage")
 
    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()
 
    def capture_asset(self):
        print("get the name of button pressed and store global variable for later use")
 
class Userpage(tk.Frame):
 
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, background="#b22222")
        self.controller = controller

        data1 = tk.StringVar(value=Mydata[0])
        data2 = tk.StringVar(value=Mydata[1])
 
        button1 = tk.Button(self, textvariable =data1, width=8)
        button1.grid(row=2, column=1, padx =5, pady =5)
        button2 = tk.Button(self, textvariable = data2, width=8)
        button2.grid(row=2, column=2, padx =5, pady =5)
        button3 = tk.Button(self, text="Setup", command=lambda: controller.show_frame("Setup"))
        button3.grid(row=6, column=3)
 
class Setup(tk.Frame):
 
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, width=500, height=500, background="bisque")
        self.controller = controller
 
        data1 = tk.Entry(self, textvariable = tk.StringVar(value=self.Mydata[0]))
        data1.grid(row=4, column=0)
        data2 = tk.Entry(self, textvariable = tk.StringVar(value=self.Mydata[1]))
        data2.grid(row=4, column=1)
 
        def setup_update():
            Mydata = [data1.get(), data2.get()]
            with open('sender2_ini.pkl', 'wb') as f:
                pickle.dump(Mydata, f)
 
        SaveButton = tk.Button(self, text='Save', width=25, command = setup_update)
        SaveButton.grid(row=5, column=0)
 
        senderbutton = tk.Button(self, text="Back to Userpage", command=lambda: controller.show_frame("Userpage"))
        senderbutton.grid(row=8, column=0)
 
if __name__ == "__main__":
    app = MainApp()
    app.mainloop()