Same pygame event generated over and over - python-3.x

In my pygame application, I want a web browser to open when the user presses the F1 key:
#!/usr/bin/env python3
import pygame as pg
import webbrowser
pg.init()
screen = pg.display.set_mode((400, 400))
pg.key.set_repeat(200, 100)
while True:
for evt in pg.event.get():
if evt.type == pg.KEYDOWN and evt.key == pg.K_F1:
webbrowser.open('http://some-website.com')
pg.quit()
When pressing F1, the browser opens but my application keeps opening new tabs if I don't kill it. My guess is that the same KEYDOWN event is generated over and over when my application loses the focus due to the use of pg.key.set_repeat: if I comment this call to pg.key.set_repeat then everything works fine.
How can I fix that?
Versions used are: pygame 2.0.1 (SDL 2.0.14, Python 3.9.5).

You should use keyboard module like this:
import keyboard
# [...]
while True:
# [...]
if keyboard.is_pressed("F1"):
webbrowser.open('http://some-website.com')
pg.quit()
Or you can break the loop after you open the spesific website:
# [...]
while True:
for evt in pg.event.get():
if evt.type == pg.KEYDOWN and evt.key == pg.K_F1:
webbrowser.open('http://some-website.com')
break
# [...]
pg.quit()

Related

How to let cmd-line continuous print log message?

I wrote a simple app that I want to print logging message every seconds.
I open a terminal and run it, it works well. But when I use mouse to click the terminal, it will not print logging message unless I print Enter in the terminal.
The Code
import logging
from PyQt5.QtCore import *
logging.basicConfig(level=logging.DEBUG)
app = QCoreApplication([])
timer = QTimer()
timer.setInterval(1000)
timer.timeout.connect(lambda: logging.info("abc"))
timer.start()
app.exec()
Seems to be environment issue.
Below example demonstrates that Qt logging works fine even if mouse button is pressed.
cat pyqt_logging_ex.py
#!/usr/bin/python3.9
import logging,os
from PyQt5.QtCore import *
from pynput import mouse,keyboard
def on_click(x, y, button, pressed):
print("Mouse click")
def on_press(key):
print("Key pressed, exiting")
os._exit(0)
listener = keyboard.Listener(on_press=on_press)
listener.start()
listener = mouse.Listener(on_click=on_click)
listener.start()
print("Started listeners")
logging.basicConfig(level=logging.DEBUG)
app = QCoreApplication([])
timer = QTimer()
timer.setInterval(1000)
timer.timeout.connect(lambda: logging.info("abc"))
timer.start()
app.exec()
Run example:
pyqt_logging_ex.py
Started listeners
INFO:root:abc
INFO:root:abc
INFO:root:abc
Mouse click
Mouse click
INFO:root:abc
INFO:root:abc
Mouse click
Mouse click
INFO:root:abc
INFO:root:abc
qKey pressed, exiting
My environment:
uname -or ; lsb_release -d ; python3.9 --version
4.4.0-19041-Microsoft GNU/Linux
Description: Ubuntu 20.04.3 LTS
Python 3.9.5

pynput.keyboard terminate program when key is pressed not responding

I have this code here and what I want is for the code to type "potato" every 5 seconds. I also want a "quit" command, and I want it so that when I press = it will stop the program. However, not only does the code not work, but it also types "=" after it types/enters "potato". Can someone help? Thanks.
from pynput.keyboard import Key, Controller
import time
keyboard = Controller()
time.sleep(3)
while True:
keyboard.type('potato')
keyboard.press(Key.enter)
keyboard.release(Key.enter)
if keyboard.type('asdf'):
quit()
time.sleep(5)
P.S. no errors or anything
The most obvious answer here would be to change the "asdf" to "=" in the if statement, but if that doesn't fix the problem, you could add a listener to detect keypresses.
from pynput import keyboard, Key, Controller
import time
# set your termination key here
cut_key = "="
# check if key pressed is cut_key, if so, quit
def on_press(key):
try:
if key.char == cut_key:
quit()
except AttributeError:
if key == cut_key:
quit()
# non-blocking listener
listener = keyboard.Listener(
on_press=on_press)
listener.start()
keyboard = Controller()
time.sleep(3)
while True:
keyboard.type('potato')
keyboard.press(Key.enter)
keyboard.release(Key.enter)
time.sleep(5)
I didn't test this code, please comment if it doesn't work.
https://pynput.readthedocs.io/en/latest/keyboard.html

Pyqt5--Why QApplication.processEvents() failed to update GUI

