I have a pygame window embedded in a a frame in tkinter. In another frame I have a button which calls the following function when clicked:
def setStart():
global start
# set start position
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
start = event.pos
print("start",start)
break
I am intending for the program to print the position of the place where the user clicked on the pygame surface after the button is clicked. However on the first click of the button and the following click of the pygame surface there is no output. It is on the second click of the button before the corresponding second click on the pygame surface that python prints out an output like :
('start', (166, 115))
How can I get it to give me a result right after the click on the pygame surface? I had the same problem when I had two seperate tkinter and pygame windows so the embedding of pygame into tkinter is unlikely to be the cause of the problem.
EDIT: after further testing it appears that if the button is pressed and then the pygame surface is clicked on multiple times, upon a second click of the button the coordinates of all of these clicks are printed out as a batch.
In the most basic form here's how you do it in pygame:
import pygame
pygame.init()
screen = pygame.display.set_mode((100, 100))
clock = pygame.time.Clock()
while True:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP: # or MOUSEBUTTONDOWN depending on what you want.
print(event.pos)
elif event.type == pygame.QUIT:
quit()
pygame.display.update()
More information on how to handle pygame events can be found in the docs.
And here's how you do it in tkinter:
try:
import tkinter as tk # Python 3
except ImportError:
import Tkinter as tk # Python 2
root = tk.Tk()
def print_pos(event):
print(event.x, event.y)
root.bind("<Button-1>", print_pos)
root.mainloop()
More information on tkinter events can be found in effbots documentation.
I would suggest not putting break in an event loop in pygame. Doing so makes all other events go un-handled, meaning that it's possible for the program to not respond to certain events.
Your "EDIT: [...]" is unfortunately wrong, given the code you've given us. I had no problem with the code; it printed the position of where I released the mouse button and always printed just one position. So there have to be a logical error somewhere else in your code.
First I have to say that I don't know anything about pygame. However, if you are already using Tkinter, I could help you maybe: I would define a new function (let's call it mouse_click). In the button-click-function I would bind the new function to the game's surface. In the new function I print out the current mouse position:
def button_click(self):
game_surface.bind("<Button-1>", self.mouse_click)
def mouse_click(self, event):
print "X:", event.x
print "Y:", event.y
I hope this is helpful. Please notice that you should modify this code to make it work in your program (using the correct widget names and so on).
By the way, "Button-1" is the event identifier of the left mouse button.
Related
I've read everything I could find about the mouse in pygame and yet I miss something.
The device has (and will not) have a mouse attached so I need to remove the cursor from the game surface, ideally even before it draws the first screen.
But no matter what I try I always have a big oppalin cursor in the middle of the screen.
My current function is this :
# initialize the pygame module
pygame.init()
# create a surface on screen that has the size of 240 x 180
screen = pygame.display.set_mode((160,80))
# define a variable to control the main loop
running = True
pygame.display.flip()
# main loop
while running:
screen.fill((0, 0, 0))
# hide cursor
pygame.mouse.set_pos((160,80)) # my screen is actually 160 x 80 px so this should hide it by pushing it over the edge
pygame.mouse.set_visible(False) # this should hide the mouse plain and simple
# Here I do other unrelated (but working) stuff, like displaying images and text
# event handling, gets all event from the event queue
for event in pygame.event.get():
# only do something if the event is of type QUIT
if event.type == pygame.QUIT:
# change the value to False, to exit the main loop
running = False
pygame.display.flip()
And the mouse is still on screen, sometimes after a while it disappears.
I tried other method like making the cursor transparent, but that crash the app.
Note that I'm running Pygame on an Alpine Linux with direct output to the framebuffer on a Raspberry Pi. There's no mouse attached to the device but if I connect one I can move the cursor around.
Pygame is Version 2.1.2 (compiled and installed by pip)
Python is 3.10.0
Any help or pointer would be greatly appreciated.
(sorry if it's a dumb question; I'm a total noob with python/pygame)
Just write the set_visible(False) outside the main loop, you don't need to call this every frame:
pygame.init()
screen = pygame.display.set_mode((160,80))
pygame.mouse.set_visible(False) # Hide cursor here
running = True
pygame.display.flip()
# main loop
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# unrelated with your question but I also suggest that you clear your background inside the loop, at the contrary you likely will need this at each frame
screen.fill((0, 0, 0))
# ... your code, blitting images etc
pygame.display.flip()
I'm currently making a graph plotter and I'm in the early stages so Im just using the shell to get inputs from the user at the moment. However, due to other parts of my program, I need the pygame window to be open before they begin their inputs (I cannot change the order of this as their inputs are gotten by a function and I don't really want to open pygame in this function). This blocks the shell so I used pygame.display.iconify() which minimized the pygame window doing what I needed.
My problem is that when you have completed the inputs the pygame window is still minimized and I want it to be back as an active window. Is there such a thing that does the opposite of iconify() or should I change my code completely?
Thanks.
There's no way to do this with pygame only, but if you're on Windows, you can use the pywin32 package.
Here's an example that will minify and restore the window every second:
import pygame
import win32gui
import win32con
def main():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((200, 200))
hwnd = win32gui.GetForegroundWindow()
EVENT = pygame.USEREVENT + 1
pygame.time.set_timer(EVENT, 1000)
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
return
if event.type == EVENT:
if win32gui.IsIconic(hwnd):
win32gui.ShowWindow(hwnd, win32con.SW_SHOWNOACTIVATE)
win32gui.BringWindowToTop(hwnd)
else:
pygame.display.iconify()
screen.fill((30, 30, 30))
clock.tick(30)
pygame.display.flip()
main()
Don't use pygame.display.iconify() as there is no pygame.display.uniconify() counterpart.
There is this ugly hack, where you can use pygame.display.set_mode() to hide the window, and then regain focus and size, when needed:
# Minimize window
pygame.display.set_mode((1,1))
# Restore window
pygame.display.set_mode((1024, 768))
You should write your plot on a surface, independent of the display surface, and then blit and flip it, when you need to display it.
i typed the below code in my sublime text, but as this code is used by people to change the background color; i hope it would happen, but, unfortunately it didn't. i.e precisely color didn't change. i
then i started to research in stackoverflow.
some questions like this in (mac os ) has been already asked.
though, you people say that that question will answer my question, it does to some level; but I would love to get the answer of this question. Why does my Tkinter window background not change?
likewise a similar question was asked, like this; Python tkinter window background/canvas not changing colour
import sys
import pygame
def run_game():
#initialize game and create a screen object.
pygame.init()
screen = pygame.display.set_mode((1200,800))
pygame.display.set_caption("Alien Invasion")
#set the background color.
bg_color=pygame.color.Color('#FFFFF')
# start the main loop for the game.
while True:
#watch for keyboard and mouse events.
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
#redraw the sceen during each pass through the loop
screen.fill(bg_color)
#make most recently drawn screen visible
pygame.display.flip()
run_game
I am trying to implement a game using mouse position to see if the user clicks a button. Somehow the mouse position does not update for a couple seconds, and changes to a new position for another couple seconds, and repeat. I moved and pressed the mouse at different location in the screen, but the mouse position did not change at all. (Working on python3.5.1 and pygame 1.9.2, using IDE PyCharm)Any idea?
Here is my code:
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if click[0]==1:
print(mouse)
pygame.display.update()
The call
mouse = pygame.mouse.get_pos()
doesn't update the position unless the event MouseMotion is executed.
If you are executing the program in a window on a MAC, the mouse must be pressed, held, and moved (if you were to press, hold, then move the mouse, pygame.mouse.get_pos() would return the current mouse position).
There is two ways of handling input events in pygame :
State Checking
Event Handling
For better understanding of how it works :
http://www.pygame.org/docs/tut/newbieguide.html#managing-the-event-subsystem
You use both in your code, state checking :
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
Event handling :
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
If you still want to use state checking to get the mouse position you can add:
clock=pygame.time.Clock()
clock.tick(60) # 60 frames per second
So the update of the position should be better.
If the button has a rect then you can use the rect.collidepoint() method with event checking like this:
mouse_pos = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0] and button.rect.collidepoint(mouse_pos):
This drove me crazy for hours. I had a similar problem.
Using pygame in:
Mac OSX 10.13 (High Sierra)
pygame 1.9.3
python 3.6
in a virtualenv
In this setup (specifically in the virtualenv), window focus is not properly tracked. Click and dragging will generate a MOUSEMOTION event, but simply moving the mouse around will not. If the MOUSEMOTION event is not generated, calling:
pos = pygame.mouse.get_pos()
will continue report the same value until another MOUSEMOTION event occurs.
Installing pygame outside of the virtualenv, all works as expected. Not really the answer I was hoping for, but at least it explains the behavior I was seeing.
Your
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
only get the states at the time of the call. As per the documentation http://www.pygame.org/docs/ref/mouse.html:
to get all of the mouse events it is better to use either
pygame.event.wait() or pygame.event.get() and check all of those events
That is you are missing the clicks because your program isn't storing them to process. You only see it when you get lucky and the program calls the function when the button is actually down.
This shows a basic pygame mouse getting program. Simply click anywhere in the window and the mouse coordinate are printed:
import pygame as py
py.init()
white = (255,255,255)
window = (400,400)
screen = py.display.set_mode(window)
clock = py.time.Clock()
done = False
while not done:
for event in py.event.get():
if event.type == py.QUIT:
done = True
elif event.type == py.MOUSEBUTTONDOWN:
print py.mouse.get_pos()
screen.fill(white)
py.display.flip()
clock.tick(30)
py.quit()
hope this helps :)
This question already has answers here:
Pygame window not responding after a few seconds
(3 answers)
Pygame unresponsive display
(1 answer)
Closed 1 year ago.
Basically I have a loop (tick, set_caption, screen_fill, event.get(), send_frame_event, flip, repeat)
When I drag the window around on windows 7, the loop stops looping, I ended up stuck in pygame.event.get(), I have tried to define certain events only for get e.g. get([pygame.QUIT]) to no avail.
Simply calling pygame.event.clear() has the same freeze effect when dragging/moving the window.
Is there a workaround?
Not full code, but should be enough:
def start(self):
self.running = True
Clock = pygame.time.Clock()
while self.running:
self.p += 25
tickFPS = Clock.tick(self.fps)
pygame.display.set_caption("Press Esc to quit. FPS: %.2f" % (Clock.get_fps()))
self.screen.fill([self.p&0xFF,(255-self.p)&0xFF,255])
self.handleEvents()
self.raiseEvent("updateFrame")
pygame.display.flip()
def handleEvents(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.running = False
full code at: http://pastie.org/private/wm5vqq3f7xe0xlffy1fq
Try placing a call to pygame.event.pump() inside your mainloop (or handleEvents function)
No idea if this will help or not:
I realize the problem is with moving the window window, not with re-sizing the window.
Perhaps there is some similarity between moving and re-sizing?
I found this in the documentation on re-sizing:
Then the display mode is set, several events are placed on the pygame event queue. pygame.QUIT is sent when the user has requested the program to shutdown. The window will receive pygame.ACTIVEEVENT events as the display gains and loses input focus. If the display is set with the pygame.RESIZABLE flag, pygame.VIDEORESIZE events will be sent when the user adjusts the window dimensions. Hardware displays that draw direct to the screen will get pygame.VIDEOEXPOSE events when portions of the window must be redrawn.
and:
Note that when the user resizes the game window, pygame does not automatically update its internal screen surface. You must call set_mode() every time VIDEORESIZE is sent. This really should be more clear in the documentation.
Perhaps when moving the game window, something similar happens?