Mailing List Archive

Tkinter & socket question
Hello,

I am writing a little chat program in Python and Tkinter. I can't figure =
out
two things though:

1) When there's no connection, I don't want people to use the Entry on th=
e
window (which is used to enter text and send it after pressing Enter). So=
, I
want to disable it. I used entry.state =3D DISABLED, but I still can ente=
r text.
Is this normal? Is there a way to make it "unusable"?

2) I need to poll the connection periodically, say, every second. This wo=
uld
not have been a problem in console mode... I don't know how to do this in=
a
Tkinter environment though. So, how can I do something every second (or e=
very
n milliseconds, or whatever the time span may be)? Are threads the way to=
go?
I haven't used them before.

Thanks,
Def P


____________________________________________________________________
Get free e-mail and a permanent address at http://www.netaddress.com/?N=3D=
1
Tkinter & socket question [ In reply to ]
On Fri, 18 Jun 1999 21:54:11 GMT, Def P wrote:
>2) I need to poll the connection periodically, say, every second. This would
>not have been a problem in console mode... I don't know how to do this in a
>Tkinter environment though. So, how can I do something every second (or every
>n milliseconds, or whatever the time span may be)? Are threads the way to go?
>I haven't used them before.

Well you can always check for a recv() that returns a zero-length
buffer. That means that the other end has closed connection.

--C

--
Constantinos A. Kotsokalis || C.Kotsokalis@ece.ntua.gr
National Technical University of Athens - GREECE
Electrical and Computer Engineering Department
"Bus error -- driver executed."
Tkinter & socket question [ In reply to ]
On 18 Jun 99, Constantinos A. Kotsokalis wrote:

> On Fri, 18 Jun 1999 21:54:11 GMT, Def P wrote:
> >2) I need to poll the connection periodically, say, every second. This would
> >not have been a problem in console mode... I don't know how to do this in a
> >Tkinter environment though. So, how can I do something every second (or every
> >n milliseconds, or whatever the time span may be)? Are threads the way to go?
> >I haven't used them before.
>
> Well you can always check for a recv() that returns a zero-length
> buffer. That means that the other end has closed connection.

That is a nice way to detect disconnection, but I think the question
was, how to receive messages from the other side? In console mode you
can simply do a while loop with recv() in it and check what comes
back. This is not so straightforward in Tk, you are either in
mainloop or in your own loop, and unless there's some special event
in Tk which can be called periodically, I don't know how to do this
either.

--Hans Nowak (ivnowa@hvision.nl)
Homepage: http://fly.to/zephyrfalcon
Tkinter & socket question [ In reply to ]
>2) I need to poll the connection periodically, say, every second. This would
>not have been a problem in console mode... I don't know how to do this in a
>Tkinter environment though. So, how can I do something every second (or every
>n milliseconds, or whatever the time span may be)? Are threads the way to go?
>I haven't used them before.

Wow, a question I can answer.... amazing.
Obligatory-Mandatory-Necessary-Essential Disclaimer: I bear no
resemblance whatsoever to a python wizard, I just happen to have done
something like what you want to do. There's almost definitely a
better way of doing this, but my method seems to work.

I assume that you have already opened a nonblocking socket connection,
and that that is what you are polling. Your main Tkinter window has a
method called "after" which can be used to do the polling.
Documentation can be found at:
http://www.pythonware.com/library/tkinter/introduction/x8550-alarm-handlers-and-other.htm

An example, in my stupid little networked python game, I have the
following polling function:
def ListenForMessages(self):
msg = None
theConn = None

# Check to see if we are the client or the server
if self.serverActive == 1:
if self.clientConn is None:
print "No Client!"
return
theConn = self.clientConn
elif self.clientActive == 1:
theConn = self.socket

if theConn is None: return

# see if there is anything there to read
try:
msg = theConn.recv(1024)
# Got it! Dispatch the message.
self.Dispatch(self.message.Type(msg),msg)
except error:
# nope... no one loves us.
pass

# re-register the after callback, with a 200msec delay
self.listenID = self.Game.rootWin.after(200,self.ListenForMessages)

The last line is important, because the after callback is removed
after being called. So it needs to be re-registered with Tk.

The callback is first registered immediately upon establishing the
socket connection.


I hope this helps,
-greg

--
---------------------
Dr. Greg Landrum (landrumSPAM@foreman.ac.rwth-aachen.de)
Institute of Inorganic Chemistry
Aachen University of Technology
Tkinter & socket question [ In reply to ]
Gregory A. Landrum <landrum@foreman.ac.rwth-aachen.de> wrote:

:>2) I need to poll the connection periodically, say, every second. This would
:>not have been a problem in console mode... I don't know how to do this in a
:>Tkinter environment though. So, how can I do something every second (or every
:>n milliseconds, or whatever the time span may be)? Are threads the way to go?
:>I haven't used them before.

: Wow, a question I can answer.... amazing.
: Obligatory-Mandatory-Necessary-Essential Disclaimer: I bear no
: resemblance whatsoever to a python wizard, I just happen to have done
: something like what you want to do. There's almost definitely a
: better way of doing this, but my method seems to work.

: I assume that you have already opened a nonblocking socket connection,
: and that that is what you are polling. Your main Tkinter window has a
: method called "after" which can be used to do the polling.
: Documentation can be found at:
: http://www.pythonware.com/library/tkinter/introduction/x8550-alarm-handlers-and-other.htm

: An example, in my stupid little networked python game, I have the
: following polling function:
: def ListenForMessages(self):
: msg = None
: theConn = None
:
: # Check to see if we are the client or the server
: if self.serverActive == 1:
: if self.clientConn is None:
: print "No Client!"
: return
: theConn = self.clientConn
: elif self.clientActive == 1:
: theConn = self.socket

