[Python-bugs-list] [ python-Bugs-632323 ] Tkinter: BitmapImage vanishes if not stored in non-local var
noreply@sourceforge.net
noreply@sourceforge.net
Thu, 07 Nov 2002 01:22:33 -0800
Bugs item #632323, was opened at 2002-11-01 22:39
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=632323&group_id=5470
Category: Tkinter
Group: Python 2.2.2
Status: Closed
Resolution: Invalid
Priority: 5
Submitted By: L. Peter Deutsch (lpd)
Assigned to: Nobody/Anonymous (nobody)
Summary: Tkinter: BitmapImage vanishes if not stored in non-local var
Initial Comment:
The following program incorrectly produces a blank canvas:
#!/usr/bin/env python
from Tkinter import *
class Me(Canvas):
def init1(self):
return BitmapImage(foreground = '#ff0000',
background = '#00ff00',
data = """\
#define t_width 8
#define t_height 8
static unsigned char t_bits[] = {
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3c, 0x3c};
""",
maskdata = """\
#define t_width 8
#define t_height 8
static unsigned char t_bits[] = {
0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18};
""")
def init2(self, image):
self.create_image(32, 32, anchor = NW, image =
image)
self = Me()
self.pack(expand = 1, fill = BOTH)
self.init2(self.init1())
#img = self.init1()
#self.init2(img)
self.mainloop()
----------------
However, the following program correctly draws a small
red-and-green icon:
#!/usr/bin/env python
from Tkinter import *
class Me(Canvas):
def init1(self):
return BitmapImage(foreground = '#ff0000',
background = '#00ff00',
data = """\
#define t_width 8
#define t_height 8
static unsigned char t_bits[] = {
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3c, 0x3c};
""",
maskdata = """\
#define t_width 8
#define t_height 8
static unsigned char t_bits[] = {
0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18};
""")
def init2(self, image):
self.create_image(32, 32, anchor = NW, image =
image)
self = Me()
self.pack(expand = 1, fill = BOTH)
#self.init2(self.init1())
img = self.init1()
self.init2(img)
self.mainloop()
----------------
The two programs are identical except that one of them
assigns the BitmapImage to a variable rather than
passing it directly as an argument.
Python 2.2.1, OS = Linux version 2.4.18-3
(bhcompile@daffy.perf.redhat.com) (gcc version 2.96
20000731 (Red Hat Linux 7.3 2.96-110)) #1 Thu Apr 18
07:37:53 EDT 2002
----------------------------------------------------------------------
Comment By: Internet Discovery (idiscovery)
Date: 2002-11-07 09:22
Message:
Logged In: YES
user_id=33229
> When the BitmapImage object is no longer referenced, it is
> finalized; finalization causes "image delete" to be
> invoked.
Martin, thanks for the explanation. The behaviour is
counterintuitive for a Tk wrapper, because in Tk images are
eternal unless explicitly deleted. They are not GC'd when
they are unreferenced, and that's their documented behaviour.
IThe documentation I was refering to was the Image class
documentation in Tkinter.py - it makes no mention of this,
and as a rule in Python, I didn't think you had to keep a
global reference to everything you pass to any function if
you want it to be still alive when the function uses it.
Perhaps the Label/Canvas/Button instances should keep a
reference to it, which would be deleted when the instance
is deleted?
I know it's not in the Library Reference, as I contributed
the Tkinter section, but I think it should be clear in
Tkinter.py.
----------------------------------------------------------------------
Comment By: Martin v. Löwis (loewis)
Date: 2002-11-05 22:13
Message:
Logged In: YES
user_id=21627
Mentioning "the docs" is somewhat funny when it comes to
Tkinter: there was no documentation on images in the first
place. I've added a new section on this in tkinter.tex 1.17.
I've also added a Tk wishlist item at
http://sourceforge.net/tracker/?func=detail&aid=633300&group_id=12997&atid=362997
If they ever act on this, we can improve Tkinter in this
respect.
----------------------------------------------------------------------
Comment By: Guido van Rossum (gvanrossum)
Date: 2002-11-05 21:23
Message:
Logged In: YES
user_id=6380
Let's close this as Not A Bug.
Maybe it needs to be fixed in the docs?
----------------------------------------------------------------------
Comment By: Martin v. Löwis (loewis)
Date: 2002-11-04 07:26
Message:
Logged In: YES
user_id=21627
When the BitmapImage object is no longer referenced, it is
finalized; finalization causes "image delete" to be invoked.
Tcl does not keep a reference to the image object; if you
don't yourself, nobody does. In turn, the image object goes
away right after being created.
The right approach would be for Tcl to somehow keep a
reference to the Python object, but I think this is
unimplementable.
----------------------------------------------------------------------
Comment By: L. Peter Deutsch (lpd)
Date: 2002-11-03 19:42
Message:
Logged In: YES
user_id=8861
The bug does *not* manifest with the following definition
for init():
def init(self):
self.img = self.init1()
self.init2(self.img)
I think this is even stronger evidence that we're seeing a
reference counting / garbage collection / finalization (?)
problem.
----------------------------------------------------------------------
Comment By: Internet Discovery (idiscovery)
Date: 2002-11-03 05:14
Message:
Logged In: YES
user_id=33229
This may be the same as what I'm seeing in Demo/tix/tixwidgets.py
Look for image1 in tixwidgets.py: I put the following comment in the code:
# This image is not showing up under Python unless it is set to a
# global variable - no problem under Tcl. I assume it is being garbage
# collected some how, even though the tcl command 'image names' shows
# that as far as Tcl is concerned, the image exists and is called pyimage1.
Can anyone explain to me what's going on? IMHO, either this is a Tkinter bug,
or a documentation bug because the documentation does not explain to me why
this image1 has to be global, or am I missing something here.
----------------------------------------------------------------------
Comment By: L. Peter Deutsch (lpd)
Date: 2002-11-02 04:32
Message:
Logged In: YES
user_id=8861
Comment #1: This bug is still there in Python 2.2.2.
Comment #2: Using a variable isn't the whole story. The bug
also manifests if I define:
def init(self):
img = self.init1()
self.init2(img)
and then have the calling program invoke self.init().
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=632323&group_id=5470