How to Implement Option Buttons and Change the Button Color in Pygame

How do I implement option buttons and change the button color in PyGame?

When you draw the button, you have to set the color dependent on the global variable clicked:

def draw_button(self):

global clicked

# get mouse position
pos = pygame.mouse.get_pos()

# create pygame Rect object for the button
button_rect = Rect(self.x, self.y, self.width, self.height)

# check mouseover and clicked conditions
hover = button_rect.collidepoint(pos)
if hover and pygame.mouse.get_pressed()[0] == 1:
clicked = not clicked

color = self.button_col
if clicked:
color = self.click_col
elif hover:
color = self.hover_col

pygame.draw.rect(screen, color, button_rect)

Anyway, that won't satisfy you, because 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.

You have to use MOUSEBUTTONDOWN event. The MOUSEBUTTONDOWN event occurs once when you click the mouse button and the MOUSEBUTTONUP event occurs once when the mouse button is released. The pygame.event.Event() object has two attributes that provide information about the mouse event. pos is a tuple that stores the position that was clicked. button stores the button that was clicked.


If you have multiple buttons that you have to interact with each other, a single clicked status is not enough. You need a separate "clicked" state for each button. If the clicked state of 1 button becomes True, the states of the other keys must be set to False. I recommend to implement a RadioButton class for this.

See also Mouse and Sprite.

Minimal example:
repl.it/@Rabbid76/PyGame-RadioButton

import pygame

