Re: Threading and tkinter

2009-03-27 Thread Eric Brunel
(Sorry: replying to the wrong message here, but my newsreader somehow managed
to miss the former post...)

 On Mar 7, 9:40 am, Jani Hakala jahak...@iki.fi wrote:
  After reading the docs and seeing a few examples i think this should
  work ?
  Am I forgetting something here or am I doing something stupid ?
  Anyway I see my yellow screen, that has to count for something :)

 I have been using the following scheme:
   - Pass the root object to the thread object when creating the object
   - Define a event_handler: root.bind('SomeEvent', evt_handler) in
     the main thread.

   - When the thread has done something that the GUI part should now
     about, signal an event in the thread:
         root.event_generate('SomeEvent')    (no other arguments)

   - Call a method of the thread object in the event handler e.g. to get
     some data from a queue object.

 This ensures that only the main thread accesses Tkinter-related things.

Are you sure about that? Last time I check, doing:
root.event_generate('SomeEvent')
without any other argument called the binding directly, in the context where
it is done, so in the secondary thread. To actually switch to the thread where
the bind was done, you had to do:
root.event_generate('SomeEvent', when='tail')
to force the event to get into the event queue... Maybe it has changed in the
latest tcl/tk version (I checked this quite a long time ago on tcl/tk 8.3).


BTW, with the newer tcl/tk versions this time, be sure to compile them with
thread support ('configure ... --enebale-threads' on Unices and 'nmake ...
OPTS=threads' on Windows) if you plan to do such things. We had a lot of
problems with this trick on a tcl/tk 8.5 version not compiled with thread
support, especially when a lot of events happened in a very short time:
crashes, weird errors apparently caused by memory corruption, and so on...
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-03-25 Thread gert
On Mar 7, 9:40 am, Jani Hakala jahak...@iki.fi wrote:
  After reading the docs and seeing a few examples i think this should
  work ?
  Am I forgetting something here or am I doing something stupid ?
  Anyway I see my yellow screen, that has to count for something :)

 I have been using the following scheme:
   - Pass the root object to the thread object when creating the object
   - Define a event_handler: root.bind('SomeEvent', evt_handler) in
     the main thread.

   - When the thread has done something that the GUI part should now
     about, signal an event in the thread:
         root.event_generate('SomeEvent')    (no other arguments)

   - Call a method of the thread object in the event handler e.g. to get
     some data from a queue object.

 This ensures that only the main thread accesses Tkinter-related things.


Thanks :-)
PS why does the first example leave a running process (dos box) open
when you close the gui and yours not ?
Also root.after can make the program crash if the threat is waiting
for com1 response.
Speaking of com1 ports, for some reason I have to start up some other
serial terminal app and close it again before the device is returning
data to the python app ? Do you need to send something to the com1
device first ?

---first example--

from tkinter import *
from threading import Thread
from time import sleep

class Weegbrug(Thread):
def __init__(self):
Thread.__init__(self)
self.x=0
def run(self):
while True:
self.x=self.x+1
sleep(0.5)

w = Weegbrug()
w.start()

def display():
v.set(w.x)
root.after(500, display)

root = Tk()
v = StringVar()
txt = Label(root, textvariable=v, width=800, height=600, bg='yellow',
font=('Helvetica', 300))
txt.pack(expand=YES, fill=BOTH)
root.title('Weegbrug')
root.overrideredirect(1)
root.geometry('%dx%d+0+0' % (root.winfo_screenwidth(),
root.winfo_screenheight()))
root.after(500, display)
root.mainloop()

from tkinter import *
from threading import Thread
from queue import Queue
from time import sleep

--second example-

class Weegbrug(Thread):
def __init__(self, gui):
Thread.__init__(self)
self.gui = gui
self.queue = Queue()

def run(self):
while True:
with open('com1', 'w+') as f:
for line in f:
self.queue.put(line)
self.gui.event_generate('LineRead')
time.sleep(0.5)

def get_line(self):
return self.queue.get()

def evt_handler(*args):
v.set(w.get_line())

r = Tk()
r.title('Weegbrug')
r.overrideredirect(1)
r.geometry('%dx%d+0+0' % (r.winfo_screenwidth(),r.winfo_screenheight
()))
r.bind('LineRead', evt_handler)
v = StringVar()
v.set('0')
t = Label(r, textvariable=v, width=100, bg='yellow', font=
('Helvetica', 300))
t.pack(expand=YES, fill=BOTH)
w = Weegbrug(r)
w.start()
r.mainloop()

