- Google+ Tools
-
Make Google+ profile picture
Make Google plus banners for profile
Create and share your Google Plus profile banners.
-
A simple, yet effective rectangle selection box. :)
Works with a tkinter canvas! Just add the class and set it up like in the example code. The cross heir was my own touch, the RectTracker only draws a box.
Have fun! And please don't just vote down, post what you don't like if you don't like it.
Python Tkinter Canvas Rectangle Selection Box
"""Rect Tracker class for Python Tkinter Canvas"""
def groups(glist, numPerGroup=2):
result = []
i = 0
cur = []
for item in glist:
if not i < numPerGroup:
result.append(cur)
cur = []
i = 0
cur.append(item)
i += 1
if cur:
result.append(cur)
return result
def average(points):
aver = [0,0]
for point in points:
aver[0] += point[0]
aver[1] += point[1]
return aver[0]/len(points), aver[1]/len(points)
class RectTracker:
def __init__(self, canvas):
self.canvas = canvas
self.item = None
def draw(self, start, end, **opts):
"""Draw the rectangle"""
return self.canvas.create_rectangle(*(list(start)+list(end)), **opts)
def autodraw(self, **opts):
"""Setup automatic drawing; supports command option"""
self.start = None
self.canvas.bind("<Button-1>", self.__update, '+')
self.canvas.bind("<B1-Motion>", self.__update, '+')
self.canvas.bind("<ButtonRelease-1>", self.__stop, '+')
self._command = opts.pop('command', lambda *args: None)
self.rectopts = opts
def __update(self, event):
if not self.start:
self.start = [event.x, event.y]
return
if self.item is not None:
self.canvas.delete(self.item)
self.item = self.draw(self.start, (event.x, event.y), **self.rectopts)
self._command(self.start, (event.x, event.y))
def __stop(self, event):
self.start = None
self.canvas.delete(self.item)
self.item = None
def hit_test(self, start, end, tags=None, ignoretags=None, ignore=[]):
"""
Check to see if there are items between the start and end
"""
ignore = set(ignore)
ignore.update([self.item])
# first filter all of the items in the canvas
if isinstance(tags, str):
tags = [tags]
if tags:
tocheck = []
for tag in tags:
tocheck.extend(self.canvas.find_withtag(tag))
else:
tocheck = self.canvas.find_all()
tocheck = [x for x in tocheck if x != self.item]
if ignoretags:
if not hasattr(ignoretags, '__iter__'):
ignoretags = [ignoretags]
tocheck = [x for x in tocheck if x not in self.canvas.find_withtag(it) for it in ignoretags]
self.items = tocheck
# then figure out the box
xlow = min(start[0], end[0])
xhigh = max(start[0], end[0])
ylow = min(start[1], end[1])
yhigh = max(start[1], end[1])
items = []
for item in tocheck:
if item not in ignore:
x, y = average(groups(self.canvas.coords(item)))
if (xlow < x < xhigh) and (ylow < y < yhigh):
items.append(item)
return items
def main():
from random import shuffle
canv = Canvas(width=500, height=500)
canv.create_rectangle(50, 50, 250, 150, fill='red')
canv.pack(fill=BOTH, expand=YES)
rect = RectTracker(canv)
# draw some base rectangles
rect.draw([50,50], [250, 150], fill='red', tags=('red', 'box'))
rect.draw([300,300], [400, 450], fill='green', tags=('gre', 'box'))
# just for fun
x, y = None, None
def cool_design(event):
global x, y
kill_xy()
dashes = [3, 2]
x = canv.create_line(event.x, 0, event.x, 1000, dash=dashes, tags='no')
y = canv.create_line(0, event.y, 1000, event.y, dash=dashes, tags='no')
def kill_xy(event=None):
canv.delete('no')
canv.bind('<Motion>', cool_design, '+')
# command
def onDrag(start, end):
global x,y
items = rect.hit_test(start, end)
for x in rect.items:
if x not in items:
canv.itemconfig(x, fill='grey')
else:
canv.itemconfig(x, fill='blue')
rect.autodraw(fill="", width=2, command=onDrag)
mainloop()
if __name__ == '__main__':
try:
from tkinter import *
except ImportError:
from Tkinter import *
main()
Comments
blog comments powered by Disqus