Scrollable Tkinter widget not threadsafe?

Peter Abel p-abel at t-online.de
Wed Jun 11 04:37:16 EDT 2003


Hi all,
Im developping an controlling application on an embedded linux.
It gets its input from multiple sensors and other applications
via a data-interface.
The ouput goes to a data-interfaces, from where it is displayed
on a monitor.

At the moment Im developping under W2k and Python 2.2.2.
I simulate the sensors by Tkinter-widgets (Scales, Radiobuttons).
The output is directed to the same Tkinter-window to
output-widgets (Listboxes, Labels).
The Testsuite under W2k consists of 3 parts:
1) The controlling application, which runs in a thread
2) The Tkinter-window, which runs in a thread too
3) A main-program, which glues 1) and 2) togather.

All works fine.
Now the number of output-widgets is growing, and it became necessary
that the Tkinter-window would be scrollable. With some effort I made
it
work with the help of Fredrik Lundh's example **Autohiding
Scrollbars**
at http://effbot.org/zone/tkinter-autoscrollbar.htm.

But I couldn't make it work with threads.

Either it is not possible or I made some mistake when calling
the thread.
The following code snippet represents the kernel of my problem.
It works, when with_threads is False but not when True.
Any help would be appriciated.

import Tkinter,thread,time
#====================================
class FrameScollTest (Tkinter.Frame):
#====================================
  """
    A class to Test scrolling of widgets with
    several child-widgets
  """
  #-----------------------------------------------------------------
  def __init__ (self, master = None, **packOptions):
  #-----------------------------------------------------------------
    Tkinter.Frame.__init__ (self, master)

    self.canvas = Tkinter.Canvas
(self,width=80,height=50,bg='white',relief='flat')

    self.vscroll = Tkinter.Scrollbar
(self,orient='vertical',command=self.canvas.yview)
    self.canvas.configure(yscrollcommand=self.vscroll.set)

    self.container = Tkinter.Frame (self.canvas)


    self.label_1 = Tkinter.Label (self.container, {
        'bg'     : 'green',
        'relief' : 'ridge',
        'text'   : 'GREEN 1'
        })
    self.label_2 = Tkinter.Label (self.container, {
        'bg'     : 'white',
        'relief' : 'ridge',
        'text'   : 'WHITE 2'
        })
    self.label_3 = Tkinter.Label (self.container, {
        'bg'     : 'red',
        'relief' : 'ridge',
        'text'   : 'RED 3'
        })
    self.label_4 = Tkinter.Label (self.container, {
        'bg'     : 'blue',
        'relief' : 'ridge',
        'text'   : 'BLUE 4'
        })
    self.label_5 = Tkinter.Label (self.container, {
        'bg'     : 'yellow',
        'relief' : 'ridge',
        'text'   : 'YELLOW 5'
        })

#===============================
#   GRIDDING
#===============================
    self.canvas.grid(row=0,column=0,sticky='nesw')

    self.vscroll.grid  (row=0, column=1, sticky='ns')

    self.container.grid({
        'in' : self.canvas,
        'column' : '0',
        'row' : '0',
        'sticky' : 'nesw'
        })

    self.label_1.grid({
        'in' : self.container,
        'column' : '0',
        'row' : '0',
        'sticky' : 'nesw'
        })
    self.label_2.grid({
        'in' : self.container,
        'column' : '0',
        'row' : '1',
        'sticky' : 'nesw'
        })
    self.label_3.grid({
        'in' : self.container,
        'column' : '0',
        'row' : '2',
        'sticky' : 'nesw'
        })
    self.label_4.grid({
        'in' : self.container,
        'column' : '0',
        'row' : '3',
        'sticky' : 'nesw'
        })
    self.label_5.grid({
        'in' : self.container,
        'column' : '0',
        'row' : '4',
        'sticky' : 'nesw'
        })

    # The widget itself
    self.rowconfigure (0, {'weight' : 1, 'minsize' : 10})
    # --
    self.columnconfigure (0, {'weight' : 1})
    self.columnconfigure (1, {'weight' : 0})

    # The canvas
    self.canvas.rowconfigure(0, weight=1)
    #--
    self.canvas.columnconfigure(0, weight=0)

    # The container
    self.container.rowconfigure (0, {'weight' : 0, 'minsize' : 80})
    self.container.rowconfigure (1, {'weight' : 0, 'minsize' : 80})
    self.container.rowconfigure (2, {'weight' : 0, 'minsize' : 80})
    self.container.rowconfigure (3, {'weight' : 0, 'minsize' : 80})
    self.container.rowconfigure (4, {'weight' : 0, 'minsize' : 80})
    #--
    self.container.columnconfigure (0, {'weight' : 0, 'minsize' : 80})

    # Make canvas scrollable
    self.canvas.create_window(0, 0, anchor='nw',
window=self.container)
    self.container.update_idletasks()
    self.canvas.config(scrollregion=self.canvas.bbox("all"))


#---------------------
def show_widget():
#---------------------
  global root, activated

  activated=True
  print 'in show_widget'
  root.mainloop()
  print 'root.mainloop ready ...'
  activated=False

#=========================================
if __name__ == '__main__':
  global root, activated

  activated    = False
  with_threads = False

  root=Tkinter.Tk()
  FrameScollTest (root).pack(fill='both',expand=True)

  if with_threads:

    # 1) With thread
    thread.start_new_thread(show_widget,())
    # Give the thread a little time to install
    time.sleep(2.0)
    while activated:
      pass
    print 'ready with thread  ...'

  else:

    # 2) Without thread
    root.mainloop ()
    print 'ready without thread  ...'

Regards
Peter




More information about the Python-list mailing list