Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #108920 > unrolled thread

Image loading problem

Started by"sweating_ant@yahoo.com" <huey.y.jiang@gmail.com>
First post2016-05-21 08:22 -0700
Last post2016-05-22 22:57 +0200
Articles 11 — 9 participants

Back to article view | Back to comp.lang.python


Contents

  Image loading problem "sweating_ant@yahoo.com" <huey.y.jiang@gmail.com> - 2016-05-21 08:22 -0700
    Re: Image loading problem Peter Otten <__peter__@web.de> - 2016-05-21 18:54 +0200
    Re: Image loading problem Peter Pearson <pkpearson@nowhere.invalid> - 2016-05-21 17:10 +0000
    Re: Image loading problem Gary Herron <gherron@digipen.edu> - 2016-05-21 10:16 -0700
    Re: Image loading problem Terry Reedy <tjreedy@udel.edu> - 2016-05-21 15:23 -0400
    Re: Image loading problem Random832 <random832@fastmail.com> - 2016-05-21 15:55 -0400
    Re: Image loading problem huey.y.jiang@gmail.com - 2016-05-21 21:01 -0700
    Re: Image loading problem Peter Otten <__peter__@web.de> - 2016-05-22 11:03 +0200
    Re: Image loading problem Michael Torrie <torriem@gmail.com> - 2016-05-22 13:37 -0600
    Re: Image loading problem Random832 <random832@fastmail.com> - 2016-05-22 16:19 -0400
      Re: Image loading problem Christian Gollwitzer <auriocus@gmx.de> - 2016-05-22 22:57 +0200

#108920 — Image loading problem

From"sweating_ant@yahoo.com" <huey.y.jiang@gmail.com>
Date2016-05-21 08:22 -0700
SubjectImage loading problem
Message-ID<743e5fbe-3a6c-49ea-ac5e-9bc055f652b5@googlegroups.com>
Hi All,


I am working on an image project, and I can display my image in main(). I mean, I can load my image in my main(). Needless, it is awkward. I am trying to load my image with a function, but got an empty image window popped up, no image content loaded. Please take a look at code:



rom Tkinter import *

def load_img(win):	
	img = PhotoImage(file="xxx.gif")
	Label(win, image=img).pack()
	
win = Tk()
load_img(win)
win.mainloop()

Somebody can help me out? Thanks!

[toc] | [next] | [standalone]


#108923

FromPeter Otten <__peter__@web.de>
Date2016-05-21 18:54 +0200
Message-ID<mailman.85.1463849696.27390.python-list@python.org>
In reply to#108920
sweating_ant@yahoo.com wrote:

> I am working on an image project, and I can display my image in main(). I 
mean, I can load my image in my main(). Needless, it is awkward. I am trying 
to load my image with a function, but got an empty image window popped up, 
no image content loaded. Please take a look at code:
> 
> 
> 
> rom Tkinter import *
> 
> def load_img(win):      
>         img = PhotoImage(file="xxx.gif")
>         Label(win, image=img).pack()
>         
> win = Tk()
> load_img(win)
> win.mainloop()
> 
> Somebody can help me out? Thanks!

It's not your fault, there's an odd quirk in the library: you have to keep a 
reference of the PhotoImage instance around to prevent the image from being 
garbage-collected. For example

from Tkinter import *

def load_img(win):
    global img

    img = PhotoImage(file="xxx.gif")
    Label(win, image=img).pack()

win = Tk()
load_img(win)
win.mainloop()

will work because img is now a global that is not deleted until the script 
ends (but don't run the function twice -- then the first image will 
disappear).

[toc] | [prev] | [next] | [standalone]


#108925

FromPeter Pearson <pkpearson@nowhere.invalid>
Date2016-05-21 17:10 +0000
Message-ID<dqbj3bF77iU1@mid.individual.net>
In reply to#108920
On Sat, 21 May 2016 08:22:41 -0700 (PDT), sweating_ant@yahoo.com wrote:
>
> I am working on an image project, and I can display my image in
> main(). I mean, I can load my image in my main(). Needless, it is
> awkward. I am trying to load my image with a function, but got an
> empty image window popped up, no image content loaded. Please take a
> look at code:
>
> rom Tkinter import *
>
> def load_img(win):	
> 	img = PhotoImage(file="xxx.gif")
> 	Label(win, image=img).pack()
> 	
> win = Tk()
> load_img(win)
> win.mainloop()
>

This seems to work:
-----------
from Tkinter import Tk, PhotoImage, Label

