Reputation: 443
I am creating a simple drawing program using Zelle's graphics.py in Python
I have a rectangular drawing area and I am trying to get my drawing to stay within the confines of the rectangle without overlap. One of the challenges is that any drawn object is close to the line of the boundaries of the rectangle (although not technically not outside the drawing area) will draw anyway and cause overlap (see attached image)
Here is what I worked on (NOTE : I have not included this practice code because it is included in the main code):
PRACTICE and TESTING
I then took the formula into my drawing program to test if it would work. Right away, I had to use a clone() for the circle because the "for loop" was drawing the same object in the same place over and over giving an error.
After that was fixed, I still could not get the "for loop" and circle formula to work for me. I then thought about removing all items from the win.items[:] list IF the drawing was outside of the boundary of the rectangle. I tried this and still could not get it to work. Here is the code of the attempt.
from graphics import *
import random
import math
win = GraphWin("DRAG", 500, 500)
win.master.attributes('-topmost', True)
drawrect=Rectangle(Point(50,50),Point(450,300))
drawrect.setFill("white")
drawrect.draw(win)
testlist=[]
def motion(event):
global radius
x1, y1 = event.x, event.y
if (x1 > 50 and x1 < 450) and (y1 > 50 and y1 < 300):
circ = Circle(Point(x1, y1), radius)
circ.setFill("black")
circ1 = circ.clone()
cx = circ.getCenter().getX()
cy = circ.getCenter().getY()
for i in range(0, 360):
x = radius * math.cos(i) + cx
y = radius * math.sin(i) + cy
if (x > 50 and x < 450) and (y > 50 and y < 300):
circ1 = circ.clone()
circ1.draw(win)
print("drawing")
else:
circ1 = circ.clone()
testlist.append(circ1)
print(testlist)
print(win.items)
for item in win.items[1:]:
print("This is ITEM in win.items list:", item)
if item in testlist:
input("YES - input waiting for enter")
for i in win.items[1:]:
circ.undraw()
circ1.undraw()
win.update()
else:
input("NO - input waiting for enter")
radius = 40
win.bind('<B1-Motion>', motion)
win.mainloop()
Upvotes: 0
Views: 854
Reputation: 142681
If you want only full circles then you need only
if (50+radius < x1 < 450-radius) and (50+radius < y1 < 300-radius):
like
def motion(event):
x1, y1 = event.x, event.y
if (50+radius < x1 < 450-radius) and (50+radius < y1 < 300-radius):
circ = Circle(Point(x1, y1), radius)
circ.setFill("black")
circ.draw(win)
Full code:
from graphics import *
# --- functions ---
def motion(event):
x1, y1 = event.x, event.y
if (50+radius < x1 < 450-radius) and (50+radius < y1 < 300-radius):
circ = Circle(Point(x1, y1), radius)
circ.setFill("black")
circ.draw(win)
# --- main ---
radius = 40
win = GraphWin("DRAG", 500, 500)
#win.master.attributes('-topmost', True)
drawrect = Rectangle(Point(50, 50), Point(450, 300))
drawrect.setFill("white")
drawrect.draw(win)
win.bind('<B1-Motion>', motion)
win.mainloop()
EDIT:
If you would to crop circles then it would be problem.
My first idea was to use directly tkinter.Canvas()
and it will crop elements. But it would need to write all code for drawing Circle
and other objects.
So I took code from GraphicWin()
which is tkinter.Canvas()
with all functions to draw Circle
and other objects and little modify - and now you can put in window similar to other objects.
from graphics import *
# --- functions ---
class Canvas(GraphWin):
"""A GraphWin is a toplevel window for displaying graphics."""
def __init__(self, master, x, y, width=200, height=200, autoflush=True, **kwarg):
tk.Canvas.__init__(self, master, width=width, height=height,
highlightthickness=0, bd=0, **kwarg)
self.x = x
self.y = y
#self.foreground = "black"
self.items = []
self.mouseX = None
self.mouseY = None
self.bind("<Button-1>", self._onClick)
self.bind_all("<Key>", self._onKey)
self.height = int(height)
self.width = int(width)
self.autoflush = autoflush
self._mouseCallback = None
self.trans = None
self.closed = False
self.lastKey = ""
if autoflush: update() # it needs to use `import *`
def draw(self, canvas):
self.id = canvas.create_window((self.x, self.y), window=self._w, anchor='nw')
# --- functions ---
def motion1(event):
x1, y1 = event.x, event.y
circ = Circle(Point(x1, y1), radius)
circ.setFill("black")
#circ.setOutline("red")
circ.draw(canvas1)
def motion2(event):
x1, y1 = event.x, event.y
circ = Circle(Point(x1, y1), radius)
circ.setFill("red")
circ.setOutline("red")
circ.draw(canvas2)
# --- main ---
radius = 40
win = GraphWin("DRAG", 500, 700)
#win.master.attributes('-topmost', True)
# Canvas(win, x, y, width, height, ...)
canvas1 = Canvas(win, 50, 50, 400, 250, bg='white')
canvas1.draw(win)
canvas1.bind('<B1-Motion>', motion1)
canvas2 = Canvas(win, 50, 350, 400, 250, bg='white')
canvas2.draw(win)
canvas2.bind('<B1-Motion>', motion2)
# draw on canvas
r = Rectangle(Point(100, 100), Point(150, 150))
r.setFill('red')
r.setOutline("red")
r.draw(canvas1)
win.mainloop()
EDIT:
This better shows that circles are croped.
Upvotes: 1