Python Forum
[Tkinter] Implementing tk.after
Thread Rating:
  • 1 Vote(s) - 1 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Implementing tk.after
#1
Hello all,
I have difficulty implement tk.after command into my code.
I heard tk.after does not freeze the program, so I intend to use it.

Here is my code
import tkinter as tk
import time

running = True #Global Flag

class BackGroundFrame(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.shared_data = {
            "name1": tk.StringVar(),
            "name2": tk.StringVar(),
            "name3": tk.StringVar(),
            "name4": tk.StringVar(),
            }
        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, ManualPage):    
            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, page_class):
        return self.frames[page_class]

        
class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        
        instruction = tk.Label(self, text="Welcome to Dispensing GUI")
        instruction.grid(row=0 , column=0, columnspan=3, sticky="W")
        
        tk.Label(self, text="        ").grid(row=1, column=0, sticky="W")
        
        tk.Label(self, text="Solutions to Pumps Allocations").grid(row=2, column=0, columnspan=10, sticky="W")
        
        self.typeofsolution1 = tk.Entry(self, textvariable=self.controller.shared_data["name1"], width=12)  # tk.Entry widget function 
        self.typeofsolution1.grid(row=3, column=0, sticky="W")
        tk.Label(self, text="Pump 1").grid(row=4, column=0, columnspan=2, sticky="W") 
         
        tk.Label(self, text="    ").grid(row=3, column=1, sticky="W")
        
        self.typeofsolution2 = tk.Entry(self, textvariable=self.controller.shared_data["name2"], width=12)  # tk.Entry widget function 
        self.typeofsolution2.grid(row=3, column=2, sticky="W")
        tk.Label(self, text="Pump 2").grid(row=4, column=2, sticky="W")
        
        tk.Label(self, text="    ").grid(row=3, column=3, sticky="W")
        
        self.typeofsolution3 = tk.Entry(self, textvariable=self.controller.shared_data["name3"], width=12)
        self.typeofsolution3.grid(row=3, column=4, sticky="W")
        tk.Label(self, text="Pump 3").grid(row=4, column=4, columnspan=2, sticky="W") 
        
        tk.Label(self, text="    ").grid(row=3, column=5, sticky="W")
        
        self.typeofsolution4 = tk.Entry(self, textvariable=self.controller.shared_data["name4"], width=12)
        self.typeofsolution4.grid(row=3, column=6, sticky="W")
        tk.Label(self, text="Pump 4").grid(row=4, column=6, columnspan=2, sticky="W")
        
        self.submitManual = tk.Button(self, text="Manual", command=lambda:controller.show_frame(ManualPage))
        self.submitManual.grid(row=8, rowspan=5, column=0, columnspan=4, sticky="W")
        
        self.submitAutomatic = tk.Button(self, text="Automatic")
        self.submitAutomatic.grid(row=8, rowspan=5, column=1, columnspan=2, sticky="W")
            
        
class ManualPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
         
        self.manualtitle = tk.Label(self, text="Welcome to Manual Dispensing")
        self.manualtitle.grid(row=0 , column=0, columnspan=6, sticky="W")
        
        
        tk.Label(self, text="Solution Name    ").grid(row=1, column=0, sticky="W")
        tk.Label(self, text="Time Input(s)     ").grid(row=1, column=2, sticky="w")
        tk.Label(self, text="Dispense").grid(row=1, column=3, sticky="W")
       
        
        
        self.submitlol = tk.Button(self, text="Back to Main Menu", command=lambda:controller.show_frame(StartPage))
        self.submitlol.grid(row=12, rowspan=5, column=0, columnspan=4, sticky="W")
        
        
        
        self.timepump1 = tk.Entry(self, width=10)  # entry widget function 
        self.timepump1.grid(row=2, column=1, columnspan=10, sticky="w")
        
        self.timepump2 = tk.Entry(self, width=10)  # entry widget function 
        self.timepump2.grid(row=4, column=1, columnspan=10, sticky="w")
        
        self.timepump3 = tk.Entry(self, width=10)  # entry widget function 
        self.timepump3.grid(row=6, column=1, columnspan=10, sticky="w")
        
        self.timepump4 = tk.Entry(self, width=10)  # entry widget function 
        self.timepump4.grid(row=8, column=1, columnspan=10, sticky="w")
        
        self.timepump5 = tk.Entry(self, width=10)  # entry widget function 
        self.timepump5.grid(row=10, column=1, columnspan=10, sticky="w")
        
        
        
        
        self.submit1 = tk.Button(self, text="Dispense 1",command=self.actldis1)
        self.submit1.grid(row=2, column=3, columnspan=10, sticky="w")
        
        self.submit2 = tk.Button(self, text="Dispense 2",command=self.actldis2)
        self.submit2.grid(row=4, column=3, columnspan=10, sticky="w")
        
        self.submit3 = tk.Button(self, text="Dispense 3",command=self.actldis3)
        self.submit3.grid(row=6, column=3, columnspan=10, sticky="w")
        
        self.submit4 = tk.Button(self, text="Dispense 4",command=self.actldis4)
        self.submit4.grid(row=8, column=3, columnspan=10, sticky="w")
        
        self.submit5 = tk.Button(self, text="Dispense 5",command=self.actldis5)
        self.submit5.grid(row=10, column=3, columnspan=10, sticky="w")
        
        self.action1 = tk.Button(self, text="Retrieve Solution Name",command=self.retrievesolutions)
        self.action1.grid(row=0, column=3, columnspan=3, sticky="W")
        
    def retrievesolutions(self):
        name1 = self.controller.shared_data["name1"].get()
        name2 = self.controller.shared_data["name2"].get()
        name3 = self.controller.shared_data["name3"].get()
        name4 = self.controller.shared_data["name4"].get()
        
        self.text1 = tk.Text(self, width=10, height=1)
        self.text1.grid(row=2, column=0, columnspan=10, sticky="W")
        
        
        self.text2 = tk.Text(self, width=10, height=1)
        self.text2.grid(row=4, column=0, columnspan=10, sticky="W")
        
        
        self.text3 = tk.Text(self, width=10, height=1)
        self.text3.grid(row=6, column=0, columnspan=10, sticky="w")
        
        
        self.text4 = tk.Text(self, width=10, height=1)
        self.text4.grid(row=8, column=0, columnspan=10, sticky="w")
        
        tk.Label(self, text="        Drain").grid(row=10, column=0, sticky="W")
        
        
        
        
        self.text1.delete(0.0,tk.END)
        self.text1.insert(0.0, name1)
        
        self.text2.delete(0.0,tk.END)
        self.text2.insert(0.0, name2)
        
        self.text3.delete(0.0,tk.END)
        self.text3.insert(0.0, name3)
        
        self.text4.delete(0.0,tk.END)
        self.text4.insert(0.0, name4)
        
        
        
        print(name1, name2, name3, name4)
        
    
    def lol1(self):
        solution="1" 
        t=self.timepump1.get()
        return solution,t
    
    def lol2(self):
        solution="2" 
        t=self.timepump2.get()
        return solution,t
    
    def lol3(self):
        solution="3" 
        t=self.timepump3.get()
        return solution,t
        
    def lol4(self):
        solution="4"
        t=self.timepump4.get()
        return solution,t
    
    def lol5(self):
        solution="5"
        t=self.timepump5.get()
        return solution,t
        


            
    def actldis1(self):
        solution, t = ManualPage.lol1(self)       
        dispense(self,solution=solution,t=t)
    def actldis2(self):
        solution, t = ManualPage.lol2(self)       
        dispense(self,solution=solution,t=t)  
    def actldis3(self):
        solution, t = ManualPage.lol3(self)       
        dispense(self,solution=solution,t=t)
    def actldis4(self):
        solution, t = ManualPage.lol4(self)       
        dispense(self,solution=solution,t=t)
        
    def actldis5(self):
        solution, t = ManualPage.lol5(self)       
        dispense(self,solution=solution,t=t)

