tkinter destroy()

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • max(01)*

    #1

    tkinter destroy()

    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:
    [color=blue][color=green][color=darkred]
    >>> import Tkinter
    >>> fin = None
    >>> fin1 = Tkinter.Topleve l()
    >>> fin1.destroy()
    >>> print fin1[/color][/color][/color]
    ..1075951116

    any help?

    bye

    macs
  • Eric Brunel

    #2
    Re: tkinter destroy()

    On Tue, 29 Mar 2005 10:37:10 GMT, max(01)* <max2@fisso.cas a> wrote:[color=blue]
    > 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:
    >[color=green][color=darkred]
    > >>> import Tkinter
    > >>> fin = None
    > >>> fin1 = Tkinter.Topleve l()
    > >>> fin1.destroy()
    > >>> print fin1[/color][/color]
    > .1075951116[/color]

    The winfo_exists method is what you want:
    [color=blue][color=green][color=darkred]
    >>> print fin1.winfo_exis ts()[/color][/color][/color]
    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+-"])'

    Comment

    • max(01)*

      #3
      Re: tkinter destroy()

      Eric Brunel wrote:[color=blue]
      > On Tue, 29 Mar 2005 10:37:10 GMT, max(01)* <max2@fisso.cas a> wrote:
      >[color=green]
      >> 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:
      >>[color=darkred]
      >> >>> import Tkinter
      >> >>> fin = None
      >> >>> fin1 = Tkinter.Topleve l()
      >> >>> fin1.destroy()
      >> >>> print fin1[/color]
      >> .1075951116[/color]
      >
      >
      > The winfo_exists method is what you want:
      >[color=green][color=darkred]
      >>>> print fin1.winfo_exis ts()[/color][/color]
      >
      > 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?[/color]

      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.mioGenitor e = genitore
      self.fonte = ("Helvetica" , 12)
      self.fonteVar = ("Helvetica" , 14)

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

      self.msg = Label(self.quad ro_grande)
      self.msg.config ure(
      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(s ide = TOP)

      self.pulsanti = Frame(self.quad ro_grande)
      self.pulsanti.p ack(side = BOTTOM, fill = X, padx = "2m")

      self.pulsanti_s punta = Frame(self.quad ro_grande)
      self.pulsanti_s punta.pack(side = TOP, fill = X, padx = "2m")

      self.annulla = Button(self.pul santi)
      self.annulla.co nfigure(
      text = "Annulla",
      command = self.mioGenitor e.destroy
      )
      self.annulla.pa ck(side = LEFT, expand = YES)


      self.var = Button(self.pul santi)
      self.var.config ure(
      text = "Mostra Variabili",
      command = self.pulsanteMo straVariabiliPr emuto
      )
      self.var.pack(s ide = LEFT, expand = YES)

      self.tergicrist alli = IntVar()
      self.b1 = Checkbutton(sel f.pulsanti_spun ta)
      self.b1.configu re(
      text = "Tergicrist alli a posto",
      variable = self.tergicrist alli,
      relief = FLAT
      )
      self.b1.pack(
      side = TOP,
      pady = 2,
      anchor = W
      )

      self.freni = IntVar()
      self.b2 = Checkbutton(sel f.pulsanti_spun ta)
      self.b2.configu re(
      text = "Freni a posto",
      variable = self.freni,
      relief = FLAT
      )
      self.b2.pack(
      side = TOP,
      pady = 2,
      anchor = W
      )

      self.autista = IntVar()
      self.b3 = Checkbutton(sel f.pulsanti_spun ta)
      self.b3.configu re(
      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.qu adro_grande = Frame(self.dial ogo)
      self.dialogo.qu adro_grande.pac k(expand = YES, fill = BOTH)

      self.dialogo.ti tolo = Label(self.dial ogo.quadro_gran de)
      self.dialogo.ti tolo.configure(
      text = "Valori delle variabili:",
      width = 20,
      font = self.fonteVar
      )
      self.dialogo.ti tolo.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.dial ogo.quadro_gran de)
      self.dialogo.dq[i].pack(
      side = TOP,
      anchor = W,
      fill = X
      )

      self.dialogo.dn[i] = Label(self.dial ogo.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.dial ogo.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.va Bene = Button(self.dia logo.quadro_gra nde)
      self.dialogo.va Bene.configure(
      text = "Va Bene",
      command = self.pulsanteVa BenePremuto,
      default = ACTIVE
      )
      self.dialogo.va Bene.bind(
      "<Return>",
      self.pulsanteVa BenePremuto_a
      )
      self.dialogo.va Bene.focus_forc e()
      self.dialogo.va Bene.pack(
      side = BOTTOM,
      pady = 2
      )

      def pulsanteVaBeneP remuto(self):
      self.dialogo.de stroy()
      self.dialogo = None

      def pulsanteVaBeneP remuto_a(self, evento):
      self.pulsanteVa BenePremuto()

      def pulsanteMostraV ariabiliPremuto (self):
      if not self.dialogo:
      self.mostraVari abili("self.ter gicristalli",
      "self.freni ",
      "self.autis ta") ### FIXME
      else:
      self.dialogo.li ft(self.mioGeni tore)

      radice = Tk()
      radice.wm_title ("Dimostrazi one Pulsanti a Spunta")
      radice.wm_iconn ame("spunta")
      miaApp = MiaApp(radice)
      radice.mainloop ()

      Comment

      • stewart.midwinter@gmail.com

        #4
        Re: tkinter destroy()

        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 = ["Tergicrist alli a posto", "Freni a posto", "Autista
        sobrio"]
        self.testo = testo
        variabili = []
        pulsanti = []
        for i in range(0,3):
        variabili.appen d(None)
        variabili[i] = IntVar()
        variabili[i].set(0)

        pulsanti.append (None)
        pulsanti[i] = Checkbutton(gen itore, 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.pulsanteMo straVariabiliPr emuto)
        var1.grid(row=4 , column=0)

        annulla = Button(genitore , text = "Annulla",
        command = genitore.destro y)
        annulla.grid(ro w=4, column=1)


        def pulsanteMostraV ariabiliPremuto (self):
        argomenti = []
        for i in range(0,len(sel f.variabili)):
        argomenti.appen d(self.variabil i[i].get())
        if self.debug:
        print "%s=%i" % (self.testo[i],
        self.variabili[i].get())
        self.mostraVari abili(argomenti )


        def mostraVariabili (self, *argomenti):
        dialogo = Toplevel()
        dialogo.wm_titl e("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.te sto)) + 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(N one)
        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.pulsanteVa BenePremuto)
        vaBene.bind("<R eturn>", lambda e=1:
        self.pulsanteVa BenePremuto() )
        vaBene.focus_fo rce()
        #items can span more than one column if desired
        vaBene.grid(row =4, column=0, pady = 2, sticky='e')

        def pulsanteVaBeneP remuto(self):
        self.dialogo.de stroy()


        radice = Tk()
        radice.wm_title ("Dimostrazi one Pulsanti a Spunta")
        radice.wm_iconn ame("spunta")
        miaApp = MiaApp(radice)
        radice.mainloop ()

        Comment

        • max(01)*

          #5
          Re: tkinter destroy()

          stewart.midwint er@gmail.com wrote:[color=blue]
          > 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.
          >[/color]

          very good advice. i'll try to follow it (i am a newbie, you see...)
          [color=blue]
          >
          > Reading the code with Italian names adds a little difficulty in
          > understanding your code (non parlo italiano ma si parlo espagnol),[/color]

          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 ;-)
          [color=blue]
          > 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?[/color]

          precisely.
          [color=blue]
          > 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?[/color]

          right... :-)
          [color=blue]
          >
          > I also think you could get away with no frames in your initial window,
          > at least if you use grid() instead of pack().[/color]

          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.
          [color=blue]
          > Also your three state
          > variables could be members of a list, so you don't have to have
          > separate constructors for each of them.
          >[/color]

          ok...
          [color=blue]
          > 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[/color]

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

          bye

          macs

          Comment

          • max(01)*

            #6
            Re: tkinter destroy()

            > also the app seems to have too many variables and widgets defined as[color=blue]
            > 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.
            >[/color]

            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_1 a = PhotoImage()
            self.immagine_1 a.configure(
            file = "terra.gif"
            )

            self.e1 = Label(self.quad ro_grande)
            self.e1.configu re(
            image = self.immagine_1 a,
            bd = 1,
            relief = SUNKEN
            )

            if we follow your advice we should do:

            immagine_1a = PhotoImage()
            ....

            instead, but it doesn't work. why?
            [color=blue]
            > 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?
            >[/color]

            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...
            [color=blue]
            > Also your three state
            > variables could be members of a list, so you don't have to have
            > separate constructors for each of them.
            >[/color]

            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)
            [color=blue]
            > 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.[/color]

            .... and to use eval()

            [color=blue]
            > massimo = len(max(self.te sto)) + 2[/color]

            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.p ack(expand = YES, fill = BOTH)

            msg = Label(quadro_gr ande)
            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_gr ande)
            pulsanti.pack(s ide = BOTTOM, fill = X, padx = "2m")

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

            chiudi = Button(pulsanti )
            chiudi.configur e(text = "Chiudi", command = genitore.destro y)
            chiudi.pack(sid e = LEFT, expand = YES)

            self.var = Button(pulsanti )
            self.var.config ure(
            text = "Mostra Variabili",
            command = self.pulsanteMo straVariabiliPr emuto,
            default = NORMAL
            )
            self.var.pack(s ide = LEFT, expand = YES)

            self.tergicrist alli = IntVar()
            ps1 = Checkbutton(pul santi_spunta)
            ps1.configure(
            text = "Tergicrist alli a posto",
            variable = self.tergicrist alli,
            relief = FLAT
            )
            ps1.pack(side = TOP, pady = 2, anchor = W)

            self.freni = IntVar()
            ps2 = Checkbutton(pul santi_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(pul santi_spunta)
            ps3.configure(
            text = "Autista sobrio",
            variable = self.autista,
            relief = FLAT
            )
            ps3.pack(side = TOP, pady = 2, anchor = W)

            def pulsanteMostraV ariabiliPremuto (self):
            if self.var.cget(" state") == ACTIVE:
            self.var.config ure(state = DISABLED)
            mv = MostraVariabili (
            self,
            "tergicristalli ",
            "freni",
            "autista"
            )

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

            Toplevel.__init __(self)

            self.mioChiaman te = chiamante

            fonteVar = ("Helvetica" , 14)

            self.wm_title(" Valori delle variabili")

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

            titolo = Label(quadro_gr ande)
            titolo.configur e(
            text = "Valori delle variabili:",
            width = 20,
            font = fonteVar
            )
            titolo.pack(sid e = TOP, fill = X)

            lung = max(map(len, variabili))

            dq = {}
            dn = {}
            dv = {}
            for i in variabili:
            dq[i] = Frame(quadro_gr ande)
            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.mioC hiamante." + i),
            anchor = W
            )
            dv[i].pack(side = LEFT, expand = YES, fill = X)

            vaBene = Button(quadro_g rande)
            vaBene.configur e(
            text = "Va Bene",
            command = self.pulsanteVa BenePremuto,
            default = ACTIVE
            )
            vaBene.bind("<R eturn>", self.pulsanteVa BenePremuto_a)
            vaBene.focus_fo rce()
            vaBene.pack(sid e = BOTTOM, pady = 2)

            def pulsanteVaBeneP remuto(self):
            self.destroy()
            self.mioChiaman te.var.configur e(state = NORMAL)

            def pulsanteVaBeneP remuto_a(self, evento):
            self.pulsanteVa BenePremuto()

            radice = Tk()
            radice.wm_title ("Dimostrazi one Pulsanti a Spunta")
            radice.wm_iconn ame("spunta")
            miaApp = MiaApp(radice)
            radice.mainloop ()

            Comment

            • stewart.midwinter@gmail.com

              #7
              Re: tkinter destroy()

              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_1 a and it should work.

              lots of good information on:


              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

              Comment

              Working...