Creating a Button (from image) in Zelle's Graphics - python

I have a start button image that I am trying to turn into a button in my program. However, I believe I am doing the math wrong or something wrong obviously because it's not working. Basically, what I am trying to do is if the person clicks on the button, it will initiate an if statement. Any ideas? Thanks in advance!
#Assigning Mouse x,y Values
mousePt = win.getMouse()
xValue = startImage.getHeight()
yValue = startImage.getWidth()
#Assigning Buttons
if mousePt <= xValue and mousePt <= yValue:
hour = 2
startImage is the image I want to make a button. hour is a variable stated in other code.

You're comparing apples to oranges. This line:
if mousePt <= xValue and mousePt <= yValue:
is roughly the same as saying:
if Point(123, 45) <= 64 and Point(123, 45) <= 64:
It makes no sense to compare Points to widths and heights. You need to combine the widths and heights with the center position of the image and extract the X & Y values from the mouse position:
from graphics import *
win = GraphWin("Image Button", 400, 400)
imageCenter = Point(200, 200)
# 64 x 64 GIF image from http://www.iconsdb.com/icon-sets/web-2-green-icons/video-play-icon.html
startImage = Image(imageCenter, "video-play-64.gif")
startImage.draw(win)
imageWidth = startImage.getWidth()
imageHeight = startImage.getHeight()
imageLeft, imageRight = imageCenter.getX() - imageWidth/2, imageCenter.getX() + imageWidth/2
imageBottom, imageTop = imageCenter.getY() - imageHeight/2, imageCenter.getY() + imageHeight/2
start = False
while not start:
# Obtain mouse Point(x, y) value
mousePt = win.getMouse()
# Test if x,y is inside image
x, y = mousePt.getX(), mousePt.getY()
if imageLeft < x < imageRight and imageBottom < y < imageTop:
print("Bullseye!")
break
win.close()
This particular icon shows up as a circle, the area you can click includes its rectangular bounding box, some of which is outside the circle. It's possible to limit the clicks to exactly the visible image but that takes more work.

Related

How to check if a moving picture is touched to another moving picture

def check_crash():
(x,y) = c.coords(my_car)
for car in other_carss :
(car_x,car_y) = c.coords(car)
if y < (car_y+ other_cars_height) and (y + my_car_height) >= (car_y+ other_cars_height):
if x > car_x and x < (car_x + other_cars_width):
c.delete(car)
lose_a_life()
root.after(100, check_crash)
The canvas has a method named find_overlapping which will return all objects that overlap a given rectangle.

Restricting the area that PyAutoGui's mouse feature will work

I want to make a program that randomly doodles on paint, but when I leave it alone for extended periods of time, it minimizes paint and moves every one of my files around
is there any way to keep pyautogui from moving the mouse outside of a range? Thanks in advance!
import pyautogui, time, random
time.sleep(5)
pyautogui.click() # click to put drawing program in focus
distance = random.randrange(200,300)
while 6 > 0:
pyautogui.dragRel(distance, 0) # move right
distance = random.randrange(-50,50)
pyautogui.dragRel(0, distance) # move down
distance = random.randrange(-50,50)
pyautogui.dragRel(-distance, 0) # move left
distance = random.randrange(-50,50)
pyautogui.dragRel(0, -distance) # move up
I want it to stay within Top left 24,163 Bottom right 1902,996
pyautogui won't do it for you, but you can track the x and y position and ensure it remains within bounds:
import pyautogui, time, random
minx = 24
miny = 163
maxx = 1902
maxy = 996
maxmove = 50
x = (maxx-minx)/2
y = (maxy-miny)/2
time.sleep(5)
pyautogui.moveTo(x, y)
pyautogui.click() # click to put drawing program in focus
def inx(x):
return x <= maxx and x >= minx
def iny(y):
return y <= maxy and y >= miny
def xdrag(x):
distx = random.randrange(maxmove) - maxmove/2
if inx(x + distx):
x = x + distx
pyautogui.dragRel(distx, 0)
def ydrag(y):
disty = random.randrange(maxmove) - maxmove/2
if iny(y + disty):
y = y + disty
pyautogui.dragRel(0, disty)
count = 0
while count < 100: # no infinite loop
xdrag(x)
ydrag(y)
count += 1

Mapping coordinates to interact with a 2D Interaction Box

I want to detect whether or not a finger (or any object) is pointing at a certain box (on the screen) as shown in the image below.
The following code can be used to get the xy cordinates of the finger but what is the easiest way to define the interaction boxes and then map the cordinates to see if it matches any of the boxes on the outside of the screen.
I am using the latest version of the leap motion SDK (3.2.0) on Windows.
def on_frame(self, controller):
app_width = 800
app_height = 600
# Get the most recent frame and report some basic information
frame = controller.frame()
pointable = frame.pointables.frontmost
if pointable.is_valid:
iBox = frame.interaction_box
leapPoint = pointable.stabilized_tip_position
normalizedPoint = iBox.normalize_point(leapPoint, False)
app_x = normalizedPoint.x * app_width
app_y = (1 - normalizedPoint.y) * app_height
#The z-coordinate is not used
print ("X: " + str(app_x) + " Y: " + str(app_y))
The output then looks like this:
X: 467.883825302 Y: 120.019626617
X: 487.480115891 Y: 141.106081009
X: 505.537891388 Y: 164.418339729
X: 522.712898254 Y: 189.527964592
X: 539.482307434 Y: 213.160014153
X: 556.220436096 Y: 233.744287491
X: 573.109865189 Y: 253.145456314
First of all, this code won't tell you where the finger is pointing. It just tells you where the finger tip is located in space -- an important, but perhaps subtle, distinction.
Since you presumably have your boxes defined in screen coordinates, you could just check every box to see if the finger tip position is inside. Something like:
def check_in_box(box, point):
if point.x > box.left and point.x < box.right
and point.y > box.top and point.y < box.bottom:
return True
else:
return False
This assumes you have a suitable class to represent a 2D box.

