I'm trying to write a script where it has a control panel and you can select what application u want to open only problem is that it opens that application multiple times please help only want to open it once.
I think the problem is that it checks if my mouse button is pressed multiple times a second and since my mouse is only being pressed for a second and it checks a couple times a second it does the if statement and completes it and opens the application multiple times.
# Importing Modules/Libraries.
import pygame
import subprocess
pygame.init()
pygame.font.init()
# Color Variables.
white_color = "#FFFFFF"
# Control Panel Variables.
ctrlpanel_run = True
ctrlpanel_program_select = True
ctrlpanel_program_select_input = True
# Main Arguments.
root = pygame.display.set_mode((700,400))
pygame.display.set_caption("AutoDraw Control Panel")
root.fill("#333333")
# Draws Control panel Program Select Screen.
if ctrlpanel_program_select == True:
title_font = pygame.font.Font("./fonts/Exo-Bold.otf", 100)
button_font = pygame.font.Font("./fonts/Exo-Bold.otf", 45)
title_text = button_font.render("What Application?", True, white_color)
root.blit(title_text, (165, 100))
paint_button_rect = pygame.draw.rect(root, '#006EE6', pygame.Rect(70,200,200,90))
paint3d_button_rect = pygame.draw.rect(root, '#006EE6', pygame.Rect(430,200,200,90))
paint_button_text = button_font.render("Paint", True, white_color)
root.blit(paint_button_text, (120, 225.5))
paint3d_button_text = button_font.render("Paint 3D", True, white_color)
root.blit(paint3d_button_text, (447, 225.5))
# Control panel Program Select Screen Input /// And Variables for Mouse positions and inputs.
mouse_x, mouse_y = pygame.mouse.get_pos()
mouse_l, mouse_m, mouse_r = pygame.mouse.get_pressed()
print(mouse_x, mouse_y)
while ctrlpanel_run:
pygame.display.flip()
mouse_x, mouse_y = pygame.mouse.get_pos()
mouse_l, mouse_m, mouse_r = pygame.mouse.get_pressed()
print(mouse_x, mouse_y)
for event in pygame.event.get():
if event.type == pygame.QUIT:
ctrlpanel_run = False
break
if ctrlpanel_program_select_input == True:
if mouse_x > 69 and mouse_x < 270:
if mouse_y > 199 and mouse_y < 290:
if mouse_l:
subprocess.call(["cmd", "/c", "start", "/max", "C:\Windows\System32\mspaint.exe"])
You know the problem already, as you state in your question. The solution is to stop checking for the mouse click as long as mouse_l == True. So something like this:
Initialize a click_detected boolean variable before your main loop. Then inside the loop:
if ctrlpanel_program_select_input == True:
if mouse_x > 69 and mouse_x < 270:
if mouse_y > 199 and mouse_y < 290:
if mouse_l:
click_detected = True
if not mouse_l and click_detected:
click_detected = False
subprocess.call(["cmd", "/c", "start", "/max", "C:\Windows\System32\mspaint.exe"])
This should open the application when you let go of the button, instead of when you press the button.
Instead of checking the state of mouse buttons, you could use events generated by pressing or releasing the buttons.
You've already defined Rects for your buttons, so you can use collidepoint() to see if the mouse was clicked in the button.
for event in pygame.event.get():
if event.type == pygame.QUIT:
ctrlpanel_run = False
break
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # Left-click
if paint_button_rect.collidepoint(event.pos):
subprocess.call(["cmd", "/c", "start", "/max", r"C:\Windows\System32\mspaint.exe"])
elif paint3d_button_rect.collidepoint(event.pos)
# launch Paint 3D
Related
I use this code to get a separate position of each left click on pygame:
for event in pygame.event.get():
if event.type==QUIT:
running=False
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = event.pos
I use mouse_x and mouse_y for drawing , but they are always change. So, how to get an exact position of each click on a screen in pygame and to use them to draw ?
Thank you
1. To get the position when the mouse is clicked
You can use pygame.event.get() to get the position at the exact frame when you begin to press the button like that:
import pygame
from pygame.locals import * # import constants like MOUSEBUTTONDOWN
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == MOUSEBUTTONDOWN and event.button = 0: # detect only left clicks
print(event.pos)
pygame.display.flip()
pygame.quit()
exit()
2. To get the position each frame
In this case, you can use pygame.mouse.get_pos() like that:
import pygame
from pygame.locals import * # import constants like MOUSEBUTTONDOWN
pygame.init()
screen = pygame.display.set_mode((640, 480))
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
print(pygame.mouse.get_pos())
pygame.display.flip()
pygame.quit()
exit()
If you want to get the mouse position only if the left button is pressed:
Place the line print(pygame.mouse.get_pos()) in if pygame.mouse.get_pressed()[0]::
...
if pygame.mouse.get_pressed()[0]: # if left button of the mouse pressed
print(pygame.mouse.get_pos())
...
This code actually detects all kinds of mouse clicks, if you just want the left clicks you can add this to your if statement:
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
You are also not getting the coordinates the right way, you need to write it like this:
mouse_x, mouse_y = pygame.mouse.get_pos()
If you need to use all the clicks that are happening you need to store the x_mouse and y_mouse to a log which you can do like this:
# This outside the pygame loop
mouse_clicks = []
# This inside the pygame loop
for event in pygame.event.get():
if event.type==QUIT:
running=False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
mouse_clicks.append(pygame.mouse.get_pos())
Now you have a list of tuples with all x,y coordinates for all clicks
This is my python code, using pygame. When I pressed my mouse down, scene 1 does not switch to scene 2. I am coming from Code HS, so the scene switch is from the Tell A Story project. I realized that code is not the same as pygame's. So I used pygame docs and see what I can learn from that, but nothing still. Please can any one help me. Thank you.
import pygame as pg
pg.init()
win = pg.display.set_mode((500,500))
pg.display.set_caption('Scene Switcher')
center_x = 250 - 130
center_y = 250
black= (0,0,0)
red = (255,0,0)
blue = (0,0,255)
def ct(font, size, text, color):
mf = pg.font.Font(font, size)
t = mf.render(text, True, color)
return t
def draw_scene1():
print("This is Scene 1")
txt = ct("SB.ttf", 40, "Hello World!", black)
win.blit(txt, (center_x,center_y))
def draw_scene2():
print("This is scene 2")
txt2 = ct("SB.ttf", 40, "scene2 ", black)
win.blit(txt2, (center_x,center_y))
while True:
win.fill(red)
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
quit()
mouses = pg.mouse.get_pressed()
scene_counter = 0
# When this function is called the next scene is drawn.
def draw_next_screen():
global scene_counter
scene_counter += 1
if scene_counter == 1:
draw_scene1()
else:
draw_scene2()
if mouses:
draw_next_screen()
pg.display.update()
You have to initialize scene_counter before the application loop rather than in the application loop.
The pygame.mouse.get_pressed() returns a list of Boolean values that represent the state (True or False) of all mouse buttons. The state of a button is True as long as a button is held down. Therefor the scene_counter is continuously incremented in each frame as long a mouse button is hold down.
The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released. Increment the counter when the MOUSEBUTTONDOWN event occurs:
scene_counter = 0
run = True
while run:
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
elif event.type == pg.MOUSEBUTTONDOWN:
scene_counter += 1
win.fill(red)
if scene_counter == 0:
draw_scene1()
else:
draw_scene2()
pg.display.update()
pg.quit()
So I currently have this code for an airbrush in a drawing app. When the function is active, it should draw on a canvas, basically like an airbrush. But right now, I don't know how to make pygame detect a mouse down or mouse up and make a while loop out of it. Here is the code:
def airbrush():
airbrush = True
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
while click == True:
pygame.draw.circle(gameDisplay, colorChosen, (cur[0] + random.randrange(brushSize), cur[1] + random.randrange(brushSize)), random.randrange(1, 5))
pygame.display.update()
clock.tick(60)
Right now, I have "while click" which doesn't work. What should I replace "click" with to make this work so that while the mouse is held down, it paints, but when the mouse is "up", it stops?
The state which is returned by pygame.mouse.get_pressed() is evaluated once when pygame.event.get() is called. The return value of pygame.mouse.get_pressed() is tuple with th states of the buttons.
Don't implement a separate event handling in a function. Do the event handling in the main loop:
done = False
while not done:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
airbrush()
pygame.display.flip()
Evaluate the current state of a button (e.g. left button), of the current frame, in the function airbrush:
def airbrush():
airbrush = True
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if click[0] == True: # evaluate left button
pygame.draw.circle(gameDisplay, colorChosen, (cur[0] + random.randrange(brushSize), cur[1] + random.randrange(brushSize)), random.randrange(1, 5))
A few things first:
I am using Windows 10 Home edition
I am using Python 3.7
I am using pygame 1.9.4
My IDE is Visual Studio Code, with IDLE as the backup
I am currently designing a GUI using pygame. NOTE: the code is NOT done yet.
When I run a debug session in VS Code, it (mostly) works as expected, but when I try to click on the start button, pygame does not respond and shows not responding.
I've also noticed this with other pygame scripts I've made, where the pygame window freezes when clicked or moved.
Any help would be appreciated.
Here's the code:
# Import modules
import sys, pygame, time, math
from time import sleep
from PIL import Image
# Display background image
image = 'asdf.png'
change = 2
img = Image.open('asdf.png')
width = img.width * change
height = img.height * change
print(width)
print(height)
screen = pygame.display.set_mode((width,height))
background = pygame.image.load(image).convert()
newscreen = pygame.transform.scale(background, (width, height))
screen.blit(newscreen, (0,0))
pygame.display.update()
# start button
pygame.draw.rect(newscreen, (255,120,0), pygame.Rect(width/4,height-height/4, width/2, height/7))
screen.blit(newscreen, (0,0))
pygame.display.update()
pygame.init()
myFont = pygame.font.SysFont("Times New Roman", 100)
text = myFont.render("START", False, (0, 0, 0))
screen.blit(text, (width/4+8,height-height/4-10))
pygame.display.update()
pygame.image.save(newscreen, 'background.png')
pygame.image.save(text, 'starttext.png')
# i button
pygame.draw.rect(newscreen, (255,0,120), pygame.Rect(width - 50, 10, 40,40))
screen.blit(newscreen,(0,0))
pygame.display.update()
myFont = pygame.font.SysFont("Times New Roman", 25)
ibutton = myFont.render("i", False, (0, 0, 0))
screen.blit(ibutton, (width-32,17))
pygame.display.update()
# Mouse click
while True:
left,right,center = pygame.mouse.get_pressed()
if left == True:
if event.type == MOUSEBUTTONUP:
x,y = pygame.mouse.get_pos()
if ((width/4) <= x <= ((width/4) + (width/2))) and ((height-height/4) <= y <= ((height-height/4) + height/76)):
#move to next screen
break
time.sleep(5)
This is NOT similar to the linked problem because my program is for a GUI, and it requires mouse click events.
This answer by Ted Klein Bergamn explains why the window becomes unresponsive: https://stackoverflow.com/a/42719689/6220679
This is how pygame.event.get should be used:
running = True
while running:
for event in pygame.event.get():
# This lets you quit by pressing the X button of the window.
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # 1 = left mouse button, 2 = middle, 3 = right.
print('mouse up')
x,y = pygame.mouse.get_pos()
if ((width/4) <= x <= ((width/4) + (width/2))) and ((height-height/4) <= y <= ((height-height/4) + height/76)):
#move to next screen
running = False
In your case (for a simple GUI app) pygame.event.wait would probably be a good choice (it lets the program sleep while no event is in the queue).
running = True
while running:
event = pygame.event.wait()
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
print('mouse up')
x,y = pygame.mouse.get_pos()
if ((width/4) <= x <= ((width/4) + (width/2))) and ((height-height/4) <= y <= ((height-height/4) + height/76)):
#move to next screen
running = False
I'm making a game in pygame with a pressable button, but I want it to do only one thing when clicked. The code below prints "button pressed" for as long as you hold it down. What's an elegant way to change this code to make it only print that once per click?
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()
def makeButton(x,y,width,height):
if x + width > cur[0] > x and y + height > cur[1] > y:
if click == (1,0,0):
print "button pressed"
square = pygame.Rect((0,0), (32,32))
while True:
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
makeButton(square.left,square.top,square.width,square.height)
screen.fill((255,255,255))
screen.fill((55,155,0), square)
pygame.display.update()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
A simple and more efficient way to do what you want would be to explicitly check for pygame.MOUSEBUTTONDOWN events and only do the mouse event processing when necessary. You can also streamline the logic in makeButton() by using pygame's Rect class which knows how to do collision detection.
Here's what I mean:
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()
def makeButton(cur, rect):
if rect.collidepoint(cur):
print "button pressed"
square = pygame.Rect((0,0), (32,32))
while True:
screen.fill((255,255,255))
screen.fill((55,155,0), square)
pygame.display.update()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # left mouse button?
makeButton(event.pos, square)
Rather than just having a method, I'd make a button class and instantiate it for each button you need. You're also attempting to create your own mouse event handling that runs every time the game loop does, but it's better practice in pygame to pass mouse info to such a button object only on a mouse event. MOUSEBUTTONDOWN and MOUSEBUTTONUP event types will be passed to the event queue whenever there is a click. To create the behavior you describe you could have your button action execute only if the mouse is within the button bounds on the MOUSEBUTTONUP event. This page provides a good intro into pygame input handling and this page provides a detailed (though somewhat advanced) discussion of creating a general button class in pygame.
I don't know if this helps, but this worked for me.
I went from a code like this:
..........ygame.mouse.get_pressed()
if x+ button_width > mouse[0] > x and y + button_height > mouse[1] > y:
pygame.draw.rect(screen, ac, ([x, y],[button_width, button_height])
if click[0] == 1:
if bn == 0:
button_0()
if bn == 1:
button_1()
if bn == 2:
button_2()
if bn == 3:
button_3()
if bn == 4:
button_4()
if bn == 5:
button_5()
Adding a global variable is_clicked = False with the other
variables at the beginning of the program, a global statement
in the function, and 2 if statements, (6 lines of code).
Changed to this:
# (msg, (x, y coordinates),width,height,inactive color, active color,
# button number) all the info to place and label the buttons.
def button(msg, x, y, w, h, ic, ac, bn):
global is_clicked
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+ button_width > mouse[0] > x and y+ button_height > mouse[1] > y:
pygame.draw.rect(screen, ac, ([x, y],[button_width, button_height]))
if click[0] == 1 and is_clicked == False:
is_clicked = True
if bn == 0:
button_0()
if bn == 1:
button_1()
if bn == 2:
button_2()
if bn == 3:
button_3()
if bn == 4:
button_4()
if bn == 5:
button_5()
if click[0] == 0 and is_clicked == True:
is_clicked = False # set is_clicked back to False after mouse
# button up.