--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-03-07 Thread Jani Hakala
gert gert.cuyk...@gmail.com writes:

 After reading the docs and seeing a few examples i think this should
 work ?
 Am I forgetting something here or am I doing something stupid ?
 Anyway I see my yellow screen, that has to count for something :)

I have been using the following scheme:
  - Pass the root object to the thread object when creating the object
  - Define a event_handler: root.bind('SomeEvent', evt_handler) in
the main thread.

  - When the thread has done something that the GUI part should now
about, signal an event in the thread:
root.event_generate('SomeEvent')(no other arguments)

  - Call a method of the thread object in the event handler e.g. to get
some data from a queue object.

This ensures that only the main thread accesses Tkinter-related things.

from Tkinter import *
from threading import Thread

import Queue
import time

class Weegbrug(Thread):
def __init__(self, gui, file_name):
Thread.__init__(self)
self.gui = gui
self.queue = Queue.Queue()
self.file_name = file_name

def run(self):
while True:
with open(self.file_name, 'r') as f:
for line in f:
self.queue.put(line)
self.gui.event_generate('LineRead')
time.sleep(0.5)

def get_line(self):
return self.queue.get()

root = Tk()
v = StringVar()
v.set(0)
w = Weegbrug(root, '/tmp/test.py')

def evt_handler(*args):
v.set(w.get_line())
root.bind('LineRead', evt_handler)

tx = Label(root, textvariable=v, width=100, bg=yellow, font=(Helvetica, 20))
tx.pack(expand=YES, fill=BOTH)
root.title(Weegbrug)

# root.overrideredirect(1)
# root.geometry(%dx%d+0+0 % (root.winfo_screenwidth(),
# root.winfo_screenheight()))

# Don't start before there's a handler installed
w.start()
root.mainloop() 

Jani Hakala
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-03-06 Thread Aahz
[posted and e-mailed -- please reply to the group]

In article 492d5db9-3681-4ae8-827e-f2a4f66be...@v39g2000yqm.googlegroups.com,
gert  gert.cuyk...@gmail.com wrote:

After reading the docs and seeing a few examples i think this should
work ?

This is a bit late, and I don't have time to review your code, but you
should see a good example here:

http://www.pythoncraft.com/OSCON2001/index.html
-- 
Aahz (a...@pythoncraft.com)   * http://www.pythoncraft.com/

All problems in computer science can be solved by another level of 
indirection.  --Butler Lampson
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-03-06 Thread gert
On Mar 6, 7:42 pm, a...@pythoncraft.com (Aahz) wrote:
 [posted and e-mailed -- please reply to the group]

 In article 
 492d5db9-3681-4ae8-827e-f2a4f66be...@v39g2000yqm.googlegroups.com,

 gert  gert.cuyk...@gmail.com wrote:

 After reading the docs and seeing a few examples i think this should
 work ?

 This is a bit late, and I don't have time to review your code, but you
 should see a good example here:

 http://www.pythoncraft.com/OSCON2001/index.html
 --
 Aahz (a...@pythoncraft.com)           *        http://www.pythoncraft.com/

 All problems in computer science can be solved by another level of    
 indirection.  --Butler Lampson

Witch basically translate into stop being a smart ass and just do
this :)

from tkinter import *

def weegbrug():
with open('com1','r') as f:
 for l in f:
 v.set(l[2:-1])
root.after(500, weegbrug)

root = Tk()
v = StringVar()
v.set(0)
txt = Label(root, textvariable=v, width=800, height=600, bg=yellow,
font=(Helvetica, 300))
txt.pack(expand=YES, fill=BOTH)
root.title(weegbrug)
root.overrideredirect(1)
root.geometry(%dx%d+0+0 % (root.winfo_screenwidth(),
root.winfo_screenheight()))
root.after(500, weegbrug)
root.mainloop()
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-20 Thread Hendrik van Rooyen
 gert ger.@gmail.com

 Hope you do not mind ignoring part of answers, so I can figure out
 more why things work the way they are.
 This two examples work, what i do not understand is that in function
 display i do not have to declare root, v or x ?
 

x is easy - it was declared outside, in module scope, and you 
modified it after declaring it global.

