Oddities of Tkinter

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Tuvas

    #1

    Oddities of Tkinter

    I am building a tkinter program. A part of this program is to read data
    from an incoming interface, and depending on the data, will display a
    bit of text on the tk dialog, it decodes this data, so to speak. If one
    command is sent, everything's just fine. When multiple are sent, the
    program will stop responding, and will only continue to respond after
    one types <ctrl>-c. The statement at fault is something like this.

    e1=StringVar()
    Label (master,textvar iable=e1, width=32).grid( row=44, column=4)

    def disp_mes1(text) :
    e1.set(text)

    It's the line 31.set(text) that takes so long when there's other
    processes running. I've ran this program sucessfully many times on
    another computer, however, when transfering to another with the same
    OS, this problem was created. Any ideas as to what I might be able to
    do to fix this problem? My main code is hopelessly complex to post the
    entire thing, and I can't recreated the same structure with smaller
    ammounts of code. Thanks for the help!

  • James Stroud

    #2
    Re: Oddities of Tkinter

    Tuvas wrote:[color=blue]
    > I am building a tkinter program. A part of this program is to read data
    > from an incoming interface, and depending on the data, will display a
    > bit of text on the tk dialog, it decodes this data, so to speak. If one
    > command is sent, everything's just fine. When multiple are sent, the
    > program will stop responding, and will only continue to respond after
    > one types <ctrl>-c. The statement at fault is something like this.
    >
    > e1=StringVar()
    > Label (master,textvar iable=e1, width=32).grid( row=44, column=4)
    >
    > def disp_mes1(text) :
    > e1.set(text)
    >
    > It's the line 31.set(text) that takes so long when there's other
    > processes running. I've ran this program sucessfully many times on
    > another computer, however, when transfering to another with the same
    > OS, this problem was created. Any ideas as to what I might be able to
    > do to fix this problem? My main code is hopelessly complex to post the
    > entire thing, and I can't recreated the same structure with smaller
    > ammounts of code. Thanks for the help!
    >[/color]

    The code you posted looks okay (assuming "31.set(tex t)" is a typo). This
    is very standard usage of Tkinter, so your problem may be somewhere else
    in your code. What happens if you replace disp_mes1() with

    def disp_mes1(text) :
    print text

    Does it still hang?

    James

    Comment

    • Tuvas

      #3
      Re: Oddities of Tkinter

      Nope, that's the oddest thing about it all... Perhaps the statement is
      called twice or something along those lines, but there again, I can't
      see how it would be...

      Comment

      • James Stroud

        #4
        Re: Oddities of Tkinter

        Tuvas wrote:[color=blue]
        > Nope, that's the oddest thing about it all... Perhaps the statement is
        > called twice or something along those lines, but there again, I can't
        > see how it would be...
        >[/color]

        Very strange behavior can occur if the same python process instantiates
        Tkinter.Tk more than once (either concurrently or at different times).
        This is my best guess without any other code to look at.

        James

        Comment

        • Tuvas

          #5
          Re: Oddities of Tkinter

          Only 1 process initiated Tkinter.Tk. I guess this'll just be a tough
          bug hunt... It drives me nuts that it should work, it just doesn't for
          some reason... I guess I can try various things to make it work, but,
          well, I would rather that it just works to start out with...

          Comment

          • James Stroud

            #6
            Re: Oddities of Tkinter

            Tuvas wrote:[color=blue]
            > Only 1 process initiated Tkinter.Tk. I guess this'll just be a tough
            > bug hunt... It drives me nuts that it should work, it just doesn't for
            > some reason... I guess I can try various things to make it work, but,
            > well, I would rather that it just works to start out with...
            >[/color]

            If you have the time, buy and read Grayson
            (http://www.manning.com/books/grayson) or the Tkinter section of
            Programming Python by Mark Lutz--and then re-write your code. The
            exercise will be well worth the time of learning and the pain of
            re-writing your code.

            James

            Comment

            • Eric Brunel

              #7
              Re: Oddities of Tkinter

              On 23 Jan 2006 11:28:37 -0800, Tuvas <tuvas21@gmail. com> wrote:
              [color=blue]
              > I am building a tkinter program. A part of this program is to read data
              > from an incoming interface, and depending on the data, will display a
              > bit of text on the tk dialog, it decodes this data, so to speak. If one
              > command is sent, everything's just fine. When multiple are sent, the
              > program will stop responding, and will only continue to respond after
              > one types <ctrl>-c. The statement at fault is something like this.
              >
              > e1=StringVar()
              > Label (master,textvar iable=e1, width=32).grid( row=44, column=4)
              >
              > def disp_mes1(text) :
              > e1.set(text)
              >
              > It's the line 31.set(text) that takes so long when there's other
              > processes running. I've ran this program sucessfully many times on
              > another computer, however, when transfering to another with the same
              > OS, this problem was created. Any ideas as to what I might be able to
              > do to fix this problem?[/color]

              I've already seen this kind of problems when trying to do Tkinter calls
              from other threads than the one from which the mainloop was started. Are
              there any threads involved?

              I also know that tk can take a very long time on such requests when there
              are "unusual" non-ascii characters to display (CJK for example) as it
              automatically looks for a font that will be able to render it; it may take
              a very long time, especially if there are many installed fonts. Do you try
              to display such characters?

              You also don't tell us what your OS is. It may help...
              --
              python -c "print ''.join([chr(154 - ord(c)) for c in
              'U(17zX(%,5.zmz 5(17;8(%,5.Z65\ '*9--56l7+-'])"

              Comment

              • Tuvas

                #8
                Re: Oddities of Tkinter

                I thought I mentioned that I'm running in linux, and yes, there are
                threads involved. I just don't know why on one machine that it would
                run so differently than another.

                As to re-writing my whole code, well, I've got around 2500 lines of
                code, and while re-writing would be faster I'm sure, I still don't want
                to invest in the long hours to do such a thing. Especially since 90% of
                the time that it will be running on the one machine that works, only a
                small percentage on the other, and it will never be publically used.
                It's an interface for a custom-built astronamical camera, it'd be
                useless to anyone who doesn't have the very camera that we have, except
                to get an idea as to how some things work.

                Comment

                • Eric Brunel

                  #9
                  Re: Oddities of Tkinter

                  On 24 Jan 2006 12:37:01 -0800, Tuvas <tuvas21@gmail. com> wrote:[color=blue]
                  > I thought I mentioned that I'm running in linux, and yes, there are
                  > threads involved. I just don't know why on one machine that it would
                  > run so differently than another.[/color]

                  The only secure way I found to make Tkinter mix with threads is to never
                  issue commands altering the graphical state of the application in another
                  thread than the one where the mainloop was started. Not doing that often
                  leads to random behaviour such as the one you have here. Fortunately, one
                  of the commands that seems to work in secondary threads is event_generate,
                  giving you a means to communicate between threads. If you have to pass
                  information from one thread to another, you can use a Queue.

                  For example:
                  ---------------------------------------------------------------------
                  import threading
                  import time
                  import Queue
                  from Tkinter import *

                  ## Create main window
                  root = Tk()

                  ## Communication queue
                  commQueue = Queue.Queue()

                  ## Function run in thread
                  def timeThread():
                  curTime = 0
                  while 1:
                  ## Each time the time increases, put the new value in the queue...
                  commQueue.put(c urTime)
                  ## ... and generate a custom event on the main window
                  try:
                  root.event_gene rate('<<TimeCha nged>>', when='tail')
                  ## If it failed, the window has been destoyed: over
                  except TclError:
                  break
                  ## Next
                  time.sleep(1)
                  curTime += 1

                  ## In the main thread, do usual stuff
                  timeVar = IntVar()
                  Label(root, textvariable=ti meVar, width=8).pack()

                  ## Use a binding on the custom event to get the new time value
                  ## and change the variable to update the display
                  def timeChanged(eve nt):
                  timeVar.set(com mQueue.get())

                  root.bind('<<Ti meChanged>>', timeChanged)

                  ## Run the thread and the GUI main loop
                  th=threading.Th read(target=tim eThread)
                  th.start()

                  root.mainloop()
                  ---------------------------------------------------------------------

                  This obvioulsy complicates things a bit, but it may work far better.
                  Please note that the 'when' option *must* be specified in the call to
                  event_generate and *must not* be 'now'. If it's not specified or if it's
                  'now', Tkinter may directly execute the binding in the secondary thread's
                  context.

                  HTH

                  (BTW, please quote the question to which you're replying. You're fortunate
                  I still had your original question in mind, or I would have had no idea of
                  what you were talking about...)
                  --
                  python -c "print ''.join([chr(154 - ord(c)) for c in
                  'U(17zX(%,5.zmz 5(17;8(%,5.Z65\ '*9--56l7+-'])"

                  Comment

                  • tooper

                    #10
                    Re: Oddities of Tkinter

                    Tuvas,

                    I fully agree with Eric's post above. You may additionnaly have to kill
                    the main window before exit, to avoid a nasty thread related error
                    message and occasionally some zombie procs:

                    import Tkinter,atexit
                    top=Tkinter.Tk( )
                    ..../...
                    atexit.register (lambda top=top: top.destroy())
                    top.mainloop()

                    Comment

                    Working...