tural
tural

Reputation: 320

retrieve from database dynamically to tkinter gui

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

Answers (2)

msw
msw

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

Terry Jan Reedy
Terry Jan Reedy

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

Related Questions