By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
438,427 Members | 1,356 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 438,427 IT Pros & Developers. It's quick & easy.

tkinter destroy()

P: n/a
hi people.

when i create a widget, such as a toplevel window, and then i destroy
it, how can i test that it has been destroyed? the problem is that even
after it has been destroyed, the instance still exists and has a tkinter
name, so testing for None is not feasible:
import Tkinter
fin = None
fin1 = Tkinter.Toplevel()
fin1.destroy()
print fin1

..1075951116

any help?

bye

macs
Jul 18 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
On Tue, 29 Mar 2005 10:37:10 GMT, max(01)* <ma**@fisso.casa> wrote:
hi people.

when i create a widget, such as a toplevel window, and then i destroy
it, how can i test that it has been destroyed? the problem is that even
after it has been destroyed, the instance still exists and has a tkinter
name, so testing for None is not feasible:
>>> import Tkinter
>>> fin = None
>>> fin1 = Tkinter.Toplevel()
>>> fin1.destroy()
>>> print fin1 .1075951116


The winfo_exists method is what you want:
print fin1.winfo_exists()

0

However, I'm curious about *why* you want to do that: since *you* made the call to destroy, what would you want to do anything with a widget you've already destroyed?

HTH
--
python -c 'print "".join([chr(154 - ord(c)) for c in "U(17zX(%,5.z^5(17l8(%,5.Z*(93-965$l7+-"])'
Jul 18 '05 #2

P: n/a
Eric Brunel wrote:
On Tue, 29 Mar 2005 10:37:10 GMT, max(01)* <ma**@fisso.casa> wrote:
hi people.

when i create a widget, such as a toplevel window, and then i destroy
it, how can i test that it has been destroyed? the problem is that even
after it has been destroyed, the instance still exists and has a tkinter
name, so testing for None is not feasible:
>>> import Tkinter
>>> fin = None
>>> fin1 = Tkinter.Toplevel()
>>> fin1.destroy()
>>> print fin1

.1075951116

The winfo_exists method is what you want:
print fin1.winfo_exists()


0

However, I'm curious about *why* you want to do that: since *you* made
the call to destroy, what would you want to do anything with a widget
you've already destroyed?


my main window has a button that opens another toplevel window. this
button is bound to a method that creates the window and does some other
processing *only if* the windows does not exist yet (otherwise, the user
could click more on the button and multiple copies of the window would
pop up, which is not what i want... in fact what i do is to assign None
to a variable called self.dialogo in my main application code, then i do
self.dialogo = Toplevel() inside the method...)

in this precise moment, though, it comes to my mind that i could achieve
the purpose simply activating/deactivating the button according to a flag...

anyway, i attach the code, so you can see better what i mean...

anyone who has to say anything about is welcome of course...

it is a tentative adapration of a program found in the tcl/tk package demo

---cut here---

from Tkinter import *

class MiaApp:
def __init__(self, genitore):

self.mioGenitore = genitore
self.fonte = ("Helvetica", 12)
self.fonteVar = ("Helvetica", 14)

self.quadro_grande = Frame(genitore)
self.quadro_grande.pack(expand = YES, fill = BOTH)

self.msg = Label(self.quadro_grande)
self.msg.configure(
font = self.fonte,
wraplength = "10c",
justify = LEFT,
text = u"Sono qui sotto presentati tre pulsanti a spunta. \
Premendo un pulsante, se ne varia lo stato di selezione e si \
imposta una variabile a un valore che indica lo stato del \
pulsante stesso. Premendo il pulsante \u00ABMostra \
Variabili\u00BB si possono vedere i valori correnti delle \
variabili."
)
self.msg.pack(side = TOP)

self.pulsanti = Frame(self.quadro_grande)
self.pulsanti.pack(side = BOTTOM, fill = X, padx = "2m")

self.pulsanti_spunta = Frame(self.quadro_grande)
self.pulsanti_spunta.pack(side = TOP, fill = X, padx = "2m")

self.annulla = Button(self.pulsanti)
self.annulla.configure(
text = "Annulla",
command = self.mioGenitore.destroy
)
self.annulla.pack(side = LEFT, expand = YES)
self.var = Button(self.pulsanti)
self.var.configure(
text = "Mostra Variabili",
command = self.pulsanteMostraVariabiliPremuto
)
self.var.pack(side = LEFT, expand = YES)

