0
votes

I have a main tkinter window where the user selects some files, marks his options and whatever. On pressing the Run button,3 things should happen:

  • the main window disappears
  • the background procces starts to run WHILE
  • a new window appears and starts to print information regarding the running process(in the example below things such as, b is 3, b is 5, b is 10, etc.

Is there any way to do this without using 2 threads?(if yes,how? i tried but i cannot figure out how to end the processes) one for the GUI and one from the process. As far as i know, tkinter mainloop has a blocking effect. Any advice is highly appreciated. The next code should be revealing- there is a class for each window.

import tkinter as Tk
import time

class Mainframe(object):


    def __init__(self,parent):
        self.root=parent
        self.root.title("Main frame")
        self.frame=Tk.Frame(parent)
        self.frame.pack()

        btn=Tk.Button(self.frame,text="Run momma",command=self.RunButton)
        btn.pack()

     def Secondwindow(self):

        self.root.destroy()
        newWindow=Tk.Tk()
        window=Secondframe(newWindow)


    def process(self):

        b=0
        for a in range(0,20):
            b=a
            print (b)
            time.sleep(0.2)

    def RunButton(self):

        self.Secondwindow()
        self.process()


class Secondframe(object):

    def __init__(self,parent):
        self.root=parent
        self.root.title("Main frame")
        self.frame=Tk.Frame(parent)
        self.frame.pack()
        self.root.geometry("400x300")
        self.root.title("otherFrame")

if __name__=="__main__":

    root=Tk.Tk()
    root.geometry("800x600")
    app=Mainframe(root)
    root.mainloop()
1

1 Answers

0
votes

Yes, you can kill one window and boot another (using withdraw and Toplevel, you should never call Tk() more than once), but why would you do that? Why don't you just update the first window?

import tkinter as tk
import time
import threading

class Mainframe(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.frame = FirstFrame(self)
        self.frame.pack()

    def change(self, frame):
        self.frame.pack_forget() # delete currrent frame
        self.frame = frame(self)
        self.frame.pack() # make new frame

class FirstFrame(tk.Frame):
    def __init__(self, master=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)

        master.title("Main frame")
        master.geometry("800x600")

        btn=tk.Button(self,text="Run momma",command=self.RunButton)
        btn.pack()

    def RunButton(self):
        self.master.change(SecondFrame)

class SecondFrame(tk.Frame):
    def __init__(self, master=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        master.title("otherFrame")
        master.geometry("400x300")
        self.var = tk.StringVar(self)
        lbl = tk.Label(self, textvariable=self.var)
        lbl.pack(anchor='w')
        btn = tk.Button(self, text="go back", command=lambda: master.change(FirstFrame))
        btn.pack()

        t = threading.Thread(target=self.process)
        t.start()


    def process(self):
        b=0
        for a in range(0,20):
            b=a
            print (b)
            self.var.set("Current value is {}".format(b))
            time.sleep(0.2)

if __name__=="__main__":
    app=Mainframe()
    app.mainloop()

Notice I still used threading. That's because you can't enter a blocking loop when you are using tkinter, since the GUI will lock up. All long computation needs to be integrated into the tkinter mainloop (usually using the after method) or it's own thread.