: if theConn is None: return

: # see if there is anything there to read
: try:
: msg = theConn.recv(1024)
: # Got it! Dispatch the message.
: self.Dispatch(self.message.Type(msg),msg)
: except error:
: # nope... no one loves us.
: pass

: # re-register the after callback, with a 200msec delay
: self.listenID = self.Game.rootWin.after(200,self.ListenForMessages)

: The last line is important, because the after callback is removed
: after being called. So it needs to be re-registered with Tk.

: The callback is first registered immediately upon establishing the
: socket connection.

You can also deal directly with Tcl/Tk's filehandler:

from Tkinter import tkinter
self.root.tk.createfilehandler(socket, tkinter.READABLE,
self.handle_msg
)
...
self.root.tk.deletefilehandler(socket)

The mainloop() method handles the rest for you.

-Arcege
Tkinter & socket question [ In reply to ]
Hello,

I have had a lot of experience with socket/Tkinter over the years
and have one simple recommendation. If you are going to use a
lot of event based updates of UI's based on socket interactions,
use the tcl sockets instantiated in a tcl interpreter inside
of your GUI program. The createfilehandler is not supported
on Windows any longer (starting with tcl/tk 8.0). Using after()
and polling are alternatives, but using the native tcl sockets
will put everything in the tcl/tk event loop (this is my humble
opinion, so take it for what it is worth). I have used native
python sockets but the limitation is really on the tcl/tk side,
not the python side. Another bonus is tcl handles more of
the socket housecleaning stuff.

Here's some code snips to do some simple socket serving inside
of Python using the tcl sockets layer. This example is not fully
functional but hopefully this gives you ideas. It is based on
prior postings in this newsgroup.

Regards,

Matt
--------------------------------------------------------------
import Tkinter

class _Callback:
""" A foundation class used for representing callbacks.
Methods added by this class:

__call__() - Apply function for the callback

"""

# =========================================================================

def __init__(self, callback):
self.callback = callback
self.name = "cb%d" % id(self)

# =========================================================================

def __call__(self, *args):
return apply(self.callback, args)

class Server:

def __init__(self):

self.acceptCb = _Callback(self.acceptRequest)
self.connection.tk.createcommand(self.acceptCb.name, self.acceptCb)
self.handleCb = _Callback(self.handleRequest)
self.connection.tk.createcommand(self.handleCb.name, self.handleCb)

self.connection = Tkinter.Tk()
self.connection.withdraw()


#=================================================================================
def acceptRequest(self, sock, addr, port):
# Accept the connection request
self.connection.tk.eval('fconfigure ' + sock + ' -buffering none')
self.connection.tk.eval('fconfigure ' + sock + ' -translation binary')
self.connection.tk.eval('fileevent ' + sock + ' readable [list ' + self.handleCb.name + ' '
+ sock + ' ' + addr + ' ' + port + ']')

#=================================================================================
def handleRequest(self, sock, addr, port):
try:
self.processMessage( sock, addr )
except _ClientShutdown:
self.handleClientShutdown( sock, addr )
except:
print 'error'

....
def serveForever(self):
self.connection.tk.mainloop()


------------------------------------------------------------------------------------

Michael P. Reilly wrote:

> Gregory A. Landrum <landrum@foreman.ac.rwth-aachen.de> wrote:
>
> :>2) I need to poll the connection periodically, say, every second. This would
> :>not have been a problem in console mode... I don't know how to do this in a
> :>Tkinter environment though. So, how can I do something every second (or every
> :>n milliseconds, or whatever the time span may be)? Are threads the way to go?
> :>I haven't used them before.
>
> : Wow, a question I can answer.... amazing.
> : Obligatory-Mandatory-Necessary-Essential Disclaimer: I bear no
> : resemblance whatsoever to a python wizard, I just happen to have done
> : something like what you want to do. There's almost definitely a
> : better way of doing this, but my method seems to work.
>
> : I assume that you have already opened a nonblocking socket connection,
> : and that that is what you are polling. Your main Tkinter window has a
> : method called "after" which can be used to do the polling.
> : Documentation can be found at:
> : http://www.pythonware.com/library/tkinter/introduction/x8550-alarm-handlers-and-other.htm
>
> : An example, in my stupid little networked python game, I have the
> : following polling function:
> : def ListenForMessages(self):
> : msg = None
> : theConn = None
> :
> : # Check to see if we are the client or the server
> : if self.serverActive == 1:
> : if self.clientConn is None:
> : print "No Client!"
> : return
> : theConn = self.clientConn
> : elif self.clientActive == 1:
> : theConn = self.socket
>
> : if theConn is None: return
>
> : # see if there is anything there to read
> : try:
> : msg = theConn.recv(1024)
> : # Got it! Dispatch the message.
> : self.Dispatch(self.message.Type(msg),msg)
> : except error:
> : # nope... no one loves us.
> : pass
>
> : # re-register the after callback, with a 200msec delay
> : self.listenID = self.Game.rootWin.after(200,self.ListenForMessages)
>
> : The last line is important, because the after callback is removed
> : after being called. So it needs to be re-registered with Tk.
>
> : The callback is first registered immediately upon establishing the
> : socket connection.
>
> You can also deal directly with Tcl/Tk's filehandler:
>
> from Tkinter import tkinter
> self.root.tk.createfilehandler(socket, tkinter.READABLE,
> self.handle_msg
> )
> ...
> self.root.tk.deletefilehandler(socket)
>
> The mainloop() method handles the rest for you.
>
> -Arcege