I am learning to use PyQT5 and QtDesign. The workflow is :Click button->Change a image. But GUI failed to update until QMessege appeared. Here is a code. Firstly, I draw a button named pass_btn, a label named fds_img, by QtDesign.
Then, code as below:
from PyQt5 import QtWidgets, uic, QtGui
import os, sys
from PyQt5.QtWidgets import *
app = QtWidgets.QApplication(sys.argv)
dlg = uic.loadUi('grading_sys.ui')
stepper = 0
img_dir_list = [] #this is a image dir list
dlg.fds_img.setPixmap(QtGui.QPixmap(img_dir_list[stepper]))
def pass_btn():
global stepper
if stepper == len(img_dir_list) - 1:
QtWidgets.QMessageBox.information(None, 'Warning', 'Warning')
return
stepper += 1
dlg.fds_img.setPixmap(QtGui.QPixmap(img_dir_list[stepper]))
print('Try to refresh')
QApplication.processEvents()
dlg.pass_btn.clicked.connect(pass_btn)
dlg.show()
sys.exit(app.exec_())
So why I could not refresh the label? Or how could I refresh image when I click the button?
Finally, I solved this by using QTimer. I know it is a waste of CPU, may not efficient enough, but it finally works. But I still confusing about why it did't work before. I solved this as codes below:
First, put all the update codes in a def, then connected it with QTimer, and ran it every second:
def refresh_ui():
print('Try to refresh UI')
print('Prepare to change image' + str(img_dir_list[stepper]))
dlg.fds_img.setPixmap(QtGui.QPixmap(img_dir_list[stepper]))
timer = QTimer()
timer.timeout.connect(refresh_ui)
timer.start(1000)
My environment: MacOS 10.14.2, PyCharm 2018.3.3 edu edition, Python 3.6, PyQt5, QtDesign (through Anaconda). Dose this happened because of MacOS?

Tkinter copy to clipboard not working in PyCharm

I just installed PyCharm and opened up a script I had been using in IDLE that did some string manipulation then copied it to the clipboard, but it doesn't work when I run it in PyCharm.
from tkinter import Tk
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append("test")
r.destroy()
When I run this in IDLE I am able to paste "test" after, but in PyCharm it just says "Process finished with exit code 0" but there is nothing in the clipboard (even if there was before running). I have Python 3.5 as the selected interpreter.
There seems to be problem if the clipboard is manipulated and the program closes too quickly soon after. The following program worked for me but was unreliable when the call to root.after only used one millisecond for the delay. Other possibilities were tried, but code down below should work:
import random
import string
import tkinter
def main():
root = tkinter.Tk()
root.after_idle(run_code, root)
root.after(100, root.destroy)
root.mainloop()
def run_code(root):
root.withdraw()
root.clipboard_clear()
root.clipboard_append(''.join(random.sample(string.ascii_letters, 10)))
print('Clipboard is ready.')
if __name__ == '__main__':
main()
The following is a mildly more useful version of the program and demonstrates that you can make many calls to root.after_idle to run your code in a sequential manner. Its design is primarily for use to process command-line arguments and send them to your clipboard for you:
import sys
import tkinter
def main(argv):
root = tkinter.Tk()
root.after_idle(root.withdraw)
root.after_idle(root.clipboard_clear)
root.after_idle(root.clipboard_append, ' '.join(argv[1:]))
root.after_idle(print, 'The clipboard is ready.')
root.after(100, root.destroy)
root.mainloop()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))

pygame.surface type error: an integer is required

I am new to pygame and i wanted to know what is wrong and how can i fix it, thank you! also my pygame closes right when i open it, thats why i took a screenshot like this one. if you could also explain why it closes that fast, that would be great! (pygame 1.9.2 python 3.4.1 , windows 8)![enter image description here][1]
#!/usr/bin/env python
import pygame, sys
from pygame.locals import *
pygame.init()
pygame.font.init()
pygame.display.set_caption('Primer juego de Gian Di Julio')
mainclock= pygame.time.Clock()
screen = pygame.display.set_mode((800,600))
pygame.mouse.set_visible(0)
#positioning the ship into the middle of the screen
ship = pygame.image.load('ship.png')
ship_top = screen.get_height() - ship.get_height()
ship_left = screen.get_width()/2 - ship.get_width()/2
pygame.Surface(ship,(ship_left,ship_top))
while True:
screen.fill((0,0,0))
x,y = pygame.mouse.get_pos()
screen.blit(ship, (x-ship.get.width()/2, ship_top))
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
pygame.display.update()
pygame.display.flip()
I just looked it up in the pygame docs:
Surface((width, height), flags=0, Surface) -> Surface
But the returned surface is not used in your program so you might leave it out.
When using pygame.display.flip() there is no need for calling pygame.display.update().
Additionally it should be indented.
It closes quickly because you have a syntax error in your code.
pygame.Surface(ship,(ship_left,ship_top))
This line tries to create a surface, with dimensions taken from the ship variable.
Since ship is a surface loaded from an image, it fails.
Removing this line will fix the issue.

Resources