class RadioButton(pygame.sprite.Sprite):
def __init__(self, x, y, w, h, font, text):
super().__init__()
text_surf = font.render(text, True, (0, 0, 0))
self.button_image = pygame.Surface((w, h))
self.button_image.fill((96, 96, 96))
self.button_image.blit(text_surf, text_surf.get_rect(center = (w // 2, h // 2)))
self.hover_image = pygame.Surface((w, h))
self.hover_image.fill((96, 96, 96))
self.hover_image.blit(text_surf, text_surf.get_rect(center = (w // 2, h // 2)))
pygame.draw.rect(self.hover_image, (96, 196, 96), self.hover_image.get_rect(), 3)
self.clicked_image = pygame.Surface((w, h))
self.clicked_image.fill((96, 196, 96))
self.clicked_image.blit(text_surf, text_surf.get_rect(center = (w // 2, h // 2)))
self.image = self.button_image
self.rect = pygame.Rect(x, y, w, h)
self.clicked = False
self.buttons = None

def setRadioButtons(self, buttons):
self.buttons = buttons

def update(self, event_list):
hover = self.rect.collidepoint(pygame.mouse.get_pos())
for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
if hover and event.button == 1:
for rb in self.buttons:
rb.clicked = False
self.clicked = True

self.image = self.button_image
if self.clicked:
self.image = self.clicked_image
elif hover:
self.image = self.hover_image

pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
font50 = pygame.font.SysFont(None, 50)

radioButtons = [
RadioButton(50, 40, 200, 60, font50, "option 1"),
RadioButton(50, 120, 200, 60, font50, "option 2"),
RadioButton(50, 200, 200, 60, font50, "option 3")
]
for rb in radioButtons:
rb.setRadioButtons(radioButtons)
radioButtons[0].clicked = True

group = pygame.sprite.Group(radioButtons)

run = True
while run:
clock.tick(60)
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
run = False

group.update(event_list)

window.fill(0)
group.draw(window)
pygame.display.flip()

pygame.quit()
exit()

How do I change the color of a button once it is clicked in Pygame?

global clickedButtons,sumOfCosts,textDisp
clickedButtons=[]
sumOfCosts=[0,0]
textDisp = None

def addCostsAndDisplay(msg,cost,weight):
global sumOfCosts
sumOfCosts[0]+=cost
sumOfCosts[1]+=weight

basicfont = pygame.font.SysFont(None, 48)
text = basicfont.render('adding '+str(msg)+' adds up to '+str(sumOfCosts[0])+' and weighs '+str(sumOfCosts[1]), True, (255, 0, 0), (255, 255, 255))

return text

def button2(msg,x,y,w,h,ic,ac,cost=1,weight=1, action=None):
global clickedButtons,textDisp
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(gameDisplay, ac, (x,y,w,h))

if click[0] == 1 and action != None:
if not (msg in clickedButtons):
#Save that this button has been clicked
clickedButtons.append(msg)
textDisp=addCostsAndDisplay(msg,cost,weight)
if action == "START":
game_loop()
elif action == "BACK":
game_intro()
quit()

elif action == "Playstation 4":
print("")
else:
#Check if this button has been clicked
if (msg in clickedButtons):
pygame.draw.rect(gameDisplay, ac, (x,y,w,h))
else:
pygame.draw.rect(gameDisplay, ic, (x,y,w,h))

smallText = pygame.font.Font("freesansbold.ttf", 20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)

#Selection Screen
def game_select_items_menu():
global textDisp
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()

gameSelectItems = False
while not gameSelectItems:

for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()

blank_image(x, y)
if (not textDisp is None):

screen=pygame.display.get_surface()
textRect=textDisp.get_rect()
textRect.centerx = x
textRect.centery = y
screen.blit(textDisp,textRect)

button2("Xbox One", 374, 60, 168, 48, white, orange,10,20,"Xbox One") #XBOX ONE - BUTTON (TOP ROW)

button2("Playstation 4", 200, 60, 168, 48, white, orange,20,20"Playstation 4")#PLAYSTATION 4 - BUTTON (TOP ROW)

button("Kettle", 30, 60, 163, 48, white, orange)#Kettle - BUTTON (TOP ROW)

button("Lewi Jeans", 374, 160, 168, 48, white, orange)#LEWI JEANS - BUTTON(SECOND ROW)

button("MacBook", 200, 160, 168, 48, white, orange)#MACBOOK - BUTTON (SECOND ROW)

button("Samsung TV", 30, 160, 163, 48, white, orange)#SAMSUNG TV - BUTTON (SECOND ROW)

button("Nike Air Max", 374, 250, 168, 48, white, orange)#NIKE AIR MAX - BUTTON (THIRD ROW)

button("Tablet", 200, 250, 168, 48, white, orange)#TABLET - BUTTON (THIRD ROW)

button("Perfume", 30, 250, 163, 48, white, orange)#PERFUME - BUTTON (THIRD ROW)

#button("", 30, 340, 300, 150, white, orange)#Print Box

#Bottom buttons(Start,Back)

button2("START", 374, 370, 163, 48,green, green_bright,0,0 "START")#START - BUTTON (BOTTOM)

button2("BACK", 374, 430, 163, 48, green, green_bright,0,0 "BACK")#BACK - BUTTON (BOTTOM)

pygame.display.update()

clock.tick(80) #Setting the fps

Change these lines to change the coordinates of the text (They are close to the end)

textRect.centerx = x
textRect.centery = y

Try it out.

Changing background color to buttons generated in a for loop

If someone is searching for the same thing the problem was that the buttons could configure because they weren't even saved anywhere. My solution was to create a separate function to create buttons with a return statement to initially save the buttons and then using tuples call those buttons to configure them.

def __init__(self):
super().__init__()
self.button = {}
self.turn = 'X'
for i in range(3):
for j in range(3):
self.button[(i,j)]=self.create_button(i, j)

def create_button(self, x, y):
self.button1 = Button(root, width=10, height=5, bg='#E0E0E0', fg='#6D6D6D', command=lambda i=x, j=y: self.pressed_button(i, j),)
self.button1.grid(row=x, column=y)
return self.button1

def pressed_button(self, i, j):
label = Label(root, text=self.turn, fg='#E0E0E0', bg='#6D6D6D')
label.grid(row=i, column=j)
self.button[(i, j)].configure(bg='#6D6D6D')

My buttons in Pygame are not changing colors due to overlapping

Thought gamestate parameters were the hangup; so I put those in a dictionary, to print them all out during clicks. It'll be good for debugging. Turned out to be if / elif chain, but I don't need credit for that.

Would like to mention that ya don't need to initialize objects more than once in your various modules though; can run into circular imports with overlapping values. Might think something's one way and it ends up being another.

Game1.py

#! /usr/bin/env python3

from pygame_init import *
from Game2 import *

## Module for game logic

def keep_waiting_3():
our_game_display .fill(black)
text('Nothing still...wait! You hear something!', 0, halfheight -100)
win .blit(our_game_display, origin)
pygame .display .update()

def keep_waiting_2():
our_game_display.fill(black)
text('Are you sure you want to keep waiting?', 0, halfheight -100)
text("Maybe this isn't worth it...You could always choose the other options.", 0, halfheight -50)
win .blit(our_game_display, origin)
Wait3Button .draw( win, white)
SearchButton .draw(win, white)
YellHelpButton .draw(win, white)
pygame.display .update()

def keep_waiting():
our_game_display .fill( black )
text( 'You continue to sit and wait. Will anything happen?', 0, halfheight -100 )
text( 'You can keep waiting..or choose the other options.', 0, halfheight -50 )
win .blit( our_game_display, origin )
Wait2Button .draw( win, white)
SearchButton .draw(win, white)
YellHelpButton .draw(win, white)
pygame .display .update()

def yell_choice_2():
our_game_display .fill( black )
text( "Despite the warning, you yell 'Hello? Who's there?'", 0, halfheight -100 )
win .blit( our_game_display, origin )
pygame .display .update()

def yell_choice():
our_game_display .fill( black )
text( "You yell 'Hello?', out into the darkness.", 0, halfheight -100 )
text( "Immediately you hear someone whisper back 'Be quiet!'.", 0, halfheight -50 )
win .blit( our_game_display, origin )
Yell2Button .draw( win, white)
pygame .display .update()

def sit_choice():
our_game_display .fill( black )
text( 'So you decided to sit and wait... nothing happens. What now?', 0, halfheight -100 )
win .blit( our_game_display, origin )
WaitButton .draw( win, white )
SearchButton .draw( win, white)
YellHelpButton .draw( win, white)
pygame .display .update()

def search_choice():
our_game_display .fill( black )
text( 'So you decided to search.', 0, halfheight -100 )
win .blit( our_game_display, origin )
pygame .display .update()

def beginning_question():
our_game_display .fill( black )
text( 'The story of this game depends on your choices. Do you wish to play?', 0, halfheight -100 )
win .blit( our_game_display, origin )
PlayButton .draw( win, white )
pygame .display .update()

def begin_game(): ## call to start again
our_game_display .fill( black )
text( 'You wake up, or... at least you think you do. Even though your eyes are open,', 0, halfheight -300 )
text( "they still can't detect anything in the complete darkness that surrounds you.", 0, halfheight -270 )
text( 'What do you do?', 0, halfheight -210 )
win .blit( our_game_display, origin )
SitWaitButton .draw( win, white )
SearchButton .draw( win, white )
YellHelpButton .draw( win, white )
pygame .display .update()

## game loop .. color, (x), y, msg
PlayButton = button( black, 0, halfheight, "Let's play." )
SitWaitButton = button( black, 1, halfheight +50, 'Sit and wait...' )
SearchButton = button( black, 1, halfheight +100, 'Get up and try to search your surroundings' )
YellHelpButton = button( black, 1, halfheight +150, 'Yell to see if anyone is there' )
WaitButton = button( black, 1, halfheight +200, 'Keep waiting...' )
Wait2Button = button( black, 1, halfheight +250, 'Wait a little more...' )
Wait3Button = button( black, 1, halfheight +200, 'Wait a bit more...' )
Yell2Button = button( black, 1, halfheight +150, 'Yell again' )

while True:
if yell2_option == 'Go': yell_choice_2()
elif yell_option == 'Go': yell_choice()
elif search_option == 'Go': search_choice()
elif wait3_option == 'Go': keep_waiting_3()
elif wait2_option == 'Go': keep_waiting_2()
elif wait_option == 'Go': keep_waiting()
elif sit_option == 'Go': sit_choice()
elif game_begun == 'Go': begin_game()
else: beginning_question()

for event in pygame .event .get():
pos = pygame .mouse .get_pos()
if event .type == pygame .QUIT:
running = False
pygame .quit()
quit()

## yes & no buttons for beginning question
if event .type == pygame .MOUSEBUTTONDOWN: ## menu if/else
if PlayButton .isOver( pos ) and para['menu'] == True:
para['menu'] = False
game_begun = 'Go'

elif YellHelpButton .isOver( pos ) and para['menu'] == False and para['lock_1'] == True:
para['wait_lock2'] = True
para['wait_lock3'] = True
para['lock_1'] = False
para['yell_lock'] = False
yell_option = 'Go'
print( 'YellHelp button is working', para )

elif SitWaitButton .isOver( pos ) and para['menu'] == False and para['sit_lock'] == True:
para['wait_lock'] = False
para['sit_lock'] = False
sit_option = 'Go'
print( 'SitWait button is working', para )

elif SearchButton .isOver( pos ) and para['menu'] == False and para['lock_1'] == True:
para['wait_lock2'] = True
para['wait_lock3'] = True
para['lock_1'] = False
search_option = 'Go'
print( 'Search button is working', para )

elif WaitButton .isOver( pos ) and para['wait_lock'] == False:
para['lock_1'] = True
para['wait_lock'] = True
para['wait_lock2'] = False
wait_option = 'Go'
print( 'Wait button is working', para )

elif Wait2Button .isOver( pos ) and para['wait_lock2'] == False:
para['lock_1'] = True
para['wait_lock2'] = True
para['wait_lock3'] = False
wait2_option = 'Go'
print( 'Wait button 2 is working', para )

elif Wait3Button .isOver( pos ) and para['wait_lock3'] == False:
para['wait_lock2'] = True
para['wait_lock3'] = True
para['lock_1'] = False
wait3_option = 'Go'
print( 'Wait button 3 is working', para )

elif Yell2Button .isOver( pos ) and para['yell_lock'] == False:
para['yell_lock'] = True
yell2_option = 'Go'
print( 'Yell 2 button is working', para )

if event .type == pygame .MOUSEMOTION: ## first option buttons
PlayButton .color = black
YellHelpButton .color = black
SitWaitButton .color = black
SearchButton .color = black
WaitButton .color = black
Wait2Button .color = black
Wait3Button .color = black
Yell2Button .color = black

if PlayButton .isOver( pos ) and para['menu'] == True:
PlayButton .color = blue
if YellHelpButton .isOver( pos ): YellHelpButton .color = blue
if SitWaitButton .isOver( pos ): SitWaitButton .color = blue
if SearchButton .isOver( pos ): SearchButton .color = blue
if WaitButton .isOver( pos ): WaitButton .color = blue
if Wait2Button .isOver( pos ): Wait2Button .color = blue
if Wait3Button .isOver( pos ): Wait3Button .color = blue
if Yell2Button .isOver( pos ): Yell2Button .color = blue

Game2.py

from pygame_init import *

## module for helper functions

class button():
def __init__( self, color, x, y, text ):
self .color = color
self .x = x
self .y = y
self .width = 20
self .height = 10
self .text = text

def draw( self, win, outline = None ):
## Call this method to draw button on screen
if self .text != '':
text = buttonfont .render( self .text, 1, white )
self .width = text .get_width()
self .height = text .get_height()
## optional x parameter. If x pos given, use it, otherwise generate
if self .x == -1: ## -1 = left align
self .x = 20
elif self .x == 0: ## 0 = center align
self .x = halfwidth -( self .width /2 )
elif self .x == 1: ## 1 = right align
self .x = Width -self .width -20
if outline:
pygame .draw .rect( win, outline, ( self .x -12, self .y -12, self .width +24, self .height +24 ), 0 )
pygame .draw .rect( win, self .color, ( self .x -10, self .y -10, self .width +20, self .height +20 ), 0 )
if self .text != '':
win .blit( text, ( self .x, self .y ) )

def isOver( self, pos ):
## mouse position or a tuple of ( x, y ) coordinates
return pos[0] > self .x -13 and pos[0] < self .x -13 +self .width +26 \
and pos[1] > self .y -13 and pos[1] < self .y -13 +self .height +26

def text( text, xx, yy ): ## Function to position and draw text on screen
antialias = True
text_surface = textfont .render( text, antialias, white )
text_rect = text_surface .get_rect()
if abs( xx ) <= 1: ## generate x pos if -1, 0, 1
ww = text_surface .get_width() /2

## optional x parameter. If given, use it, otherwise justify
if xx == -1: ## -1 = left align
xx = ww +20
elif xx == 0: ## 0 = center align
xx = halfwidth
elif xx == 1: ## 1 = right align
xx = Width -ww -20

text_rect .center = ( xx, yy )
our_game_display .blit( text_surface, text_rect )

pygame_init.py

import pygame

## Module to hold all of the initial states of variables.
## Essentially globals, to be shared among the other modules.

pygame .init()
pygame .font .init() ## don't need to initialize font every turn, just do it once

screensize = Width, Height = 800, 700
halfwidth, halfheight = Width /2, Height /2

win = pygame .display .set_mode( screensize )
our_game_display = pygame .Surface( screensize )

origin = 0, 0 ## use variables for commonly used values
black = 0, 0, 0
blue = 0, 0, 139
white = 255, 255, 255

textfont = pygame .font .SysFont( 'comicsans', 28 )
buttonfont = pygame .font .SysFont( 'comicsans', 30 )

game_begun = 'Input' ## beginning choice
search_option = 'Input'
sit_option = 'Input'
yell_option = 'Input'
wait_option = 'Input'
wait2_option = 'Input'
wait3_option = 'Input'
yell2_option = 'Input'

para = { ## gamestate parameters
'menu': True,
'lock_1': True,
'sit_lock': True,
'wait_lock': True,
'wait_lock2': True,
'wait_lock3': True,
'yell_lock': True,
}

Change the color of 2 buttons in case of clicking on one of them

You can use the command to call a function that sets the background color of the two buttons permanently (via configuring bg property).

The following code changes the color of both buttons when the wrong button is pressed:

import tkinter as tk

def change_color(btn1, btn2):
btn1.configure(bg="green")
btn2.configure(bg="red")

root = tk.Tk()

btn = tk.Button(root,text="correct button")
btn.pack()

btn2 = tk.Button(root,text="wrong button", command=lambda: change_color(btn, btn2))
btn2.pack()

root.mainloop()

Changing the color of multiple buttons

SOLUTION

The path that contains the buttons siblings is self.parent.children. With this information, you can change the background_color of all the buttons.

EXAMPLE

def change_butt_color(self, *args):
for child in self.parent.children:
child.background_color = 1,1,1,1
self.background_color = 0,0,0,0

notice how the buttons aren't being searched for by ids. Instead, self.parent.children is used to find the button's parents children, which is, its self of course and the siblings of its self (self).



Related Topics



Leave a reply



Submit