Python 3.10.6 /w pyautogui Display Message Boxes, crashes - python

Python: 3.10.6,
os: MacOS 12.6,
Software: VS code
I want to confirm before activating the mouse_click()with pyautogui's message box (.alert or .confirm).
Running the script the message box opens, and if I do nothing its okey. But once I click in the message box, a button or anywhere in the message box window, the 'spinning wheel' appears. The application window crashes and needs to 'Force quit'.
Its the same with every message box.
import pyautogui
import time
def mouse_click():
while True:
time.sleep(1)
pyautogui.click()
def main():
pyautogui.confirm('Shall I proceed?')
mouse_click()
main()
quit()
What might be the issue?

I believe your issue may stem from being in a while loop:
taking it out of the loop seems to fix things. The confirm box also returns the value of the button clicked so I implemented that.
import pyautogui
import time
x = pyautogui.confirm('Shall I proceed?', title='Are you sure?', buttons=['Ok', 'Cancel'])
if x == 'Ok':
time.sleep(1)
pyautogui.click()
else:
quit()
Though for some reason the box doesn't close until after the click event.
In any event you can work around this by making pyautogui move your mouse and click elsewhere.

the solution would be the use of 'threading'. As having an active GUI and a task running in a loop causes the GUI to freeze, looks to have crashed, until the loop has ended.
some info about threading can be found here Python threading and PySimpleGUI
I've moved over to PySimpleGUI and used threading. Explanation and demo code:
https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py

Related

Changing the active window with a hotkey using python

I want to change the active window to a particular one using python. Here is a working example:
import pygetwindow as gw
win = gw.getWindowsWithTitle('editor')[0]
win.activate()
What I'd like to do however, is triggering the switch of windows using a hotkey, for instance like this:
import pygetwindow as gw
import keyboard as kb
def change_window():
win = gw.getWindowsWithTitle('editor')[0]
win.activate()
kb.add_hotkey('q', change_window)
kb.wait('esc')
I would expect the above code to do exactly the same as the first one after pressing the "q" key. However, the second code produces an error message. I really can't understand how the fact that it is triggered by a hotkey could change anything. I have tried different hotkeys and inserted a few time.sleep in between to see if it has anything to do with me still having the hotkey pressed, but to no success. It even works if I just call the function directly in the source code.
I would appreciate your feedback very much. I'm using PyCharm on Windows 11.

Python 3.6 crashes when clicking exit in Tkinter window Mac OSX

When trying to close my tkinter window using the red 'x' button (top left) the window doesn't close and python crashes(colour wheel).
(note this is across all of my Tkinter apps, not just the one shown)
Here is an image of my code:
Here is the crashed white box, neither "quit" or red "x" works. It doesn't show up in the screenshot but the spinning colour wheel is visible whenever I hover over my window. I have to force quit due to "Python not responding".
Got me thinking when I run python in the shell there's an error message: TK Tcl. Maybe unstable.
I suggest to try master.destroy instead of frame.quit for the callback of the Quit button, and give us feedback whether it changes anything

having trouble clicking in program - pyautogui

I'm trying to click into a program window using pyautogui.
When clicking in the program window, on a button I wish to press, a loading icon appears next to the mouse cursor as if it is thinking, and it never actually clicks. It does, however, move to the cursor location that I provide.
Here's the code
import pyautogui
pyautogui.doubleClick(x=300, y=300)
I opened Excel to see if it will click into that, and it does, but only if I run the code as:
import pyautogui
pyautogui.doubleClick(x=300, y=300)
pyautogui.doubleClick(x=300, y=300)
What the heck do I do?
If the application in running as administrator and pyautogui script is not running as administrators, then control will not work. pyautogui script should also run as administrator to control it
Try giving the interval argument
pyautogui.doubleClick(x=300, y=300, interval=0.25)

Running Python clicker based on keylogger inputs on the background in Windows