The others are more subtle, and have to do with how the interpreter
searches for stuff  - first in the local scope, then up the stack in
the callers scope, up to finally in the module global scope.

That also explains why, if it is not found, you get an error message that
says Global variable x not defined (try it and see)

- Hendrik

--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-20 Thread Craig Allen

 The statement

     x=x+1

 (which, by the way, should stylistically be written

     x = x + 1


yes I was wondering what x=x+1 meant until you translated it... oh,
x = x + 1 of course! I thought to myself.

Oh wait no I'm sarcastic.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-19 Thread gert
On Feb 19, 3:20 am, Steve Holden st...@holdenweb.com wrote:
 gert wrote:
  Can you first explain why x stay's 0 please and how i should update x
  using threads ?

  fromtkinterimport *
  from _thread import start_new_thread
  from time import sleep

  x=0
  def weegbrug(x):
      while True:
          x=x+1
          sleep(0.5)
  start_new_thread(weegbrug,(x,))

  root = Tk()
  v = StringVar()
  v.set(0)
  txt = Label(root, textvariable=v, width=800, height=600, bg=yellow,
  font=(Helvetica, 300))
  txt.pack(expand=YES, fill=BOTH)
  root.title(Weegbrug)
  root.after(500, lambda:v.set(x))
  root.mainloop()

 The reason x stays at zero has nothing to do withthreading.

 The statement

     x=x+1

 (which, by the way, should stylistically be written

     x = x + 1

 if you want your code to be readable) doesn't change anything outside
 the function. Function arguments are values: since x is a parameter of
 the function, it exists only inside the function call's namespace.


Oeps :) Anyway will this x work in tkinter

from _thread import start_new_thread
from time import sleep

x=0
def weegbrug():
global x
while True:
x=x+1
sleep(0.5)
start_new_thread(weegbrug,())

while True:
print(x)
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-19 Thread Hendrik van Rooyen
 gert gert...@gmail.com wrote:


On Feb 18, 8:25 am, Hendrik van Rooyen m...@microcorp.co.za wrote:
 gert gert.cuyk...@gmail.comwrote:

  After reading the docs and seeing a few examples i think this should
  work ?
  Am I forgetting something here or am I doing something stupid ?
  Anyway I see my yellow screen, that has to count for something :)

  from tkinter import *
  from threading import Thread

  class Weegbrug(Thread):
  def __init__(self,v):
.  self.v=v
  Thread.__init__(self)
  def run(self):
  while True:
  with open('com1','r') as f:
  for line in f:
  self.v.set(line[2:-1])

 It is in general not a good idea to directly
 access GUI variables from outside the
 GUI main loop.
 There is a recipe for doing this sort of thing,
 but as usual I have lost the reference.
 What it does is that instead of interfering directly
 as above, you put the data on a queue.

 Then, you use the after() call to set up a call
 to a routine that reads the queue, and configures the
 display, and then uses after again to call itself again
 after a time, thereby keeping the GUI stuff in the GUI
 mainloop.


from tkinter import *
from threading import Thread

class Weegbrug(Thread):
def __init__(self):
self.display='0'
Thread.__init__(self)
def run(self):
x=0
while True:
x=x+1
self.display=x

Still mucking around from outside the GUI.

#with open('com1','r') as f:
# for l in f:
# self.display=l[2:-1]

root = Tk()
v = StringVar()
v.set('0')
w = Weegbrug()
w.start()
tx = Label(root, textvariable=v, width=800, height=600, bg='yellow',
font=('Helvetica', 300))
tx.pack(expand=YES, fill=BOTH)
root.title('Weegbrug')
root.overrideredirect(1)
root.geometry('%dx%d+0+0' % (root.winfo_screenwidth(),
root.winfo_screenheight()))
root.after(500, v.set(w.display))

root.after(500,displayer(q))  # You set up a stutter thread like this

root.mainloop()

Why does this not work ?
It only shows one result ?

You are only calling it once.
Read my story above again.  (And Again)
Specially the bit about putting the
values into a queue.

You need to do something like this:

def displayer(q):
  # stuff to read the queue and update the display
  root.after(500, displayer(q))# This makes sure it keeps on stuttering

Where q is an instance of Queue.Queue

There is a nice recipe by Thomas Haeller (?) but I have lost the link.

- Hendrik


