Discussion:
Tk window and contents will not display
(too old to reply)
Chris Hare
2010-08-14 18:30:59 UTC
Permalink
The scenario is this:

I want to loop around all of the images in a given directory (which I know will be images, but I guess I should check), show an image in a window, wait 2 seconds and show the next one and repeat that indefinitley, which will be until the user closes the window.

This is the code I extracted from the larger program and made work - sort of - in a standalone fashion. When I run the code, each of the file names gets displayed, and I can view the images, so it has to be something I am doing wrong with this chunk of code.

However, I don't see what the problem is.

from Tkinter import *
import time
import os
import ImageTk
import Image

class externalLoopDisplay:

def show(self):
#
# Create a frame
#
self.window = Tk()
self.f = Frame(self.window, bg="Gray")
self.f.grid()
self.btnRefresh = Button(self.f, text="Close", command=self.window.destroy, bg="Gray",highlightbackground="Red", highlightcolor="Green")
self.btnRefresh.grid(row=0, column=2)
self.loopImage()

def loopImage(self):
dir = "Radar/net17"
while 1:
fileList = os.listdir(dir)
number = len(fileList)
c = 1
for gifFile in fileList:
print "externalLoopDisplay.show:","top of for loop " + str(c) + " of " + str(number)
print "externalLoopDisplay.show:","showing file " + dir + "/" + gifFile
self.window.title("Image " + str(c) + " of " + str(number))
image = Image.open(dir + "/" + gifFile)
canvasWidth, canvasHeight = image.size
self.w = Canvas(self.f, width=canvasWidth, height=canvasHeight)
photo = ImageTk.PhotoImage(image=image)
netRadarImage = Label(self.w, image=photo)
netRadarImage.image = photo
self.w.grid(row=1, column=0, columnspan=3)
netRadarImage.grid( row=1, column=0)
time.sleep(10)
c = c + 1
self.w.destroy()

loop=externalLoopDisplay()
loop.show()
Peter Otten
2010-08-14 20:14:22 UTC
Permalink
Post by Chris Hare
I want to loop around all of the images in a given directory (which I know
will be images, but I guess I should check), show an image in a window,
wait 2 seconds and show the next one and repeat that indefinitley, which
will be until the user closes the window.
This is the code I extracted from the larger program and made work - sort
of - in a standalone fashion. When I run the code, each of the file names
gets displayed, and I can view the images, so it has to be something I am
doing wrong with this chunk of code.
However, I don't see what the problem is.
I have not looked at your code in detail, but event loops and time.sleep()
don't play together very well. Use after(delay_in_milliseconds, callable)
instead.

Here's a simple example that loops over images passed from the command line:

import Image
import ImageTk
import os
import sys
import Tkinter as tk

from itertools import cycle

def next_image():
imagefile = next(imagefiles)
image = Image.open(imagefile)