I wanted to write a program in Python for Windows that would act as a clicker, in which according to a key the user presses a click is made at a known location on the screen. This is used for an automated option selection from a list in a webpage. I have the clicking part working, but I wanted to be able to make several clicks during execution, as if there is a quiz with multiple lists one after another.
One option is to make a while loop with getch() from msvcrt. The thing is after a click outside the cmd its window is no longer selected, but rather the window where the destination point is located. Therefore, the script stops being active and the user cannot choose another location. A workaround is to click the cmd window to return the focus to it and be able to do any more clicks. To solve this, it would be necessary to create a service or, according to #Sanju, a thread.
The other option is to use a keylogger such as PyHook, which seems like the way to go. However, the problem is that the window where I want to use it in, a webpage in flash or another animations engine, causes an error that some users have found using this keylogger for example in Skype and is being described here. In my case, it also happens with this webpage and either when the click is made on the window itself or when the key is pressed with the window selected.
My base code is presented below, where click(...) would normally contain the coordinates as argument but they are being omitted for simplicity. In this case, 0 ends the program and there are three options being chosen with the numbers 1-3.
import msvcrt, win32api, win32con
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
key=0
while key!=b'0':
key=msvcrt.getch()
if key==b'1':
click(...)
elif key==b'2':
click(...)
elif key==b'3':
click(...)
The attempts below try to implement #Sanju's suggestion, first with the whole while inside the thread and then with the queue, both not working as expected...
import threading, msvcrt, win32api, win32con
def MyThread():
key=0
while key!=b'0':
key=msvcrt.getch()
if key==b'1':
...
def click(x,y):
...
threading.Thread(target=MyThread,args=[]).start()
.
import queue, threading, msvcrt, win32api, win32con
def MyThread(key):
while key.get()!=b'0':
key.put(msvcrt.getch())
if key.get()==b'1':
...
def click(x,y):
...
key=queue.Queue()
key.put(0)
threading.Thread(target=MyThread,args=[key]).start()
The other attempt uses PyHook, but it's still facing the aforementioned issue.
import pyHook, pythoncom, win32api, win32con
def OnKeyboardEvent(event):
if event.Key=='Numpad1':
...
def click(x,y):
...
hm=pyHook.HookManager()
hm.KeyDown=OnKeyboardEvent
hm.HookKeyboard()
pythoncom.PumpMessages()
All you need here is move your click part to a thread and share the user input using a shareble object such as queue. It sounds like a overkill , but that's the way to keep your tasks in background.
And BTW, you have many GUI application frameworks available in Python like tkinter ,wxpython which can ease your objective.

Tkinter method deiconify seems not working on ubuntu(12.04, unity)

Tkinter method "deiconify" seems not working on ubuntu(12.04, unity), but the the following code works as expected on windows 7. I need to show the window even it is minimized when something happens in another project https://github.com/thinker3/youdao.
from time import sleep
from Tkinter import Tk
class GUI():
def __init__(self):
self.root = Tk()
self.root.title("Test")
self.root.protocol("WM_DELETE_WINDOW", self.close_handler)
self.root.mainloop()
def close_handler(self):
self.root.iconify()
sleep(1)
self.root.deiconify()
if __name__ == '__main__':
gui = GUI()
What you are seeing is apparently the difference between Windows and non-Windows. It looks to me like the Windows behavior is a bug. At the very least, it's not expected behavior. What you are seeing on ubuntu is what I would expect to see.
For a GUI to do anything, the event loop must be running. Everything that happens is the response to an event. The drawing of a window on the screen is a response to an event. A button click is a response to an event. The visual effect of a button being pressed is a response to an event. And so on.
When you call iconify, that causes an event to be sent to the app saying "remove the window from the screen". The event loop sees the event, and redraws (or "un"draws) the window. The reverse happens when you call deiconify -- the system gets a redraw event, and tkinter redraws the window on the screen.
In your code, you never give the event loop a chance to respond to these events. You ask it to iconfiy, then you sleep, then you deiconify, all without giving the event loop a chance to respond. While the sleep command is running no events are processed. So, when you wake from sleep, the system hides the window, and then microseconds later it redraws it.
What is probably happening on windows is that the window manager is getting the iconfiy command and removing the window without tkinter's involvement. In other words, tkinter doesn't actually do anything to make it go away. On X11-based systems, however, this is all managed by the event loop.
If you want the window to go away, and a second later reappear, use the event loop to your advantage. Allow the event loop to update the screen, and arrange for the deiconify to happen at sometime in the future. For example:
def close_handler(self):
self.root.iconify()
self.after(1000, self.root.deiconify)
This should work on all platforms. It allows the event loop to respond to the iconify event, and then a second later the deiconify command will run.

Categories

Resources