self.tergicristalli = IntVar()
self.b1 = Checkbutton(self.pulsanti_spunta)
self.b1.configure(
text = "Tergicristalli a posto",
variable = self.tergicristalli,
relief = FLAT
)
self.b1.pack(
side = TOP,
pady = 2,
anchor = W
)

self.freni = IntVar()
self.b2 = Checkbutton(self.pulsanti_spunta)
self.b2.configure(
text = "Freni a posto",
variable = self.freni,
relief = FLAT
)
self.b2.pack(
side = TOP,
pady = 2,
anchor = W
)

self.autista = IntVar()
self.b3 = Checkbutton(self.pulsanti_spunta)
self.b3.configure(
text = "Autista sobrio",
variable = self.autista,
relief = FLAT
)
self.b3.pack(
side = TOP,
pady = 2,
anchor = W
)

self.dialogo = None

def mostraVariabili(self, *argomenti):
self.dialogo = Toplevel()
self.dialogo.wm_title("Valori delle variabili")

self.dialogo.quadro_grande = Frame(self.dialogo)
self.dialogo.quadro_grande.pack(expand = YES, fill = BOTH)

self.dialogo.titolo = Label(self.dialogo.quadro_grande)
self.dialogo.titolo.configure(
text = "Valori delle variabili:",
width = 20,
font = self.fonteVar
)
self.dialogo.titolo.pack(side = TOP, fill = X)

lung = 1
for i in argomenti:
if len(i) > lung:
lung = len(i)

self.dialogo.dq = {}
self.dialogo.dn = {}
self.dialogo.dv = {}
for i in argomenti:
self.dialogo.dq[i] = Frame(self.dialogo.quadro_grande)
self.dialogo.dq[i].pack(
side = TOP,
anchor = W,
fill = X
)

self.dialogo.dn[i] = Label(self.dialogo.dq[i])
self.dialogo.dn[i].configure(
text = i + ": ",
width = lung + 2,
anchor = W
)
self.dialogo.dn[i].pack(
side = LEFT
)

self.dialogo.dv[i] = Label(self.dialogo.dq[i])
self.dialogo.dv[i].configure(
textvariable = self.freni, ### FIXME
anchor = W
)
self.dialogo.dv[i].pack(
side = LEFT,
expand = YES,
fill = X
)

self.dialogo.vaBene = Button(self.dialogo.quadro_grande)
self.dialogo.vaBene.configure(
text = "Va Bene",
command = self.pulsanteVaBenePremuto,
default = ACTIVE
)
self.dialogo.vaBene.bind(
"<Return>",
self.pulsanteVaBenePremuto_a
)
self.dialogo.vaBene.focus_force()
self.dialogo.vaBene.pack(
side = BOTTOM,
pady = 2
)

def pulsanteVaBenePremuto(self):
self.dialogo.destroy()
self.dialogo = None

def pulsanteVaBenePremuto_a(self, evento):
self.pulsanteVaBenePremuto()

def pulsanteMostraVariabiliPremuto(self):
if not self.dialogo:
self.mostraVariabili("self.tergicristalli",
"self.freni",
"self.autista") ### FIXME
else:
self.dialogo.lift(self.mioGenitore)

radice = Tk()
radice.wm_title("Dimostrazione Pulsanti a Spunta")
radice.wm_iconname("spunta")
miaApp = MiaApp(radice)
radice.mainloop()
Jul 18 '05 #3

P: n/a
Your app seems to give the right state values only if you select 'Freni
a posto'. But I see you recognize that with your 'FIXME' note.

