I have a python program that accesses databases for stuff that needs to be displayed on a screen. It's purpose is to display when a person's order is ready to be picked up. I have all the code to get the data and display it on the window. However, I need every 60 seconds to re-query the databases as some orders will be picked up and need to disappear from the list and some need to be added. I just don't know how to do this, as it appears that once the app.mainloop() is called, it takes human interaction with the window to make something happen. Any assistance would be greatly appreciated... Sorry for being long winded!
Asked
Active
Viewed 2,100 times
1
-
1Take a look at my answer [here](https://stackoverflow.com/questions/47943951/tkinter-code-runs-without-mainloop-update-or-after/47955106#47955106), especially the `after` function – progmatico Oct 05 '18 at 19:04
-
1Take a look [here](https://stackoverflow.com/questions/25753632/tkinter-how-to-use-after-method) too for a good example. – progmatico Oct 05 '18 at 19:12
-
1I am sure you can make a simple looping function using the `after()` method. – Mike - SMT Oct 05 '18 at 19:59
2 Answers
2
Here is an example I threw together to show you some basics of how you can use after()
to check ever so many seconds to update your tracker.
Let me know if you have any questions.
import tkinter as tk
class Example(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry("600x400")
self.current_ticket_number = 1
self.data = [[97, "Mike"], [98, "Kaite"], [99, "Tom"]]
self.display_frame = tk.Frame(self)
self.display_frame.grid(row=2, column=0, columnspan=3, sticky="nsew")
self.lbl1 = tk.Label(self, text="Next ticket number: {}".format(self.current_ticket_number))
self.lbl1.grid(row=0, column=0)
self.lbl2 = tk.Label(self, text="Customer Name: ".format(self.current_ticket_number))
self.lbl2.grid(row=0, column=1)
self.entry1 = tk.Entry(self)
self.entry1.grid(row=0, column=2)
tk.Button(self, text="Refresh List", command=self.refresh).grid(row=1, column=0, pady=5)
tk.Button(self, text="Submit new ticket", command=self.new_ticket).grid(row=1, column=1, pady=5)
self.timed_refresh()
def new_ticket(self):
x = self.entry1.get().strip()
if x != "":
self.data.append([self.current_ticket_number, x])
#self.refresh() # you could do self.refresh() here if you want to update as soon as you create a ticket
#I left it out though so you can see how after() works below.
if self.current_ticket_number >= 99:
self.current_ticket_number = 1
else:
self.current_ticket_number += 1
def refresh(self):
self.display_frame.destroy()
self.display_frame = tk.Frame(self)
self.display_frame.grid(row=2, column=0, columnspan=3, sticky="nsew")
for ndex, item in enumerate(self.data):
tk.Label(self.display_frame, text=r"Order #{} is ready for {}.".format(item[0], item[1])).grid(row=ndex, column=1)
tk.Button(self.display_frame, text=r"Remove Ticket".format(item[0], item[1]), command=lambda x=ndex: self.remove_ticket(x)).grid(row=ndex, column=0)
def remove_ticket(self, ndex):
self.data.pop(ndex)
self.refresh()
def timed_refresh(self):
#this after statement is set for every 6 seconds
self.after(6000, self.timed_refresh)
self.refresh()
if __name__ == "__main__":
Example().mainloop()

Mike - SMT
- 14,784
- 4
- 35
- 79
-
Thanks so much for the code sample. I got mine going before I saw it, but yours incorporates things that I have yet to put in... that I need. You rock! – Bill Tepe Oct 05 '18 at 20:53
-
@BillTepe Some of the things were kinda needed to really provide a decent example of what you might want to do with a ticket list like this. Glad to help. – Mike - SMT Oct 05 '18 at 20:55
0
Here is what I ended up with. Seems to do what I need it to do. Thanks for all the help, it was spot on.
class Application(tk.Frame):
def __init__(self,master=None):
self.createWidgets()
def createWidgets(self):
tk.Frame.__init__(self)
self.pack()
for b in range(0,int(len(myItems)/2)):
#print (myItems[b])
self.btn = tk.Button(self)
self.btn["text"] = myItems[b,0]
# self.btn["command"] = (lambda tck=b, binst=btn : pickUp(tck, binst))
# self.btn["command"] = lambda ticketNo=myItems[b,1] : self.pickUp(ticketNo)
self.btn.pack(fill='x')
def pp(self) :
#print('Im in pp')
self.destroy()
getArrowDataAndUpdateSQLite()
myItems = getDisplayData()
app.createWidgets()
app.master.after(30000, self.pp)
app = Application()
app.master.title('Customer Order Status')
app.master.after(30000,app.pp)
app.mainloop()

Bill Tepe
- 53
- 5
-
I would think `self.destroy()` here would destroy your frame object and render the code unusable. – Mike - SMT Oct 05 '18 at 20:45
-
I'm new to object oriented programming, so not really sure about all the "self" stuff. But, I kind of thought the same thing... I'm destroying the very thing passed in. But, it does seem to be OK and it works. Thanks again for the help Mike. – Bill Tepe Oct 07 '18 at 12:28
-
The `self` part refers to the class itself. So for example In your answer self is the object created by your class and that is a tkinter frame. In my example self is the object that is a tk instance. AKA root window. – Mike - SMT Oct 07 '18 at 15:36