def dispense(self,solution,t):
    if solution in ("1","2","3","4","5"):
        print("solution",solution,"time taken:", t)
        gpt ={"1":17,"2":18,"3":23,"4":24,"5":27}
        print("GPIOPORTactivation:",gpt[solution])
        print("GPIO High") #GPIO.output(gpt[solution],HIGH)
        BackGroundFrame.after(t,dispense)
        print("GPIO low")#GPIO.output(gpt[solution],LOW)]    
   

BackGroundFrame.after(0,dispense)        
app = BackGroundFrame()
app.mainloop()
I wish to implement the tk.after in function"dispense"

def dispense(self,solution,t):
    if solution in ("1","2","3","4","5"):
        print("solution",solution,"time taken:", t)
        gpt ={"1":17,"2":18,"3":23,"4":24,"5":27}
        print("GPIOPORTactivation:",gpt[solution])
        print("GPIO High") #GPIO.output(gpt[solution],HIGH)
        BackGroundFrame.after(t,dispense)
        print("GPIO low")#GPIO.output(gpt[solution],LOW)]
Any help would be greatly appreciated!
Reply
#2
BackGroundFrame.after(t,dispense)
to
self.after(t, self.dispense, solution, t)

example
import tkinter as tk

class App:
    def __init__(self):
        self.root = tk.Tk()

        self.loop("first loop", 500, 5)
        self.loop("second loop", 300, 9)

    def loop(self, name, interval, countdown):
        print(name, countdown)
        if(countdown > 0):
            self.root.after(interval, self.loop, name, interval, countdown - 1)

app = App()
app.root.mainloop()
99 percent of computer problems exists between chair and keyboard.
Reply
#3
Hi Windspar,
After following your advice, I had an error "TypeError: dispense() missing 1 required positional argument: 't'"

Here's my newly implemented code :
def dispense(self,solution,t):
    if solution in ("1","2","3","4","5"):
        print("solution",solution,"time taken:", t)
        gpt ={"1":17,"2":18,"3":23,"4":24,"5":27}
        print("GPIOPORTactivation:",gpt[solution])
        print("GPIO High") #GPIO.output(gpt[solution],HIGH)
        self.after(t, dispense, solution, t)
        print("GPIO low")#GPIO.output(gpt[solution],LOW)]    
Just a reminder that my def dispense is outside my class.

Thanks !
Reply
#4
If dispense is outside your class. Then there shouldn't be a self as an argument.
def dispense(solution, t):
    # other code
    BackgroundFrame.after(t, dispense, solution, t)
99 percent of computer problems exists between chair and keyboard.
Reply
#5
Hi WindSpar,
Sorry for the late reply,
I forgot to include that I had an error with the following input you gave me earlier on.
With the new input, it produces a new error:
callit.__name__ = func.__name__
AttributeError: 'str' object has no attribute '__name__'
It would be great if you can help me out on this!
Thanks
Reply
#6
def dispense(func, solution, t):
    if solution in ("1","2","3","4","5"):
        print("solution",solution,"time taken:", t)
        gpt ={"1":17,"2":18,"3":23,"4":24,"5":27}
        print("GPIOPORTactivation:",gpt[solution])
        print("GPIO High") #GPIO.output(gpt[solution],HIGH)
        solution, t = func()
        app.after(t, dispense, func, solution, t)
        print("GPIO low")#GPIO.output(gpt[solution],LOW)]

app = BackGroundFrame()
app.mainloop()
def actldis1(self):
        solution, t = self.lol1()
        dispense(self.lol1, solution, t)
99 percent of computer problems exists between chair and keyboard.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020