I'm using pycharm and this is my code.
import pyautogui
while True:
position = pyautogui.displayMousePosition()
print(position)
After I hit play, the code starts working however the only response I get is Press "Ctrl-C to quit" and after I cancel the code an infinite list of none appears.
"pyautogui.DisplayMousePosition()" is more complex. You can search why it's not working but you can use the code below.
import pyautogui
while True:
x, y = pyautogui.position() # Setting x and y to the coordinates of mouse
print(x, y) # Printing x and y values
You can say "print(pyautogui.position().x, pyautogui.position().y)" but if you want to use x and y on something diffrent, use "x,y=pyautogui.position()".
Note that the code above will print coordinates so fast until closing the program :)
Related
I want to get the x, y position of the mouse (in windows 11) and use this position in the rest of the code.
I have tried two different modules but neither seem to work.
pyautogui (for a mouse click or button press)
keyboard (for a button press)
So far, i am able to get the current position (with pyautogui), but i cannot break out of the while loop to proceed to the next piece of code or even return the function.
Here is the function with my attempts:
import time
import pyautogui
import keyboard
def spam_ordinates():
''' function to determin the mouse coordinates'''
print('press "x" key to lock position...')
while True:
# Check if the left mouse button is clicked
time.sleep(0.1)
print(pyautogui.displayMousePosition())
# various methods i have tried ...
if keyboard.is_pressed('x'):
print('x key pressed...')
break
if pyautogui.mouseDown():
print("Mouse clicked!")
break
if pyautogui.keyDown('x'):
print('x key pressed (autogui)...')
break
# Get the current mouse position
x, y = pyautogui.position()
print(f'spam at position: {x}, {y}')
return x, y
# call function
ords = spam_ordinates()
i see answers like this:
Python get mouse x, y position on click, but unfortunately it doesn't actually return a value on the mouse click or button press.
So, how can i break out of the while loop such that the function returns the x, y position of the mouse?
update
it appears as though print(pyautogui.displayMousePosition()) was preventing the code from breaking out of the while loop.
I am not sure why, but commenting out that line corrected the issue.
I noticed that for some reason the print(pyautogui.displayMousePosition()) line of code was creating problems from breaking out of the loop.
when the above print statement was removed, i was able to use any of the modules:
pynput
keyboard
so this code works with the `keyboard module:
def spam_ordinates():
''' function to determin the mouse coordinates'''
print('press "x" key to lock position...')
while True:
# Check if x key is pressed
time.sleep(0.1)
if keyboard.is_pressed('x'):
print('x key pressed...')
break
# Get the current mouse position
x, y = pyautogui.position()
print(f'spam at position: {x}, {y}')
return x, y
I cannot explain completely why print(pyautogui.displayMousePosition()) caused this error, other than it must have been blocking the if statements that would have evoked the break.
I post this answer in case anybody else encounters the same.
This code:
Looks for an image a
If it finds a it tries to find a match for any image in the array
image_list
If it finds an image in image_list it looks for e
If it finds e it logs it and moves the mouse to x, y checks for pixel colour and then clicks when when it finds a match, clicks.
This is where my problem arises my avoidLog() function is being called 2-3 times per click. I've added print("click") to check if it's actually clicking and it isn't, it's clicking at the right time but for some reason, my log is triggering more than once.
It's logging correctly, just an odd number of times.
I know python is operating in a single thread in my example so I'm not sure why it's looping back round and not clicking. It would make more sense to me if it was clicking multiple times and logging multiple times.
import pyautogui as py
def avoidLog():
avoidLog = open('Avoided.txt', 'a')
avoidLog.write("Found at: " + str(f) + " at: " + str(skipTime))
avoidLog.write("\n")
avoidLog.close()
image_list = []
while True:
if py.locateOnScreen('a.jpg') != None:
for image in image_list:
found = py.locateCenterOnScreen(image)
if found != None:
skipTrigger = py.locateOnScreen('e.jpg')
if skipTrigger != None:
avoidLog()
py.moveTo(x, y)
r = py.pixelMatchesColor(x,y, (r,g,b))
if r == True:
py.sleep(2)
print("click")
py.click()
break
avoidLog() is called whenever e.jpg is located. However, py.click() is only called if pixelMatchesColor is True
I'm trying to make Connect 4 in python, but I can't figure out how to get the coordinates of the screen click so I can use them. Right now, I want to draw the board, then have someone click, draw a dot, then go back to the top of the while loop, wipe the screen and try again. I've tried a couple different options but none have seemed to work for me.
def play_game():
"""
When this function runs, allows the user to play a game of Connect 4
against another person
"""
turn = 1
is_winner = False
while is_winner == False:
# Clears screen
clear()
# Draws empty board
centers = draw_board()
# Decides whose turn it is, change color appropriately
if turn % 2 == 0:
color = RED
else:
color = BLACK
# Gets coordinates of click
penup()
onscreenclick(goto)
dot(HOLE_SIZE, color)
turn += 1
As well intentioned as the other answers are, I don't believe either addresses the actual problem. You've locked out events by introducing an infinite loop in your code:
is_winner = False
while is_winner == False:
You can't do this with turtle graphics -- you set up the event handlers and initialization code but turn control over to the main loop event handler. My following rework show how you might do so:
import turtle
colors = ["red", "black"]
HOLE_SIZE = 2
turn = 0
is_winner = False
def draw_board():
pass
return (0, 0)
def dot(color):
turtle.color(color, color)
turtle.stamp()
def goto(x, y):
global turn, is_winner
# add code to determine if we have a winner
if not is_winner:
# Clears screen
turtle.clear()
turtle.penup()
# Draws empty board
centers = draw_board()
turtle.goto(x, y)
# Decides whose turn it is, change color appropriately
color = colors[turn % 2 == 0]
dot(color)
turn += 1
else:
pass
def start_game():
"""
When this function runs, sets up a new
game of Connect 4 against another person
"""
global turn, is_winner
turn = 1
is_winner = False
turtle.shape("circle")
turtle.shapesize(HOLE_SIZE)
# Gets coordinates of click
turtle.onscreenclick(goto)
start_game()
turtle.mainloop()
Run it and you'll see the desired behavior you described.
I'm assuming that your using Turtle in python(hence the name.)
If that's the case, Here's a link to a helpful post: Turtle in python- Trying to get the turtle to move to the mouse click position and print its coordinates
I know, i know. I hate just link answers as much as the next guy. But The post I gave a link to can probably do a much better job of answering your question than I can.
~Mr.Python
Assuming you're using turtle as mentioned in your title:
>>> import turtle
>>> help(turtle.onscreenclick)
Help on function onscreenclick in module turtle:
onscreenclick(fun, btn=1, add=None)
Bind fun to mouse-click event on canvas.
Arguments:
fun -- a function with two arguments, the coordinates of the
clicked point on the canvas.
num -- the number of the mouse-button, defaults to 1
Example (for a TurtleScreen instance named screen)
>>> onclick(goto)
>>> # Subsequently clicking into the TurtleScreen will
>>> # make the turtle move to the clicked point.
>>> onclick(None)
That means that your callback function, which you have apparently named goto, will take two parameters, an X and Y location.
import turtle
def goto(x, y):
print('Moving to {}, {}'.format(x,y))
turtle.goto(x, y)
turtle.onscreenclick(goto)
turtle.goto(0,0)
Each click that you make will move the turtle to a different position. Note that turtle already has an event loop - you don't need one of your own. Just respond to the clicks.
basically, you need to add an 'x' and 'y' parameter for the onclick and onscreenclick functions. You don't need to use them, they're just dummy params. After filling those out the clicks will work no problem:
window = turtle.Screen()
This function uses the x, y params because i'm saving the clicks in order to specify an area to fill with turtles
def on_left_click_save_coordinates(x, y):
global counter, Fill_COORS1, Fill_COORS2
counter += 1
print(x, y)
if counter == 1:
Fill_COORS1 = (x, y)
elif counter == 2:
Fill_COORS2 = (x, y)
counter = 0
This one doesn't use the x,y params because they are dummies, this one is used to allow multiple options, one of which exits, another tells the turtle to fill in the specified area saved in clicks above.
def on_right_click_open_options(x, y):
global going
last_color = options(window, filler, Fill_COORS1, Fill_COORS2, LAST_BLOCK_USED)
if type(Last_COLOR) == type(bool):
going = True
window.onscreenclick(on_click, btn=1)
window.onscreenclick(open_options, btn=3)
This is an example of a snippet of my code. hope this helps.
btn 3 refers to the right click
btn 1 is the default and isn't necessary to specify and refers to left click
btn 2 is the scroll wheel click, not scroll.
and sorry if this isn't formatted the best, it's my first time posting to stackoverflow. Hope it helps nonetheless
My code is below. I am writing a Minecraft program that randomly places 5 blocks in a single program. I am having trouble in the for statement, as I am trying to place 5 blocks randomly without placing one block and having to run the program 5 times. I'm not sure what to put in the for statement either. Any help or suggestions are always appreciated. * The code below the def function statement are indented.
def placeRandomBlocks():
global diamond_x, diamond_y, diamond_z
pos = mc.player.getTilePos() # get player position
for i in range(0, 5):
Firstly you define your method for placing a single block randomly.
from random import randint
def placeRandomBlock():
x, y, z = mc.player.getPos()
mc.setBlock(randint(0,9) + x, randint(0,9) + y, z, 1)
and then you need to call that method, within a loop to place multiple blocks.
for block in range(0, 5):
placeRandomBlock()
Currently, I know only one way to show strings using ncurses library, like as below:
import curses
stdscr = curses.initscr()
stdscr.addch(0,0,'x')
stdscr.getch()
But I've met a problem when I want to make a falling function of string.
import curses
import time
stdscr = curses.initscr()
y=1
def fall():
global y
stdscr.addstr(y,0,'x')
stdscr.move(y-1,0)
stdscr.clrtoeol()
y += 1
stdscr.getch()
while True:
time.sleep(0.2)
fall()
If I remove this getch() function, I can't see the ncurses screen. But if I put it in. I have to touch some key on my keyboard then the string could fall.
Is there a way I can make the string automatically falling without hit keyboard or mouse?
Refresh at the point you wants to reflect changes on your screen.
I am not rectifying but modifying my draw square code in previous answer, below my own code using curses library(added comments so that it can be helpful for someone new):
from curses import *
import random, time
def main(stdscr):
start_color() # call after initscr(), to use color, not needed with wrapper
stdscr.clear() # clear above line.
stdscr.addstr(1, 3, "Fig: RAINING", A_UNDERLINE|A_BOLD)
# init some color pairs:
init_pair(10, COLOR_WHITE, COLOR_WHITE) # BG color
init_pair(1, COLOR_RED, COLOR_WHITE)
init_pair(2, COLOR_BLUE, COLOR_WHITE)
init_pair(3, COLOR_YELLOW, COLOR_WHITE)
init_pair(4, COLOR_MAGENTA, COLOR_WHITE)
init_pair(5, COLOR_CYAN, COLOR_WHITE)
# First draw a white square as 'background'
bg = ' ' # background is blank
for x in range(3, 3 + 75): # horizontal c: x-axis
for y in range(4, 4 + 20): # vertical r: y-axis
stdscr.addstr(y, x, bg, color_pair(10))
stdscr.refresh() # refresh screen to reflect
stdscr.addstr(28, 0, 'Press Key to exit: ')
# Raining
drop = '#' # drop is #
while True: # runs infinitely
xl = random.sample(range(3, 3+75), 25) # generate 25 random x-positions
for y in range(5, 4 + 20): # vertical
for x in xl:
stdscr.addstr(y-1, x, bg, color_pair(10)) #clear drops #previous row
stdscr.addstr(y, x, drop, color_pair(random.randint(1, 5)))
stdscr.refresh() # refresh each time, # ^^ add drops at next row
time.sleep(0.5) #sleep for moving..
for x in xl: # clear last row, make blank
stdscr.addstr(23, x, ' ', color_pair(10))
stdscr.getkey() # it doesn't work in this code
wrapper(main) #Initialize curses and call another callable object, func,
Snap-sort of one iteration:
two iterations: http://s1.postimg.org/ehnvucp1p/rain.gif
You have to explicitly update the screen, either by calling the refresh() method on the window (stdscr in your example) or by calling curses.doupdate().
This is due to the fact that curses was written years ago, when terminal where pretty slow and it was really important to make modifications efficiently. With an explicit update you can first change the screen how you want and then update it in a single operation, instead of doing an update for every single operation.