How to change the coordinates of a shape (i.e. oval) in tkinter?

I am trying to make a program which when you press the S button it moves shape to the square below it on the grid. I have managed to get the shape to move the first time but after that it just keeps getting bigger.
Here is my code:
from tkinter import *
root = Tk()
global y
y = 0
x = 0
def down(event):
global y
global x
y = y+100
x = x+ 100
global pirate
canvas.delete(pirate)
pirate = canvas.create_oval((x,y), (100,100), fill = 'red')
print(y)
canvas = Canvas(root, width = 1000, height = 1000)
canvas.pack()
for a in range (10):
i = a*100
canvas.create_line((i,0), (i,1000))
for a in range (10):
i = a*100
canvas.create_line((0,i), (1000,i))
pirate = canvas.create_oval((x, y),(100, 100), fill = 'red')
root.bind('<Key - S>', down)
root.mainloop()
As ArtOfWarfare mentioned in comments, instead of creating new ovals everytime, create one and move that thing around.
def down(event):
canvas.move(pirate, 0, 100)
Above code is sufficient to move your oval one square down in your code.
Assuming you'll need to move oval other than just down, instead of binding only S to canvas, I think you should get all key events and do stuff depending on pressed char.
def keyPressed(event):
if event.char.lower() == 's': #move it down if it's S or s
canvas.move(pirate, 0, 100)
root.bind('<Key>', keyPressed) #get all key pressed events
You have a problem that in python-tk the oval is NOT specified create_oval(x,y,w,h), but create_oval(x1,y1,x2,y2). Hope that's helpful!

Checking if clicks are within a graphic object [Python Graphics Module]

Here is the module I'm using: http://mcsp.wartburg.edu/zelle/python/graphics/graphics.pdf
I want to see whether a user's clicks are within a shape or not. I used the in operator, but I know that is incorrect. Below is a chunk of my code:
win = GraphWin("Click Speed", 700, 700)
theTarget = drawTarget(win, random.randrange(0,685), random.randrange(0,685))
while theTarget in win:
click = win.getMouse()
if click in theTarget:
print("Good job")
I left out the code that draws theTarget shape because it is length and unnecessary. It is a moving circle.
I'm using a while loop so it allows me to constantly get the user's clicks.
How do I go about checking whether or not a user's clicks are in the specified Target shape by using the getMouse() command?
I'm going to have to use this in the future for more abstract shapes (not simple circles).
Circle
For the simple case of a circle, you can determine whether the mouse is inside using the distance formula. For example:
# checks whether pt1 is in circ
def inCircle(pt1, circ):
# get the distance between pt1 and circ using the
# distance formula
dx = pt1.getX() - circ.getCenter().getX()
dy = pt1.getY() - circ.getCenter().getY()
dist = math.sqrt(dx*dx + dy*dy)
# check whether the distance is less than the radius
return dist <= circ.getRadius()
def main():
win = GraphWin("Click Speed", 700, 700)
# create a simple circle
circ = Circle(Point(350,350),50)
circ.setFill("red")
circ.draw(win)
while True:
mouse = win.getMouse()
if inCircle(mouse,circ):
print ("Good job")
main()
Oval
For the more advanced example of an ellipse we will need to use a formula found here. Here is the function implemting that:
def inOval(pt1, oval):
# get the radii
rx = abs(oval.getP1().getX() - oval.getP2().getX())/2
ry = abs(oval.getP1().getY() - oval.getP2().getY())/2
# get the center
h = oval.getCenter().getX()
k = oval.getCenter().getY()
# get the point
x = pt1.getX()
y = pt1.getY()
# use the formula
return (x-h)**2/rx**2 + (y-k)**2/ry**2 <= 1
Polygon
For a polygon of abitrary shape we need to reference this. I have converted that to a python equivalent for you. Check the link to see why it works because I am honestly not sure
def inPoly(pt1, poly):
points = poly.getPoints()
nvert = len(points) #the number of vertices in the polygon
#get x and y of pt1
x = pt1.getX()
y = pt1.getY()
# I don't know why this works
# See the link I provided for details
result = False
for i in range(nvert):
# note: points[-1] will give you the last element
# convenient!
j = i - 1
#get x and y of vertex at index i
vix = points[i].getX()
viy = points[i].getY()
#get x and y of vertex at index j
vjx = points[j].getX()
vjy = points[j].getY()
if (viy > y) != (vjy > y) and (x < (vjx - vix) * (y - viy) / (vjy - viy) + vix):
result = not result
return result

Categories