w, h = image.size
image = image.resize((700, 700*h//w))

label.image = label["image"] = ImageTk.PhotoImage(image=image)
root.title("Now showing %s" % os.path.basename(imagefile))

root.after(2000, next_image)

if __name__ == "__main__":
imagefiles = sys.argv[1:]
assert imagefiles
imagefiles = cycle(imagefiles)

root = tk.Tk()
label = tk.Label(root)
label.pack()

root.after_idle(next_image)
root.mainloop()
Chris Hare
2010-08-14 22:00:12 UTC
Permalink
Post by Peter Otten
Post by Chris Hare
I want to loop around all of the images in a given directory (which I know
will be images, but I guess I should check), show an image in a window,
wait 2 seconds and show the next one and repeat that indefinitley, which
will be until the user closes the window.
This is the code I extracted from the larger program and made work - sort
of - in a standalone fashion. When I run the code, each of the file names
gets displayed, and I can view the images, so it has to be something I am
doing wrong with this chunk of code.
However, I don't see what the problem is.
I have not looked at your code in detail, but event loops and time.sleep()
don't play together very well. Use after(delay_in_milliseconds, callable)
instead.
import Image
import ImageTk
import os
import sys
import Tkinter as tk
from itertools import cycle
imagefile = next(imagefiles)
image = Image.open(imagefile)
w, h = image.size
image = image.resize((700, 700*h//w))
label.image = label["image"] = ImageTk.PhotoImage(image=image)
root.title("Now showing %s" % os.path.basename(imagefile))
root.after(2000, next_image)
imagefiles = sys.argv[1:]
assert imagefiles
imagefiles = cycle(imagefiles)
root = tk.Tk()
label = tk.Label(root)
label.pack()
root.after_idle(next_image)
root.mainloop()
Thanks Peter. I threw away what I started with and merged your code into my class:

class externalLoopDisplay:

def show(self):
main.logging.debug("externalLoopDisplay.show:","start")

self.window = Tk()

self.btnClose = Button(self.window, text="Close", command=self.window.destroy, bg=backColor,highlightbackground=warnColor, highlightcolor=okColor)
self.btnClose.grid(row=0, column=2)
self.label = Label(self.window)
self.label.grid(row=1, column=0, columnspan=3)
dirName = getRadarPath() + "/net" + str(netNumber.get()) # e.g. .../Radar/net17/net17-YYYYMMDDHHMMSS.gif
self.imagefiles = glob.glob(dirName + "/*.gif")
self.imagefiles = cycle(self.imagefiles)
self.window.after_idle(self.next_image)

def next_image(self):
imagefile = next(self.imagefiles)
image = Image.open(imagefile)

w, h = image.size
image = image.resize((600, 550*h//w))

self.label.image = self.label["image"] = ImageTk.PhotoImage(image=image) # <==== bails here
self.window.title("Now showing %s" % os.path.basename(imagefile))

self.window.after(2000, next_image)


I marked where the code bails with an error saying pyimage2 doesn't exist. All of the images exist and worked just fine with your standalone script.

Suggestions?
Peter Otten
2010-08-14 22:49:45 UTC
Permalink
Post by Chris Hare
main.logging.debug("externalLoopDisplay.show:","start")
self.window = Tk()
self.btnClose = Button(self.window, text="Close",
command=self.window.destroy,
bg=backColor,highlightbackground=warnColor,
highlightcolor=okColor) self.btnClose.grid(row=0, column=2)
self.label = Label(self.window) self.label.grid(row=1, column=0,
columnspan=3)
dirName = getRadarPath() + "/net" + str(netNumber.get()) # e.g.
.../Radar/net17/net17-YYYYMMDDHHMMSS.gif
self.imagefiles = glob.glob(dirName + "/*.gif")
self.imagefiles = cycle(self.imagefiles)
self.window.after_idle(self.next_image)
imagefile = next(self.imagefiles)
image = Image.open(imagefile)
w, h = image.size
image = image.resize((600, 550*h//w))
self.label.image = self.label["image"] =
ImageTk.PhotoImage(image=image) # <==== bails here
self.window.title("Now showing %s" % os.path.basename(imagefile))
self.window.after(2000, next_image)
I marked where the code bails with an error saying pyimage2 doesn't exist.
All of the images exist and worked just fine with your standalone script.
Suggestions?
Google says you are calling Tkinter.Tk() more than once where you should
instead use Tkinter.Toplevel(). As you didn't post that part of the code
it's hard to verify, but when I add a second

root = tk.Tk()

to my example script I get a very similar exception:

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1413, in __call__
return self.func(*args)
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 498, in callit
func(*args)
File "cycle_image.py", line 16, in next_image
label.image = label["image"] = ImageTk.PhotoImage(image=image)
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1212, in __setitem__
self.configure({key: value})
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1205, in configure
return self._configure('configure', cnf, kw)
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1196, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
TclError: image "pyimage1" doesn't exist

By the way: for future posts please remember to cut and paste the traceback,
don't paraphrase the error message.

Peter
Chris Hare
2010-08-14 23:23:02 UTC
Permalink
Post by Peter Otten
Post by Chris Hare
main.logging.debug("externalLoopDisplay.show:","start")
self.window = Tk()
self.btnClose = Button(self.window, text="Close",
command=self.window.destroy,
bg=backColor,highlightbackground=warnColor,
highlightcolor=okColor) self.btnClose.grid(row=0, column=2)
self.label = Label(self.window) self.label.grid(row=1, column=0,
columnspan=3)
dirName = getRadarPath() + "/net" + str(netNumber.get()) # e.g.
.../Radar/net17/net17-YYYYMMDDHHMMSS.gif
self.imagefiles = glob.glob(dirName + "/*.gif")
self.imagefiles = cycle(self.imagefiles)
self.window.after_idle(self.next_image)
imagefile = next(self.imagefiles)
image = Image.open(imagefile)
w, h = image.size
image = image.resize((600, 550*h//w))
self.label.image = self.label["image"] =
ImageTk.PhotoImage(image=image) # <==== bails here
self.window.title("Now showing %s" % os.path.basename(imagefile))
self.window.after(2000, next_image)
I marked where the code bails with an error saying pyimage2 doesn't exist.
All of the images exist and worked just fine with your standalone script.
Suggestions?
Google says you are calling Tkinter.Tk() more than once where you should
instead use Tkinter.Toplevel(). As you didn't post that part of the code
it's hard to verify, but when I add a second
root = tk.Tk()
Exception in Tkinter callback
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1413, in __call__
return self.func(*args)
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 498, in callit
func(*args)
File "cycle_image.py", line 16, in next_image
label.image = label["image"] = ImageTk.PhotoImage(image=image)
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1212, in __setitem__
self.configure({key: value})
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1205, in configure
return self._configure('configure', cnf, kw)
File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1196, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
TclError: image "pyimage1" doesn't exist
By the way: for future posts please remember to cut and paste the traceback,
don't paraphrase the error message.
Peter
--
http://mail.python.org/mailman/listinfo/python-list
Yes - you are bang on.

Thanks. One final question if I may, how would you suggest I handle checking for new files and adding them to the list? For example, if the loop is playing and a new image is added, how can I detect it and then refresh the list of file?

I am stuck on that part with this new approach.

Chris
Peter Otten
2010-08-14 23:46:20 UTC
Permalink
Post by Chris Hare
Post by Chris Hare
main.logging.debug("externalLoopDisplay.show:","start")
self.window = Tk()
self.btnClose = Button(self.window, text="Close",
command=self.window.destroy,
bg=backColor,highlightbackground=warnColor,
highlightcolor=okColor) self.btnClose.grid(row=0, column=2)
self.label = Label(self.window) self.label.grid(row=1, column=0,
columnspan=3)
dirName = getRadarPath() + "/net" + str(netNumber.get()) # e.g.
.../Radar/net17/net17-YYYYMMDDHHMMSS.gif
Thanks. One final question if I may, how would you suggest I handle
checking for new files and adding them to the list? For example, if the
loop is playing and a new image is added, how can I detect it and then
refresh the list of file?
I am stuck on that part with this new approach.
Chris
Replacing
Post by Chris Hare
Post by Chris Hare
self.imagefiles = glob.glob(dirName + "/*.gif")
self.imagefiles = cycle(self.imagefiles)
with

self.imagefiles = image_cycler(os.path.join(dirname, "*.gif"))

where image_cycler() looks as follows

def image_cycler(pattern):
while True:
for fn in glob.glob(pattern):
yield fn

would be the simplest way.

Peter
Chris Hare
2010-08-15 00:50:25 UTC
Permalink
Post by Peter Otten
Post by Chris Hare
Post by Chris Hare
main.logging.debug("externalLoopDisplay.show:","start")
self.window = Tk()
self.btnClose = Button(self.window, text="Close",
command=self.window.destroy,
bg=backColor,highlightbackground=warnColor,
highlightcolor=okColor) self.btnClose.grid(row=0, column=2)
self.label = Label(self.window) self.label.grid(row=1, column=0,
columnspan=3)
dirName = getRadarPath() + "/net" + str(netNumber.get()) # e.g.
.../Radar/net17/net17-YYYYMMDDHHMMSS.gif
Thanks. One final question if I may, how would you suggest I handle
checking for new files and adding them to the list? For example, if the
loop is playing and a new image is added, how can I detect it and then
refresh the list of file?
I am stuck on that part with this new approach.
Chris
Replacing
Post by Chris Hare
Post by Chris Hare
self.imagefiles = glob.glob(dirName + "/*.gif")
self.imagefiles = cycle(self.imagefiles)
with
self.imagefiles = image_cycler(os.path.join(dirname, "*.gif"))
where image_cycler() looks as follows
yield fn
would be the simplest way.
Peter
--
http://mail.python.org/mailman/listinfo/python-list
Perfect!

Thank you

Loading...