tkinter destroy()

M

max(01)*

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

any help?

bye

macs
 
E

Eric Brunel

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:

.1075951116

The winfo_exists method is what you want:
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
 
M

max(01)*

Eric said:
The winfo_exists method is what you want:


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 = Frame(self.dialogo.quadro_grande)
self.dialogo.dq.pack(
side = TOP,
anchor = W,
fill = X
)

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

self.dialogo.dv = Label(self.dialogo.dq)
self.dialogo.dv.configure(
textvariable = self.freni, ### FIXME
anchor = W
)
self.dialogo.dv.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()
 
S

stewart.midwinter

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 = IntVar()
variabili.set(0)

pulsanti.append(None)
pulsanti = Checkbutton(genitore, text = testo,
variable = variabili, relief = FLAT)
pulsanti.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.get())
if self.debug:
print "%s=%i" % (self.testo,
self.variabili.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 = Label(dialogo,
text = 'self.%s' % self.testo.split()[0],
width = massimo)
pulsanti.grid(row=1+i, column=0, pady = 2,sticky = 'w')
valore.append(None)
valore = Label(dialogo, text = self.variabili.get(),
textvariable = self.variabili)
valore.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()
 
M

max(01)*

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
 
M

max(01)*

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 = Frame(quadro_grande)
dq.pack(side = TOP, anchor = W, fill = X)

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

dv = Label(dq)
dv.configure(
textvariable = eval("self.mioChiamante." + i),
anchor = W
)
dv.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()
 
S

stewart.midwinter

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,234
Messages
2,571,178
Members
47,808
Latest member
sunnysingh55

Latest Threads

Top