Pygame not drawing rectangle while clicking
To make the rectangle permanent, you need to draw the rectangle in the application loop. The event occurs only once in a single frame. Add a variable clicked = False
. Set the variable when the event occurs. And draw the rectangle dependent on the state of the variable:
clicked = False
while True:
screen.fill(background)
mouse = pygame.mouse.get_pos()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
if ev.type == pygame.MOUSEBUTTONDOWN:
if 10 <= mouse[0] <= 10 + 180 and 10 <= mouse[1] <= 10 + 190:
clicked = True
line_color = (212, 212, 255)
draw_line()
highlight()
if clicked:
pygame.draw.rect(screen,background,(10,10,180,190))
pygame.display.update()
Simplify your code:
Create a list of
pygame.Rect
objects for the rectanglesrect_list = [pygame.Rect(10, 10, 180, 190), ...]
Create a list for the stated of the fields
clicked_list = [0 for _ in rect_list]
Use
collideponit
to test if the mouse is on a rectangle:for rect in rect_list:
if rect.collidepoint(mouse):
pygame.draw.rect(screen, hover_color, rect)Use
collidepoint
to evaluate whether a field is clicked and to change the state of the fieldif ev.type == pygame.MOUSEBUTTONDOWN:
for i, rect in enumerate(rect_list):
if rect.collidepoint(ev.pos):
clicked_list[i] = 1Draw the field in a loop depending on its state:
for i, rect in enumerate(rect_list):
if clicked_list[i]:
pygame.draw.rect(screen,background,rect)
Complete code:
import pygame
pygame.init()
res = (600,600)
screen = pygame.display.set_mode(res)
pygame.display.set_caption("Tic Tac Toe")
background = (255,150,150)
color_light = (170,170,170)
color_dark = (100,100,100)
hover_color = (255, 204, 203)
width = screen.get_width()
height = screen.get_height()
def draw_line():
pygame.draw.rect(screen, line_color, (190,10,10,580))
pygame.draw.rect(screen, line_color, (390, 10, 10, 580))
pygame.draw.rect(screen, line_color, (10, 200, 580, 10))
pygame.draw.rect(screen, line_color, (10, 390, 580, 10))
rect_list = [
pygame.Rect(10, 10, 180, 190),
pygame.Rect(200, 10, 180, 190),
pygame.Rect(400, 10, 180, 190),
pygame.Rect(10, 210, 180, 190),
pygame.Rect(200, 210, 180, 190),
pygame.Rect(400, 210, 180, 190),
pygame.Rect(10, 400, 180, 190),
pygame.Rect(200, 400, 180, 190),
pygame.Rect(400, 400, 180, 190)]
clicked_list = [0 for _ in rect_list]
def highlight():
for rect in rect_list:
if rect.collidepoint(mouse):
pygame.draw.rect(screen, hover_color, rect)
while True:
mouse = pygame.mouse.get_pos()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
if ev.type == pygame.MOUSEBUTTONDOWN:
for i, rect in enumerate(rect_list):
if rect.collidepoint(ev.pos):
clicked_list[i] = 1
line_color = (212, 212, 255)
screen.fill(background)
draw_line()
highlight()
for i, rect in enumerate(rect_list):
if clicked_list[i] == 1:
pygame.draw.rect(screen,background,rect)
pygame.display.update()
How can i draw rectangles in multiple rows and columns in pygame?
Use nested loops:
no_of_rows = 8
no_of_cols = 8
x0, y0 = 20, 20 # just for example
dx, dy = 70, 16 # just for example
for row in range(no_of_rows):
for col in range(no_of_cols):
pygame.draw.rect(screen1, brick_colors[b], (x0 + col*dx, y0 + row*dy, 60, 12))
I recommend making a list of the block locations and drawing the block rectangles from the locations in the list. If a block is destroyed, all you have to do is remove the location from the list:
blocks = []
for row in range(no_of_rows):
for col in range(no_of_cols):
blocks.append((x0 + col*dx, y0 + row*dy))
for pos in blocks:
pygame.draw.rect(screen1, brick_colors[b], (pos[0], pos[1], 60, 12))
This can be further improved by using pygame.Rect
objects:
blocks = []
for row in range(no_of_rows):
for col in range(no_of_cols):
rect = pygame.Rect(x0 + col*dx, y0 + row*dy, 60, 12)
blocks.append(rect )
for rect in blocks:
pygame.draw.rect(screen1, brick_colors[b], rect )
If you want to draw checkered tiles overall the screen, the draw the tiles on a background surface before the application loop and blit
the background surface on the screen in the application loop for best performance.
import pygame
screen = pygame.display.set_mode([500, 500])
clock = pygame.time.Clock()
background = pygame.Surface(screen.get_size())
color1 = (64, 64, 128)
color2 = (196, 128, 64)
sx, sy = 50, 50
for i in range((screen.get_width() + sx -1) // sx):
for j in range((screen.get_height() +sy - 1) // sy):
c = color1 if (i+j) % 2 == 0 else color2
pygame.draw.rect(background, c, (i*sx, j*sy, sx, sy))
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.blit(background, (0, 0))
pygame.display.update()
pygame.quit()
Drawing a rectangle on mouse position in Python using pygame
You have to manage the rectangles in a list. Crate a list for the positions of the rectangles:
pos_list = []
Add a new position to the list when clicked with the mouse:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.MOUSEBUTTONDOWN:
pos_list.append(event.pos)
After you clear the display and before you update the display, draw the rectangles in a loop at the positions stored in the list:
display.fill(background_color)
for x, y in pos_list:
pygame.draw.rect(display, rect_color, (x, y, rect_size, rect_size))
pygame.display.update()
Minimal example
import pygame
pygame.init()
display = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
rect_color = "red"
rect_size = 40
pos_list = []
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
pos_list.append(event.pos)
display.fill(0)
for x, y in pos_list:
pygame.draw.rect(display, rect_color, (x, y, rect_size, rect_size))
pygame.display.update()
clock.tick(60)
pygame.quit()
exit()
If you want to align the rectangles on a grid, you have to calculate the row and column depending on the mouse position:
if event.type == pygame.MOUSEBUTTONDOWN:
col = event.pos[0] // rect_size
row = event.pos[1] // rect_size
pos_list.append((col, row))
Minimal example:
import pygame
pygame.init()
display = pygame.display.set_mode((320, 320))
clock = pygame.time.Clock()
rect_color = "red"
rect_size = 40
background = pygame.Surface(display.get_size())
ts, w, h, c1, c2 = 40, *display.get_size(), (32, 32, 32), (64, 64, 64)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
pygame.draw.rect(background, color, rect)
pos_list = []
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
col = event.pos[0] // rect_size
row = event.pos[1] // rect_size
pos_list.append((col, row))
display.blit(background, (0, 0))
for col, row in pos_list:
pygame.draw.rect(display, rect_color, (col*rect_size, row*rect_size, rect_size, rect_size))
pygame.display.update()
clock.tick(60)
pygame.quit()
exit()
Pygame doesn't draw rectangles on the screen after a specific threshold
If data['n']
is greater than SCREEN_W
, RECT_W
is 0. A coordinate is truncated when drawing. You cannot draw a fraction of a pixel. The size of the rectangle can only be integral (0, 1, 2 ...). Hence, you cannot draw a rectangle with a size less than 1.
You can draw the rectangles on a large surface and scale down the surface. However, the rectangles get blurred. So, this is no good option.
How to draw rectangle and circles in Pygame environment
You have to create a pygame.Surface
, instead of creating a new window (pygame.display.set_mode
).
The pixel format of the Surface must include a per-pixel alpha (SRCALPHA
). The center point of the circle must be the center of the Surface. The radius
must be half the size of the Surface:
self.image = pygame.Surface((size, size), pygame.SRCALPHA)
radius = size // 2
pygame.draw.circle(self.image, color, (radius, radius), radius)
Class Object
:
class Object(pygame.sprite.Sprite):
def __init__(self, position, color, size, type):
# create square sprite
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((size, size), pygame.SRCALPHA)
self.rect = self.image.get_rect()
if type == 'agent':
self.image.fill(color)
else:
radius = size // 2
pygame.draw.circle(self.image, color, (radius, radius), radius)
# initial conditions
self.start_x = position[0]
self.start_y = position[1]
self.state = np.asarray([self.start_x, self.start_y])
self.rect.x = int((self.start_x * 500) + 100 - self.rect.size[0] / 2)
self.rect.y = int((self.start_y * 500) + 100 - self.rect.size[1] / 2)
Related Topics
What Does a . in an Import Statement in Python Mean
Making All Possible Combinations of a List
Replacing Column Values in a Pandas Dataframe
How to Find All the Subsets of a Set, with Exactly N Elements
How to Check If Type of a Variable Is String
Calling Class Staticmethod Within the Class Body
Subprocess.Call Using String VS Using List
Large, Persistent Dataframe in Pandas
Emulating Bash 'Source' in Python
Selenium Compound Class Names Not Permitted
How to Ignore Deprecation Warnings in Python
Pyaudio Working, But Spits Out Error Messages Each Time
Difference Between Filter and Filter_By in SQLalchemy
Maximum Value for Long Integer
Working with Big Data in Python and Numpy, Not Enough Ram, How to Save Partial Results on Disc
How to Make Program Go Back to the Top of the Code Instead of Closing
How to Merge a Transparent Png Image with Another Image Using Pil