also the app seems to have too many variables and widgets defined as
self objects. That isn't necessary unless they will be used outside
the method they were created in (which labels and buttons usually
aren't), so all you are doing is using up more memory than necessary.
Reading the code with Italian names adds a little difficulty in
understanding your code (non parlo italiano ma si parlo espagnol), but
I'm left feeling that your app is more complicated than it needs to be
- unless I'm missing something. What you are doing is just showing how
you can capture the state of the checkbuttons for use elsewhere, right?
And also, that the state in the 2nd window should be live, so that it
updates with the change in value in the 1st window? And just a matter
of personal taste, but splitting up widget configuration over many
lines for me impedes readiblity and makes the code look like java or
c++ : surely not what we want?

I also think you could get away with no frames in your initial window,
at least if you use grid() instead of pack(). Also your three state
variables could be members of a list, so you don't have to have
separate constructors for each of them.

Anyway here's a version of your app that makes use of a 'for' statement
to draw the labels and checkbuttons, so it's only half as long as your
original app. It also does the right thing - the key pont you were
missing was to use a 'textvariable' argument in defining your label
widgets in the 2nd window.

cheers
Stewart in Calgary

---
#tested on Windows XP with Python 2.4

from Tkinter import *

class MiaApp:
def __init__(self, genitore):
self.debug = 1 #debug flag
self.fonte = ("Helvetica", 12)
self.fonteVar = ("Helvetica", 14)

msg = Label(genitore, font = self.fonte, wraplength = "10c",
justify = LEFT,
text = u"Sono qui sotto presentati tre pulsanti a
spunta. \
Premendo un pulsante, se ne varia lo stato di selezione e si \
imposta una variabile a un valore che indica lo stato del \
pulsante stesso. Premendo il pulsante \u00ABMostra \
Variabili\u00BB si possono vedere i valori correnti delle \
variabili.")
msg.grid(row=0, column=0, sticky='w')

testo = ["Tergicristalli a posto", "Freni a posto", "Autista
sobrio"]
self.testo = testo
variabili = []
pulsanti = []
for i in range(0,3):
variabili.append(None)
variabili[i] = IntVar()
variabili[i].set(0)

pulsanti.append(None)
pulsanti[i] = Checkbutton(genitore, text = testo[i],
variable = variabili[i], relief = FLAT)
pulsanti[i].grid(row=i+1, column=0,pady = 2,sticky = 'w')

self.variabili = variabili

var1 = Button(genitore, text = "Mostra Variabili",
command = self.pulsanteMostraVariabiliPremuto)
var1.grid(row=4, column=0)

annulla = Button(genitore, text = "Annulla",
command = genitore.destroy)
annulla.grid(row=4, column=1)
def pulsanteMostraVariabiliPremuto(self):
argomenti = []
for i in range(0,len(self.variabili)):
argomenti.append(self.variabili[i].get())
if self.debug:
print "%s=%i" % (self.testo[i],
self.variabili[i].get())
self.mostraVariabili(argomenti)
def mostraVariabili(self, *argomenti):
dialogo = Toplevel()
dialogo.wm_title("Valori delle variabili")
self.dialogo = dialogo

titolo = Label(dialogo,
text = "Valori delle variabili:", width = 20,
font = self.fonteVar )
titolo.grid(row=0, column=0, sticky='w' )

massimo = len(max(self.testo)) + 2
valore = []
pulsanti = []
for i in range(0,3):
pulsanti.append(None)

pulsanti[i] = Label(dialogo,
text = 'self.%s' % self.testo[i].split()[0],
width = massimo)
pulsanti[i].grid(row=1+i, column=0, pady = 2,sticky = 'w')
valore.append(None)
valore[i] = Label(dialogo, text = self.variabili[i].get(),
textvariable = self.variabili[i])
valore[i].grid(row=i+1, column=1, pady = 2, sticky = 'w')

vaBene = Button(dialogo, text = "Va Bene",
command = self.pulsanteVaBenePremuto)
vaBene.bind("<Return>", lambda e=1:
self.pulsanteVaBenePremuto() )
vaBene.focus_force()
#items can span more than one column if desired
vaBene.grid(row=4, column=0, pady = 2, sticky='e')

def pulsanteVaBenePremuto(self):
self.dialogo.destroy()
radice = Tk()
radice.wm_title("Dimostrazione Pulsanti a Spunta")
radice.wm_iconname("spunta")
miaApp = MiaApp(radice)
radice.mainloop()

Jul 18 '05 #4

P: n/a
st***************@gmail.com wrote:
Your app seems to give the right state values only if you select 'Freni
a posto'. But I see you recognize that with your 'FIXME' note.

also the app seems to have too many variables and widgets defined as
self objects. That isn't necessary unless they will be used outside
the method they were created in (which labels and buttons usually
aren't), so all you are doing is using up more memory than necessary.

very good advice. i'll try to follow it (i am a newbie, you see...)

Reading the code with Italian names adds a little difficulty in
understanding your code (non parlo italiano ma si parlo espagnol),
i am trying to write an introductory article for an italian audience,
you see... next time i'll try to translate the names (i was a bit in a
hurry, sorry ;-)
but
I'm left feeling that your app is more complicated than it needs to be
- unless I'm missing something. What you are doing is just showing how
you can capture the state of the checkbuttons for use elsewhere, right?
And also, that the state in the 2nd window should be live, so that it
updates with the change in value in the 1st window?
precisely.
And just a matter
of personal taste, but splitting up widget configuration over many
lines for me impedes readiblity and makes the code look like java or
c++ : surely not what we want?
right... :-)

I also think you could get away with no frames in your initial window,
at least if you use grid() instead of pack().
as a matter of personal taste i prefer pack(), unless special reasons
for doing differently. i like better to give general structure
(hyerarchically) to the gui than hardcoding the appearance.
Also your three state
variables could be members of a list, so you don't have to have
separate constructors for each of them.

ok...
Anyway here's a version of your app that makes use of a 'for' statement
to draw the labels and checkbuttons, so it's only half as long as your
original app. It also does the right thing - the key pont you were
missing was to use a 'textvariable' argument in defining your label
widgets in the 2nd window.

cheers
Stewart in Calgary


i am going to study it thoroughly. thanks a lot.

bye

macs
Jul 18 '05 #5

P: n/a
> also the app seems to have too many variables and widgets defined as
self objects. That isn't necessary unless they will be used outside
the method they were created in (which labels and buttons usually
aren't), so all you are doing is using up more memory than necessary.

you are right, and at the end of this post you will find a new version
of my code which heeds to your suggestion.

but i think there are exceptions.

consider for example building a BitmapImage for successive use in a
widget, such as:

self.immagine_1a = PhotoImage()
self.immagine_1a.configure(
file = "terra.gif"
)

self.e1 = Label(self.quadro_grande)
self.e1.configure(
image = self.immagine_1a,
bd = 1,
relief = SUNKEN
)

if we follow your advice we should do:

immagine_1a = PhotoImage()
....

instead, but it doesn't work. why?
And just a matter
of personal taste, but splitting up widget configuration over many
lines for me impedes readiblity and makes the code look like java or
c++ : surely not what we want?

i thought about it. i prefer not to have lines longer than the usual 80
char display, since (in my opinion) this produces an even more
unreadable code layout. but we are starting a holy war i think...
Also your three state
variables could be members of a list, so you don't have to have
separate constructors for each of them.

it's true. but the drawback is that you have to keep an explicit
mappping between names and variables; and what's worst is that this
mapping must be known by the function that displays the second windows,
and this is against data hiding.

if you are so kind as to peek at the attached code, you'll see that i
also have restructured that part as one class. i'd like to hear your
opinion about that. (now the code for the second window in completely
reusable, i guess)
Anyway here's a version of your app that makes use of a 'for' statement
to draw the labels and checkbuttons, so it's only half as long as your
original app. It also does the right thing - the key pont you were
missing was to use a 'textvariable' argument in defining your label
widgets in the 2nd window.
.... and to use eval()

massimo = len(max(self.testo)) + 2


better: massimo = max(map(len, self.testo)) + 2

.....

anyway, here it is. bye!

----

from Tkinter import *

class MiaApp:
def __init__(self, genitore):

fonte = ("Helvetica", 12)

quadro_grande = Frame(genitore)
quadro_grande.pack(expand = YES, fill = BOTH)

msg = Label(quadro_grande)
msg.configure(
font = fonte,
wraplength = "10c",
justify = LEFT,
text = u"Sono qui sotto presentati tre pulsanti a spunta. \
Premendo un pulsante, se ne varia lo stato di selezione e si \
imposta una variabile a un valore che indica lo stato del \
pulsante stesso. Premendo il pulsante \u00ABMostra \
Variabili\u00BB si possono vedere i valori correnti delle \
variabili."
)
msg.pack(side = TOP)

pulsanti = Frame(quadro_grande)
pulsanti.pack(side = BOTTOM, fill = X, padx = "2m")

pulsanti_spunta = Frame(quadro_grande)
pulsanti_spunta.pack(side = TOP, fill = X, padx = "2m")

chiudi = Button(pulsanti)
chiudi.configure(text = "Chiudi", command = genitore.destroy)
chiudi.pack(side = LEFT, expand = YES)

self.var = Button(pulsanti)
self.var.configure(
text = "Mostra Variabili",
command = self.pulsanteMostraVariabiliPremuto,
default = NORMAL
)
self.var.pack(side = LEFT, expand = YES)

self.tergicristalli = IntVar()
ps1 = Checkbutton(pulsanti_spunta)
ps1.configure(
text = "Tergicristalli a posto",
variable = self.tergicristalli,
relief = FLAT
)
ps1.pack(side = TOP, pady = 2, anchor = W)

self.freni = IntVar()
ps2 = Checkbutton(pulsanti_spunta)
ps2.configure(
text = "Freni a posto",
variable = self.freni,
relief = FLAT
)
ps2.pack(side = TOP, pady = 2, anchor = W)

self.autista = IntVar()
ps3 = Checkbutton(pulsanti_spunta)
ps3.configure(
text = "Autista sobrio",
variable = self.autista,
relief = FLAT
)
ps3.pack(side = TOP, pady = 2, anchor = W)

def pulsanteMostraVariabiliPremuto(self):
if self.var.cget("state") == ACTIVE:
self.var.configure(state = DISABLED)
mv = MostraVariabili(
self,
"tergicristalli",
"freni",
"autista"
)

class MostraVariabili(Toplevel):
def __init__(self, chiamante, *variabili):

Toplevel.__init__(self)

self.mioChiamante = chiamante

fonteVar = ("Helvetica", 14)

self.wm_title("Valori delle variabili")

quadro_grande = Frame(self)
quadro_grande.pack(expand = YES, fill = BOTH)

titolo = Label(quadro_grande)
titolo.configure(
text = "Valori delle variabili:",
width = 20,
font = fonteVar
)
titolo.pack(side = TOP, fill = X)

lung = max(map(len, variabili))

dq = {}
dn = {}
dv = {}
for i in variabili:
dq[i] = Frame(quadro_grande)
dq[i].pack(side = TOP, anchor = W, fill = X)

dn[i] = Label(dq[i])
dn[i].configure(
text = i + ": ",
width = lung + 2,
anchor = W
)
dn[i].pack(side = LEFT)

dv[i] = Label(dq[i])
dv[i].configure(
textvariable = eval("self.mioChiamante." + i),
anchor = W
)
dv[i].pack(side = LEFT, expand = YES, fill = X)

vaBene = Button(quadro_grande)
vaBene.configure(
text = "Va Bene",
command = self.pulsanteVaBenePremuto,
default = ACTIVE
)
vaBene.bind("<Return>", self.pulsanteVaBenePremuto_a)
vaBene.focus_force()
vaBene.pack(side = BOTTOM, pady = 2)

def pulsanteVaBenePremuto(self):
self.destroy()
self.mioChiamante.var.configure(state = NORMAL)

def pulsanteVaBenePremuto_a(self, evento):
self.pulsanteVaBenePremuto()

radice = Tk()
radice.wm_title("Dimostrazione Pulsanti a Spunta")
radice.wm_iconname("spunta")
miaApp = MiaApp(radice)
radice.mainloop()
Jul 18 '05 #6

P: n/a
Macs:

"if we follow your advice we should do:

immagine_1a = PhotoImage()
....

instead, but it doesn't work. why? "

Images are a special case. You need to create an object instance of
them through the self. construction or else Tkinter seems to forget
about them within a couple of lines of code. so yes, just use
self.immagine_1a and it should work.

lots of good information on:
http://tkinter.unpy.net/wiki

I took a quick look at your app but the button doesn't open the 2nd
window. I see that you sent your message a few days ago so you've
probably solved that problem by now.

S

Jul 18 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.