Reputation: 11989
I have a list like:
list = ['one', 'two', 'three', 'four']
and the items of the list are changing every 10 minutes (keep that in mind).
I need a gui with a background image where I can print every item from the list. I could do that with
for item in list:
print item
and I tried it with tkinter, but I had some problems with the mainloop(). When I do
for item in list:
root = Tk()
canvas = Canvas(width = 300, height = 200, bg = 'yellow')
canvas.pack(expand = YES, fill = BOTH)
gif1 = PhotoImage(file = 'myImage.gif')
canvas.create_image(0, 0, image = gif1, anchor = NW)
# print item from my list
w = Label(root, text=item)
w.pack()
root.mainloop()
the tkinter gui with the image is shown but only with the text "one" (first item from my list). When I close the gui another window pops up with "two", when I close that window then there is "three" ... and at least "four". It's logical because I'm the whole time in a for loop and for every item in my list a gui is generated.
My question: How can I update the gui? The items from my list are changing every 10 minutes. I need to iterate through my list and print all items in one gui window. After 10 minutes I want to iterate again through my list and to update the gui again.
How can I do that?
Upvotes: 1
Views: 7742
Reputation: 11
Your code is pretty much correct just the part where you are starting loop is causing to create multiple windows. If you just place down loop right before the label part it will print all fours items from list. Here it's like this:
from tkinter import *
list=["one","two","three","four"]
root = Tk()
canvas = Canvas(width = 300, height = 200, bg = 'yellow')
canvas.pack(expand = YES, fill = BOTH)
# print item from my list
for item in list:
w = Label(root, text=item)
w.pack()
root.mainloop()
Upvotes: 1
Reputation: 10958
Here's one way to do it with two threads, which is useful if you need to perform long computations or blocking IO. Set up a queue to communicate between your main GUI thread and the "feeder" thread. You can read from the queue in a function that the main loop will call at a regular interval using root.after(). All TK methods have to be called in the thread that calls root.mainloop() (your program may crash otherwise).
import threading
from Tkinter import Tk, Canvas, Label
import Queue
import time
from itertools import cycle
# Feeder thread puts one word in the queue every second
source_iter = cycle(['one', 'two', 'three', 'four', 'five', 'six'])
queue = Queue.Queue()
def source():
for item in source_iter:
queue.put(item)
time.sleep(1.)
source_thread = threading.Thread(target=source)
source_thread.setDaemon(True)
source_thread.start()
# Main thread reads the queue every 250ms
root = Tk()
w = Label(root, text='')
w.pack()
def update_gui():
try:
text = queue.get_nowait()
w.config(text=text)
except Queue.Empty:
pass
root.after(250, update_gui)
update_gui()
root.mainloop()
Upvotes: 0
Reputation: 444
You are getting 4 windows because you are defining mainloop and all the rest in the for loop. As an alternative try:
root = Tk()
canvas = Canvas(width = 300, height = 200, bg = 'yellow')
canvas.pack(expand = YES, fill = BOTH)
gif1 = PhotoImage(file = 'myImage.gif')
canvas.create_image(0, 0, image=gif1, anchor = NW)
item=" ".join(list)
w = Label(root, text=item)
w.pack()
root.mainloop()
That prints all items in the list as a line. The next step is to redraw the main window when the list changes. I am not a Tk expert so I can't help with that.
Try this stuff to learn how to use Tk properly.
Upvotes: 1