def load_img(win):
        img = PhotoImage(file="/home/peter/dow.gif")
        Label(win, image=img).pack()
        return img

win = Tk()
img = load_img(win)
win.mainloop()
-----------

I guess the problem was that the "img" created in load_img went
out of scope and was deleted when load_img returned.  I just tried
the "return img" as an experiment to keep it from going out of scope;
from a software-engineering standpoint this might be a gross kluge.

Baffling? Personally, I never got past feeling generally bewildered in
Tkinter-land, and now I use matplotlib for all my graphical needs.  I
had great hopes for PyGUI at one point, but I hear very little about it
now.

-- 
To email me, substitute nowhere->runbox, invalid->com.

[toc] | [prev] | [next] | [standalone]


#108927

FromGary Herron <gherron@digipen.edu>
Date2016-05-21 10:16 -0700
Message-ID<mailman.86.1463851507.27390.python-list@python.org>
In reply to#108920
On 05/21/2016 08:22 AM, sweating_ant@yahoo.com wrote:
> Hi All,
>
>
> I am working on an image project, and I can display my image in main(). I mean, I can load my image in my main(). Needless, it is awkward. I am trying to load my image with a function, but got an empty image window popped up, no image content loaded. Please take a look at code:
>
>
>
> rom Tkinter import *
>
> def load_img(win):	
> 	img = PhotoImage(file="xxx.gif")
> 	Label(win, image=img).pack()
> 	
> win = Tk()
> load_img(win)
> win.mainloop()
>
> Somebody can help me out? Thanks!
>

I believe this the problem (However It's been long since I used Tkinter, 
so be warned ... ):

The function load_img creates a local variable named img which goes out 
of scope and is deleted immediately when the function returns. However, 
Tkinter needs you to keep that image around as long as the Label uses 
it.   So, some solutions are:

keep_me = [] #  Global for keeping references to images
def load_img(win):
         img = PhotoImage(file="xxx.gif")
         keep_me.append(img)
         Label(win, image=img).pack()

or


def load_img(win):
         img = PhotoImage(file="xxx.gif")
         Label(win, image=img).pack()
         return img

saved_img = load_img(win)
...


Gary Herron



-- 
Dr. Gary Herron
Professor of Computer Science
DigiPen Institute of Technology
(425) 895-4418

[toc] | [prev] | [next] | [standalone]


#108928

FromTerry Reedy <tjreedy@udel.edu>
Date2016-05-21 15:23 -0400
Message-ID<mailman.87.1463858635.27390.python-list@python.org>
In reply to#108920
On 5/21/2016 12:54 PM, Peter Otten wrote:
> sweating_ant@yahoo.com wrote:
>
>> I am working on an image project, and I can display my image in main(). I
> mean, I can load my image in my main(). Needless, it is awkward. I am trying
> to load my image with a function, but got an empty image window popped up,
> no image content loaded. Please take a look at code:
>>
>>
>>
>> rom Tkinter import *
>>
>> def load_img(win):
>>         img = PhotoImage(file="xxx.gif")
>>         Label(win, image=img).pack()
>>
>> win = Tk()
>> load_img(win)
>> win.mainloop()
>>
>> Somebody can help me out? Thanks!
>
> It's not your fault, there's an odd quirk in the library: you have to keep a
> reference of the PhotoImage instance around to prevent the image from being
> garbage-collected. For example
>
> from Tkinter import *
>
> def load_img(win):
>     global img
>
>     img = PhotoImage(file="xxx.gif")
>     Label(win, image=img).pack()
>
> win = Tk()
> load_img(win)
> win.mainloop()
>
> will work because img is now a global that is not deleted until the script
> ends (but don't run the function twice -- then the first image will
> disappear).

The usual procedure is to create an App class and make images attributes 
of the App instance.  Then load_img would be a method and the first line 
would be 'self.img = ...'.  One can also have a list of images, to use 
in a slide show, or a dict of images, so users can select.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#108929

FromRandom832 <random832@fastmail.com>
Date2016-05-21 15:55 -0400
Message-ID<mailman.88.1463860508.27390.python-list@python.org>
In reply to#108920
On Sat, May 21, 2016, at 12:54, Peter Otten wrote:
> It's not your fault, there's an odd quirk in the library: you have to
> keep a reference of the PhotoImage instance around to prevent the
> image from being garbage-collected.

Just out of curiosity, why is this a "quirk" and not a bug? Why isn't
the reference held by the Label?

