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