--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-19 Thread gert
Hope you do not mind ignoring part of answers, so I can figure out
more why things work the way they are.
This two examples work, what i do not understand is that in function
display i do not have to declare root, v or x ?

--
example 1
--
from tkinter import *
from _thread import start_new_thread
from time import sleep

x=0
def weegbrug():
global x
while True:
x=x+1
sleep(0.5)
start_new_thread(weegbrug,())

def display():
v.set(x)
root.after(500, lambda:display())

root = Tk()
v = StringVar()
txt = Label(root, textvariable=v, width=800, height=600, bg='yellow',
font=('Helvetica', 300))
txt.pack(expand=YES, fill=BOTH)
root.title('Weegbrug')
root.overrideredirect(1)
root.geometry('%dx%d+0+0' % (root.winfo_screenwidth(),
root.winfo_screenheight()))
root.after(500, lambda:display())
root.mainloop()


--
example 2
--
from tkinter import *
from threading import Thread
from time import sleep

class Weegbrug(Thread):
def __init__(self):
self.x=0
Thread.__init__(self)
def run(self):
while True:
self.x=self.x+1
sleep(0.5)
w = Weegbrug()
w.start()

def display():
v.set(w.x)
root.after(500, lambda:display())

root = Tk()
v = StringVar()
txt = Label(root, textvariable=v, width=800, height=600, bg='yellow',
font=('Helvetica', 300))
txt.pack(expand=YES, fill=BOTH)
root.title('Weegbrug')
root.overrideredirect(1)
root.geometry('%dx%d+0+0' % (root.winfo_screenwidth(),
root.winfo_screenheight()))
root.after(500, lambda:display())
root.mainloop()
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-19 Thread Scott David Daniels

gert wrote:

Hope you do not mind ignoring part of answers, so I can figure out
more why things work the way they are.
This two examples work, what i do not understand is that in function
display i do not have to declare root, v or x ?

...


x=0
def weegbrug():
global x
while True:
x=x+1
sleep(0.5)
start_new_thread(weegbrug,())

def display():
v.set(x)
root.after(500, lambda:display())

1) Note that x, v, and root are read and manipulated, but not written.
   So, they do not need to be declared global (global is only needed
   to declare writable global names).
2) The last statement could more easily be written:
   root.after(500, display)
...

root.after(500, lambda:display())

Again you can write this:
   root.after(500, display)

--Scott David Daniels
scott.dani...@acm.org
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-18 Thread gert
On Feb 18, 8:25 am, Hendrik van Rooyen m...@microcorp.co.za wrote:
 gert gert.cuyk...@gmail.comwrote:

  After reading the docs and seeing a few examples i think this should
  work ?
  Am I forgetting something here or am I doing something stupid ?
  Anyway I see my yellow screen, that has to count for something :)

  from tkinter import *
  from threading import Thread

  class Weegbrug(Thread):
      def __init__(self,v):
          self.v=v
          Thread.__init__(self)
      def run(self):
          while True:
              with open('com1','r') as f:
                   for line in f:
                       self.v.set(line[2:-1])

 It is in general not a good idea to directly
 access GUI variables from outside the
 GUI main loop.
 There is a recipe for doing this sort of thing,
 but as usual I have lost the reference.
 What it does is that instead of interfering directly
 as above, you put the data on a queue.

 Then, you use the after() call to set up a call
 to a routine that reads the queue, and configures the
 display, and then uses after again to call itself again
 after a time, thereby keeping the GUI stuff in the GUI
 mainloop.


from tkinter import *
from threading import Thread

class Weegbrug(Thread):
def __init__(self):
self.display='0'
Thread.__init__(self)
def run(self):
x=0
while True:
x=x+1
self.display=x
#with open('com1','r') as f:
# for l in f:
# self.display=l[2:-1]

root = Tk()
v = StringVar()
v.set('0')
w = Weegbrug()
w.start()
tx = Label(root, textvariable=v, width=800, height=600, bg='yellow',
font=('Helvetica', 300))
tx.pack(expand=YES, fill=BOTH)
root.title('Weegbrug')
root.overrideredirect(1)
root.geometry('%dx%d+0+0' % (root.winfo_screenwidth(),
root.winfo_screenheight()))
root.after(500, v.set(w.display))
root.mainloop()

Why does this not work ?
It only shows one result ?
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-18 Thread Scott David Daniels

gert wrote:

