canvassing for assistance

S

Sean McIlroy

Hi all!

I've written a utility for making diagrams. It could also be a good
environment for experimenting with a Tk canvas, so I'm including the
code here (see below). The problem is that, when I save a canvas and
include the resulting postscript file in a LaTeX document, I often
find that the right edge of the canvas has been cut off and/or that
there's a bunch of extra space at the bottom that forces the picture
to take up a whole page just by itself. The Introduction to Tkinter
lists a bunch of options for the Canvas postscript method, but it
doesn't say anything about the semantics of any of them, and there are
several that sound like they could be what I need. So, if anybody
knows how to exercise finer control over the Canvas postscript method,
I'd be grateful to hear about it.

Peace,
STM


###############################################
## FRESH SHELL: import canvasser
## (so that text can be copied from the shell)
###############################################

pencil = 1
eraser = 10
color = 'black'

def save():
from tkSimpleDialog import askstring
filename = askstring('save diagram','enter name of diagram: ') +
'.eps'
canvas.postscript(file=filename,width=100,height=100,pagewidth=100,pageheight=100)

def circle(x,y,radius=25,color=None):
r = radius
return canvas.create_oval(x-r,y-r,x+r,y+r,fill=color)

#################################################################################

__P__ = None
__I__ = None

def draw(event):
global __P__
Q = [event.x,event.y]
canvas.create_line(__P__[0],__P__[1],Q[0],Q[1],width=pencil,fill=color)
__P__ = Q

def erase(event):
r = eraser
x,y = event.x,event.y
for x in canvas.find_overlapping(x-r,y-r,x+r,y+r):
canvas.delete(x)

def carry(event):
if __I__==None: return
C = canvas.coords(__I__)
x,y = event.x,event.y
if len(C)==2: canvas.coords(__I__,x,y)
else:
a,b = C[:2]
f = lambda i: ( i%2 and [y-b] or [x-a] ) [0]
D = [x,y] + [C + f(i) for i in range(2,len(C))]
canvas.coords(__I__,*D)

def scale(event):
C = canvas.coords(__I__)
if len(C)<>4: return
canvas.coords(__I__,C[0],C[1],event.x,event.y)

def point(event):
codeArea.insert(INSERT,str(event.x) + ',' + str(event.y))

def item(event):
codeArea.insert(INSERT,str(canvas.find_closest(event.x,event.y)[0]))

def mouseDown(event):
global __P__,__I__
m = mode.get()
if m==0: __P__ = [event.x,event.y]
elif m==2: point(event)
elif m==3: item(event)
elif m>=4: __I__ = canvas.find_closest(event.x,event.y)

def mouseDrag(event):
m = mode.get()
if m==0: draw(event)
elif m==1: erase(event)
elif m==4: carry(event)
elif m==5: scale(event)

def mouseUp(event):
global __P__,__I__
__P__ = None
__I__ = None

def runCode(dummy):
x = codeArea.get()
y = [i for i in range(len(x)) if x=='=' and
x[:i].count('(')==0]
z = y and x[:y[0]] + '=' + x[y[0]+1:] or x
print '>>> ' + z
try: exec z in globals()
except: print 'ERROR'
codeArea.delete(0,END)

from Tkinter import *
print '*'*80
print 'REMINDER: canvas; pencil,eraser,color; save,circle'
print '*'*80
root = Tk()
canvas = Canvas(root,background='white')
canvas.bind('<Button-1>',mouseDown)
canvas.bind('<B1-Motion>',mouseDrag)
canvas.bind('<ButtonRelease-1>',mouseUp)
canvas.pack(side=TOP,expand=1,fill=BOTH)
codeArea = Entry(root,font=6)
codeArea.pack(side=TOP,expand=1,fill=X)
codeArea.bind('<Return>',runCode)
ctrl = Frame(root)
mode = IntVar()
Radiobutton(ctrl,indicatoron=0,variable=mode,value=0,text='draw').pack(side=LEFT)
Radiobutton(ctrl,indicatoron=0,variable=mode,value=1,text='erase').pack(side=LEFT)
Radiobutton(ctrl,indicatoron=0,variable=mode,value=2,text='point').pack(side=LEFT)
Radiobutton(ctrl,indicatoron=0,variable=mode,value=3,text='item').pack(side=LEFT)
Radiobutton(ctrl,indicatoron=0,variable=mode,value=4,text='carry').pack(side=LEFT)
Radiobutton(ctrl,indicatoron=0,variable=mode,value=5,text='scale').pack(side=LEFT)
ctrl.pack(side=TOP,pady=10)
root.title('canvasser')
root.mainloop()
 
S

stewart.midwinter

Sean, nice work on canvasser! One question: what is the purpose of
'scale'? I notice that if you have already drawn a line on the canvas,
then 'scale' can be used to draw a straight-line element extending from
the end of the previous freehand line, but if you start with a blank
screen, 'scale' has no effect.

BTW if you want to extend your app further, take a look at paint.py in
the Vaults of Parnassus:
http://py.vaults.ca/apyllo.py?i=173784088

cheers,
S
 
S

Sean McIlroy

'scale' puts the lower-right corner of a bounding box where the
pointer is, while keeping the upper-left corner where it was before
(or, if the relevant item's coordinates aren't of bounding-box type,
the function does nothing).

Thanks for the link.

Peace,
STM
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top