Reputation: 320
I am new to gui development in python tkinter. What I want to do is simply listen to database table and when there is an insertion I just want this to be displayed in the gui. Currently I have the following code which does not work:
from Tkinter import *;
from db.Database import Database
import time
root = Tk();
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
logLabel = Label(topFrame, text="Log")
logField = Text(topFrame,bd=5)
logLabel.pack(side=LEFT)
logField.pack(side=LEFT)
d = Database(user='test',password='test',db='test')
prev = d.getLastLog()
logField.insert('1.0',str(prev)+'.\n')
root.mainloop()
while True:
log = d.getLastLog()
if (log[0] != prev[0]):
logField.config(state=NORMAL)
logField.insert('1.0',str(log)+'.\n')
logField.config(state=DISABLED)
prev = log
time.sleep(1)
Upvotes: 0
Views: 1320
Reputation: 43487
The underlying problem is that
root.mainloop()
does not return until the root window has been closed or destroyed. Therefore, you have to turn a polling interval into a recurring event that the mainloop
can process like any other UI event. In this case @TerryJanReedy wrote a fine answer that explained the how but not the why. Too recap the core of the other answer:
def update():
# read database and update tkinter widgets
# then reset the timer callback
root.after(interval, update)
root.after(interval, update) # kickstart the update loop
root.mainloop()
Upvotes: 1
Reputation: 19144
The way tkinter spells while True: ... time.sleep(n)
is def callback(): ... root.after(n*1000, callback)
+ an additional after call after the def
. In your case:
interval = 1000 # 1 second
def update():
log = d.getLastLog()
if (log[0] != prev[0]):
logField.config(state=NORMAL)
logField.insert('1.0',str(log)+'.\n')
logField.config(state=DISABLED)
prev = log
root.after(interval, update)
root.after(interval, update)
Put this before the root.mainloop call. For another (tested) example, see a similar answer I gave earlier today.
Upvotes: 3