Tk window and contents will not display

Discussion in 'Python' started by Chris Hare, Aug 14, 2010.

  1. Chris Hare

    Chris Hare Guest

    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()
    Chris Hare, Aug 14, 2010
    #1
    1. Advertising

  2. Chris Hare

    Peter Otten Guest

    Chris Hare wrote:

    > 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.


    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()
    Peter Otten, Aug 14, 2010
    #2
    1. Advertising

  3. Chris Hare

    Chris Hare Guest

    On Aug 14, 2010, at 3:14 PM, Peter Otten wrote:

    > Chris Hare wrote:
    >
    >> 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.

    >
    > 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()
    >


    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?
    Chris Hare, Aug 14, 2010
    #3
  4. Chris Hare

    Peter Otten Guest

    Chris Hare wrote:

    > 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?


    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
    Peter Otten, Aug 14, 2010
    #4
  5. Chris Hare

    Chris Hare Guest

    On Aug 14, 2010, at 5:49 PM, Peter Otten wrote:

    > Chris Hare wrote:
    >
    >> 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?

    >
    > 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
    > --
    > 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
    Chris Hare, Aug 15, 2010
    #5
  6. Chris Hare

    Peter Otten Guest

    Chris Hare wrote:

    >
    > On Aug 14, 2010, at 5:49 PM, Peter Otten wrote:
    >
    >> Chris Hare wrote:
    >>
    >>> 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


    > 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

    >>> 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
    Peter Otten, Aug 15, 2010
    #6
  7. Chris Hare

    Chris Hare Guest

    On Aug 14, 2010, at 6:46 PM, Peter Otten wrote:

    > Chris Hare wrote:
    >
    >>
    >> On Aug 14, 2010, at 5:49 PM, Peter Otten wrote:
    >>
    >>> Chris Hare wrote:
    >>>
    >>>> 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

    >
    >> 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
    >
    >>>> 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
    > --
    > http://mail.python.org/mailman/listinfo/python-list


    Perfect!

    Thank you
    Chris Hare, Aug 15, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?Tm92aWNl?=
    Replies:
    2
    Views:
    6,619
    Alan Ferrandiz Langley
    Jun 9, 2004
  2. Don Adams
    Replies:
    1
    Views:
    580
    Martin Honnen
    Mar 5, 2004
  3. Kamarulnizam Rahim
    Replies:
    4
    Views:
    203
    Robert Klemme
    Jan 28, 2011
  4. Graham J
    Replies:
    2
    Views:
    99
    Graham J
    Sep 20, 2003
  5. Replies:
    0
    Views:
    177
Loading...

Share This Page