python - How to recognize images and click on them - python

I would like to make a script that clicks on images depending on what is asked, it needs to go trough a list of images. so for example if the user is asked by the program to click on the green circle:
question_list = greencircle, redcircle, bluesquare, redtriangle
if(greencircle == greencircle.png){
pyautogui.click(greencircle.png)
}
could someone help with this?

PyAutoGUI has a built in function called locateOnScreen() which returns the x, y coordinates of the center of the image if it can find it on the current screen (it takes a screenshot and then analyzes it).
The image has to match exactly for this to work; i.e. if you want to click on a button.png that button picture has to be the same exact size / resolution as the button in your windows for the program to recognize it. One way to achieve this is to take a screenshot, open it in paint and cut out only the button you want pressed (or you could have PyAutoGUI do it for you as I'll show in a later example).
import pyautogui
question_list = ['greencircle', 'redcircle', 'bluesquare', 'redtriangle']
user_input = input('Where should I click? ')
while user_input not in question_list:
print('Incorrect input, available options: greencircle, redcircle, bluesquare, redtriangle')
user_input = input('Where should I click?')
location = pyautogui.locateOnScreen(user_input + '.png')
pyautogui.click(location)
The above example requires you to already have greencircle.png and all the other .png in your directory
PyAutoGUI can also take screenshots and you can specify which region of the screen to take the shot pyautogui.screenshot(region=(0, 0, 0, 0)) The first two values are the x,y coordinates for the top left of the region you want to select, the third is how far to the right(x) and the fourth is how far down (y).
This following example takes a screenshot of the Windows 10 Logo, saves it to a file, and then clicks on the logo by using the specified .png file
import pyautogui
pyautogui.screenshot('win10_logo.png', region=(0, 1041, 50, 39))
location = pyautogui.locateOnScreen('win10_logo.png')
pyautogui.click(location)
You also don't have to save the screenshot to a file, you can just save it as a variable
import pyautogui
win10 = pyautogui.screenshot(region=(0, 1041, 50, 39))
location = pyautogui.locateOnScreen(win10)
pyautogui.click(location)
Making a program detect if a user has clicked in a certain area (let's say, the windows 10 logo) would require another library like pynput.
from pynput.mouse import Listener
def on_click(x, y, button, pressed):
if 0 < x < 50 and 1080 > y > 1041 and str(button) == 'Button.left' and pressed:
print('You clicked on Windows 10 Logo')
return False # get rid of return statement if you want a continuous loop
with Listener(on_click=on_click) as listener:
listener.join()
PUTTING IT ALL TOGETHER
import pyautogui
from pynput.mouse import Listener
win10 = pyautogui.screenshot(region=(0, 1041, 50, 39))
location = pyautogui.locateOnScreen(win10)
# location[0] is the top left x coord
# location[1] is the top left y coord
# location[2] is the distance from left x coord to right x coord
# location[3] is the distance from top y coord to bottom y coord
x_boundary_left = location[0]
y_boundary_top = location[1]
x_boundary_right = location[0] + location[2]
y_boundary_bottom = location[1] + location[3]
def on_click(x, y, button, pressed):
if x_boundary_left < x < x_boundary_right and y_boundary_bottom > y > y_boundary_top and str(button) == 'Button.left' and pressed:
print('You clicked on Windows 10 Logo')
return False # get rid of return statement if you want a continuous loop
with Listener(on_click=on_click) as listener:
listener.join()

Related

How to make a python application that detects a color and when detected presses a button on the keyboard?

I am trying to write an application that constantly checks for a color and when detected, presses the e button once.
import pyautogui
import time
color = (1, 72, 132)
def clicker():
while True:
x, y = pyautogui.position()
pixelColor = pyautogui.screenshot().getpixel((x, y))
if pixelColor == color:
pyautogui.press('e')
def main():
while True:
clicker()
main()
I only got this but it does not work at all.
To get a tuple of RGB colors at the current mouse position I use this
pixel = pyautogui.pixel(*pyautogui.position())

how do i keep a key pressed using pyautogui?

i am very new to coding and am making a macro for a game that after seing the specified color it will move the cursor to said color.
the code goes:
from time import sleep
import pyautogui
x=1
color = (166, 166, 61)
sleep(5)
while x==1:
s = pyautogui.screenshot()
pyautogui.keyDown("space")
for x in range(1171, 1172):
for y in range(544, 990):
if s.getpixel((x, y)) == color:
pyautogui.moveTo((x,y))
pyautogui.keyUp("space")
sleep(38)
the thing is that the space bar is not held like it would be if a player held it down as the menu connected to it doesn't open. Is there any way for me to simulate pressing the space bar so that it acts like it was pressed irl?

Check for mouse press while mouse moves

I'm making a simple program that randomly moves my mouse to farm hours on sites like VHL. I want to add a section of code that stops the code from running when the mouse button is pressed.
So far I have this:
# imports
import random
import time
import pyautogui
# screen resolution - 2256, 1504
while True: # constantly runs, constantly updates variables
# vars that need to update part
posX = random.randint(0, 2256) # get a random x coordinate
posY = random.randint(0, 1504) # get a random y coordinate
randDuration = random.randint(2, 10) # get a random duration for mouse movement
randSleep = random.randint(5, 100) # get a random sleep time
# code part
pyautogui.moveTo(posX, posY, randDuration) # moves cursor to random coordinates from defined variables
print(f"Cursor moved to x:{posX} y:{posY} in {randDuration} seconds!")
time.sleep(randSleep)
from pynput.mouse import Listener
def is_clicked(x, y, button, pressed): # function that stops code after mouse1 is pressed
if pressed:
exit()
with Listener(on_click=is_clicked) as listener:
listener.join()
Everything works fine, but I want to be able to stop the program while the mouse is moving. In other words, while the line below runs:
pyautogui.moveTo(posX, posY, randDuration)
I want to simultaneously check if the mouse 1 button is being pressed.
Please let me know if you need any clarification. Thanks for the help.

Trying to get the GUI program to recognize when a certain area is clicked? [Python]

I have a GUI program setup to play a matching game.
In my program, I have two buttons which work out fine because I have a Button Class to recognize that a button is created and when it is clicked. for the clicked portion, I have this in my code:
def isClicked(self, p):
"""Returns true if button active and Point p is inside"""
if self.active == True and p.getX() <= self.xmax and p.getX() >= self.xmin and \
p.getY() >= self.ymin and p.getY() <= self.ymax:
return True
else:
return False
However, this only works with buttons. I have in my program a 6x4 set up of cards on the screen. I click start game and the cards pop up, however the program crashes immediately after clicking start game and having the cards pop up because it says that AttributeError: 'Image' object has no attribute 'isClicked'
This makes sense, as my program is set up for buttons. So how can I get it so that my program registers when a user clicks something that's not a button?
In other words:
I want the user to click on a card and that card then draws up another card. But not sure how to get it to click wherever he wants and have it work when clicked on an actual card
for firstcard in range(6):
firstrow = self.deck.dealCard()
randomsuite = firstrow.getSuite()
randomrank = firstrow.getRank()
#Real image with face value of card
realCard = Image(Point(xpos,ypos),"playingcards/"+ (randomsuite) + str(randomrank) +".gif")
realCard.draw(win)
#Red Back of card to cover image
firstcard = Image(Point(xpos,ypos),"playingcards/b1fv.gif")
firstcard.draw(win)
#pushes the card to the right a bit
xpos += 100
while not Quitbutton.isClicked(p):
#Start Game
if StartGameButton.isClicked(p) and player == True:
if first == True:
Game.gameboard(win,150,125)
if firstcard.isClicked(p):
firstcard.undraw()
first = False
I'll assume that Image is a class you can't directly modify.
In that case, you may extend it to be a clickable image using the following:
def ImageEx( Image ):
def __init__( location, graphic ):
super().__init__( location, graphic )
def isClicked(self, p):
# insert the click detection code here
Then simply use this class instead of the Image class:
#Real image with face value of card
realCard = ImageEx(Point(xpos,ypos),"playingcards/"+ (randomsuite) + str(randomrank) +".gif")
realCard.draw(win)
#Red Back of card to cover image
firstcard = ImageEx(Point(xpos,ypos),"playingcards/b1fv.gif")
This will give you an interactive image with an isClicked method.
It might even be worth having an interactive object class that all your interactive objects can inherit from to give them the ability to be manipulated.

python pyglet on_mouse_press

I'm trying to make a simple GUI using pyglet.
Here is my code:
button_texture = pyglet.image.load('button.png')
button = pyglet.sprite.Sprite(button_texture, x=135, y=window.height-65)
def on_mouse_press(x, y, button, modifiers):
if x > button and x < (button + button_texture.width):
if y > button and y < (button + button_texture.height):
run_program()
The problem
The "button.png" is displayed as the red box with "Click" inside. and is supposed to start run_program(). But currently the yellow in the bottom left is the place i have to click to initiate run_program().
You are comparing the button (the key-code) with the X/Y coordinates. This happens, because the function parameter button shadows your global variable. Also, you should use the buttons x, y, width and height attributes.
button_texture = pyglet.image.load('button.png')
button_sprite = pyglet.sprite.Sprite(button_texture, x=135, y=window.height-65)
def on_mouse_press(x, y, button, modifiers):
if x > button_sprite.x and x < (button_sprite.x + button_sprite.width):
if y > button_sprite.y and y < (button_sprite.y + button_sprite.height):
run_program()
I renamed your global variable button with button_sprite to avoid the name collision.

Categories