After reading the docs and seeing a few examples i think this should
work ?
Am I forgetting something here or am I doing something stupid ?
Anyway I see my yellow screen, that has to count for something :)


Try this:
# tdh_show.py
from __future__ import with_statement

import time
import Tkinter
import Tkconstants as TK
import threading

class Weegbrug(threading.Thread):
def __init__(self, frame, var, filename):
self.frame = frame
self.var = var
self.filename = filename
threading.Thread.__init__(self)

def run(self):
with open(self.filename, 'r') as f:
for n, line in enumerate(f):
# the tricky bit:
self.frame.after(100, self.var.set, line.strip())
time.sleep(.5)


def main(filename):
root = Tkinter.Tk()
svar = Tkinter.StringVar(root)
frame = Tkinter.Frame(root, relief=TK.RIDGE, borderwidth=2)
frame.pack(fill=TK.BOTH, expand=1)
label = Tkinter.Label(frame, textvar=svar, bg='yellow',
  font=('Helvetica', 16))
label.pack(fill=TK.X, expand=1)
button = Tkinter.Button(frame, text=Exit, command=root.destroy)
button.pack(side=TK.BOTTOM)
reader = Weegbrug(frame, svar, filename)
button = Tkinter.Button(frame, text=Go, command=reader.start)
button.pack(side=TK.BOTTOM)
root.mainloop()


if __name__ == '__main__':
main(__file__)


--Scott David Daniels
scott.dani...@acm.org
--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-18 Thread gert
Can you first explain why x stay's 0 please and how i should update x
using threads ?

from tkinter import *
from _thread import start_new_thread
from time import sleep

x=0
def weegbrug(x):
while True:
x=x+1
sleep(0.5)
start_new_thread(weegbrug,(x,))

root = Tk()
v = StringVar()
v.set(0)
txt = Label(root, textvariable=v, width=800, height=600, bg=yellow,
font=(Helvetica, 300))
txt.pack(expand=YES, fill=BOTH)
root.title(Weegbrug)
root.after(500, lambda:v.set(x))
root.mainloop()


--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-18 Thread Steve Holden
gert wrote:
 Can you first explain why x stay's 0 please and how i should update x
 using threads ?
 
 from tkinter import *
 from _thread import start_new_thread
 from time import sleep
 
 x=0
 def weegbrug(x):
 while True:
 x=x+1
 sleep(0.5)
 start_new_thread(weegbrug,(x,))
 
 root = Tk()
 v = StringVar()
 v.set(0)
 txt = Label(root, textvariable=v, width=800, height=600, bg=yellow,
 font=(Helvetica, 300))
 txt.pack(expand=YES, fill=BOTH)
 root.title(Weegbrug)
 root.after(500, lambda:v.set(x))
 root.mainloop()
 
The reason x stays at zero has nothing to do with threading.

The statement

x=x+1

(which, by the way, should stylistically be written

x = x + 1

if you want your code to be readable) doesn't change anything outside
the function. Function arguments are values: since x is a parameter of
the function, it exists only inside the function call's namespace.

regards
 Steve

-- 
Steve Holden+1 571 484 6266   +1 800 494 3119
Holden Web LLC  http://www.holdenweb.com/

--
http://mail.python.org/mailman/listinfo/python-list


Re: Threading and tkinter

2009-02-17 Thread Hendrik van Rooyen
gert gert.cuyk...@gmail.comwrote:


 After reading the docs and seeing a few examples i think this should
 work ?
 Am I forgetting something here or am I doing something stupid ?
 Anyway I see my yellow screen, that has to count for something :)
 
 from tkinter import *
 from threading import Thread
 
 class Weegbrug(Thread):
 def __init__(self,v):
 self.v=v
 Thread.__init__(self)
 def run(self):
 while True:
 with open('com1','r') as f:
  for line in f:
  self.v.set(line[2:-1])

It is in general not a good idea to directly
access GUI variables from outside the
GUI main loop.
There is a recipe for doing this sort of thing,
but as usual I have lost the reference.
What it does is that instead of interfering directly
as above, you put the data on a queue.

Then, you use the after() call to set up a call
to a routine that reads the queue, and configures the
display, and then uses after again to call itself again
after a time, thereby keeping the GUI stuff in the GUI 
mainloop.

HTH - Hendrik



--
http://mail.python.org/mailman/listinfo/python-list