[toc] | [prev] | [next] | [standalone]


#108933

Fromhuey.y.jiang@gmail.com
Date2016-05-21 21:01 -0700
Message-ID<85ec4ea5-3e5d-481f-85f8-de3b9d372bb1@googlegroups.com>
In reply to#108920
Thanks so much! All of methods works!

[toc] | [prev] | [next] | [standalone]


#108938

FromPeter Otten <__peter__@web.de>
Date2016-05-22 11:03 +0200
Message-ID<mailman.93.1463907806.27390.python-list@python.org>
In reply to#108920
Random832 wrote:

> On Sat, May 21, 2016, at 12:54, Peter Otten wrote:
>> It's not your fault, there's an odd quirk in the library: you have to
>> keep a reference of the PhotoImage instance around to prevent the
>> image from being garbage-collected.
> 
> Just out of curiosity, why is this a "quirk" and not a bug? 

I agree that this is at least a usability bug, but I think someone with a 
clue (Fredrik Lundh?) wrote it that way intentionally.

> Why isn't the reference held by the Label?

I can only speculate: to avoid a tcl/python reference cycle?
You might file a bug report and see what comes of it.

[toc] | [prev] | [next] | [standalone]


#108960

FromMichael Torrie <torriem@gmail.com>
Date2016-05-22 13:37 -0600
Message-ID<mailman.7.1463945887.20402.python-list@python.org>
In reply to#108920
On 05/21/2016 01:55 PM, Random832 wrote:
> On Sat, May 21, 2016, at 12:54, Peter Otten wrote:
>> It's not your fault, there's an odd quirk in the library: you have to
>> keep a reference of the PhotoImage instance around to prevent the
>> image from being garbage-collected.
> 
> Just out of curiosity, why is this a "quirk" and not a bug? Why isn't
> the reference held by the Label?

The reference is indeed held by the label but the problem is the label
is a Tcl/Tk object, thinly wrapped in Python.  It's essentially an
impedance mismatch between two different languages and object models
that each do their own reference holding and counting. I've run into
this issue with PySide also as one is instantiating C++ objects that do
their own internal reference counting through the Python wrapper.

I'm sure Python wrappers could try to correct for this somewhat, but
it's not a trivial thing to solve by any means.

[toc] | [prev] | [next] | [standalone]


#108962

FromRandom832 <random832@fastmail.com>
Date2016-05-22 16:19 -0400
Message-ID<mailman.8.1463948389.20402.python-list@python.org>
In reply to#108920

On Sun, May 22, 2016, at 15:37, Michael Torrie wrote:
> The reference is indeed held by the label but the problem is the label
> is a Tcl/Tk object, thinly wrapped in Python. 

Okay but then in that case why doesn't the image get instantiated as a
Tcl/Tk object which the label holds a reference to and then nobody cares
if the python image object gets collected?

(And anyway maybe the wrappers shouldn't be so thin if it causes
problems like these.)

[toc] | [prev] | [next] | [standalone]


#108963

FromChristian Gollwitzer <auriocus@gmx.de>
Date2016-05-22 22:57 +0200
Message-ID<nht69h$6f9$1@dont-email.me>
In reply to#108962
Am 22.05.16 um 22:19 schrieb Random832:
> On Sun, May 22, 2016, at 15:37, Michael Torrie wrote:
>> The reference is indeed held by the label but the problem is the label
>> is a Tcl/Tk object, thinly wrapped in Python.
>
> Okay but then in that case why doesn't the image get instantiated as a
> Tcl/Tk object which the label holds a reference to and then nobody cares
> if the python image object gets collected?

Actually, I think it could be solved, and not too complicated either. In 
Tk, objects are deleted explicitly. This is how you'd do it natively:

	image create photo bla -file myicon.png
	# create an image called "bla"
	pack [label .l -image bla]
	# display it in a label with name .l

Of course, the label references the image object. For instance, if you 
read in new image data

	bla read newicon.png -shrink

then the label will update.

What happens, when you create all those things from Tkinter, the Label 
object deletes the image in it's destructor:

	image delete bla # this will turn the label blank

This is IMHO correct, but when you add an image to the label through 
Tkinter, then it only does it through Tk (i.e. the second line in the 
above code). It should store a reference the Python image object inside 
the label object. This is akin to a "dangling pointer" in C. It would 
just be some work to replicate this for all widgets in Tk, there are 
buttons etc. but in essence I think it would work.

	Christian

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web