ANNOUNCE: netdraw.py
Issac
issac at myfirstlink.net
Fri Dec 28 04:35:57 EST 2001
Here's a networked drawing program for collaborative drawing with two people.
The first person to start the program runs the script with no arguments:
$ python netdraw.py
The second person must specify the host, unless it's just localhost:
$ python netdraw.py my_friends_host.widgets.com
Anything you draw on your side will show up on your friend's side and vice-versa.
Issac
-----%<-----
#!/usr/bin/env python
"""
netdraw.py: not exactly a paint prog. just a networked line drawing demo
version 0.0.0
paint program by dave michell. networking added by issac (Dec. 2001).
"""
import Tkinter,sys,socket,string,struct,thread
def recv_nbytes(sock, nbytes):
'''\
def recv_nbytes(sock, nbytes):
Receive n bytes from the socket.
_Effective TCP/IP_ p. 51
'''
count = nbytes
buf = ''
while count > 0:
chunk = sock.recv(count)
assert len(chunk) <= count
count = count - len(chunk)
buf = buf + chunk
assert len(buf) == nbytes
return buf
class NetDrawApp:
DEFAULT_PORT = 50007
DEFAULT_HOST = 'localhost'
MAX_NUM_CLIENTS = 1 # changing this will break the code a little
def __init__(self):
self.set_up_socket()
self.root = Tkinter.Tk()
self.drawing_area = Tkinter.Canvas(self.root)
self.drawing_area.pack()
self.drawing_area.bind("<Motion>", lambda evt, x=self: x.motion(evt))
self.drawing_area.bind("<ButtonPress-1>", lambda evt, x=self: x.b1down(evt))
self.drawing_area.bind("<ButtonRelease-1>", lambda evt, x=self: x.b1up(evt))
self.b1 = "up"
self.xold = None
self.yold = None
thread.start_new_thread(self.read_lines_from_socket, ())
def read_lines_from_socket(self):
while 1:
# get the next line from the socket
line_rec = recv_nbytes(self.sock, nbytes = 16)
x0,y0,x1,y1 = struct.unpack('iiii', line_rec)
self.drawing_area.create_line(x0,y0,x1,y1,smooth=1)
self.root.update()
#print 'got the line and drew it'
def set_up_socket(self):
if len(sys.argv) < 2: self.hostname = NetDrawApp.DEFAULT_HOST
else: self.hostname = sys.argv[1]
if len(sys.argv) < 3: self.portnum = NetDrawApp.DEFAULT_PORT
else: self.portnum = string.atoi(sys.argv[2])
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# if peer is already up, act like a client
self.sock.connect((self.hostname, self.portnum))
print 'connected to '+self.hostname+' on port '+`self.portnum`
except:
print "waiting for connection on port "+`self.portnum`
# peer is not up yet, so we'll just wait around like a server
self.listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listen_sock.bind(('', self.portnum))
self.listen_sock.listen(NetDrawApp.MAX_NUM_CLIENTS)
self.sock, self.addr = self.listen_sock.accept()
print 'got connection from '+`self.addr`
def b1down(self, event):
self.b1 = "down" # you only want to draw when the button is down
# because "Motion" events happen -all the time-
def b1up(self, event):
self.b1 = "up"
self.xold = None # reset the line when you let go of the button
self.yold = None
def motion(self, event):
if self.b1 == "down":
if self.xold != None and self.yold != None:
# here's where you draw it. smooth. neat.
event.widget.create_line(self.xold, self.yold,
event.x,event.y,smooth=1)
line_rec = struct.pack('iiii', self.xold, self.yold, event.x, event.y)
#print 'sending data'
try: self.sock.send(line_rec)
except: print 'error sending data: ',sys.exc_info()[0]
else: pass # print 'done sending data'
self.xold = event.x
self.yold = event.y
def run(self):
try:
self.root.update()
self.root.mainloop()
except Tkinter.TclError:
try: self.root.destroy()
except: pass
def main():
app = NetDrawApp()
app.run()
if __name__ == "__main__":
main()
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.310 / Virus Database: 171 - Release Date: 12/19/2001
More information about the Python-list
mailing list