1. GUI baseada no módulo tkinter
- GUI é a abreviatura de Graphical User Interface. A interface gráfica do usuário não deve ser desconhecida para as pessoas que já usaram computadores, e não há necessidade de entrar em detalhes aqui.
- O módulo de desenvolvimento de GUI padrão do Python é tkinter (chamado Tkinter na versão anterior do Python 3). A partir desse nome, pode-se ver que é baseado no Tk
- Tk é um kit de ferramentas, originalmente projetado para Tcl e posteriormente portado para muitas outras linguagens de script, ele fornece controles de interface de usuário de plataforma cruzada;
- Claro, Tk não é a escolha mais recente e melhor, e não há controles GUI particularmente poderosos.
- Na verdade, desenvolver aplicativos GUI não é o melhor trabalho do Python. Se você realmente precisa usar Python para desenvolver aplicativos GUI, módulos como wxPython, PyQt, PyGTK, etc. são boas escolhas.
- Basicamente, usar o tkinter para desenvolver aplicativos GUI requer as 5 etapas a seguir:
- 1. Importe o que precisamos no módulo tkinter.
- 2. Crie um objeto de janela de nível superior e use-o para hospedar todo o aplicativo GUI.
- 3. Adicione componentes GUI ao objeto de janela de nível superior.
- 4. Organize as funções desses componentes da GUI por meio de código.
- * 5. Entre no loop de evento principal (loop principal).
Parâmetros comuns do módulo tkinter (python3)
Caso 1: use o tkinter para fazer um aplicativo GUI simples
import tkinter
import tkinter.messagebox
def main():
flag = True
# 修改标签上的文字
def change_label_text():
nonlocal flag
"""
此处使用:not flag,不能使用False
如果使用了False,程序就只能执行一次,之后的flag全部都是False
使得嵌套变量和nonlocal函数失去了意义
"""
flag = not flag
# msg:提示信息
color, msg = ('red', 'Hello, world!') \
if flag else ('blue', 'Goodbye, world!') # flag为真设置红色,flag为假设置蓝色
label.config(text=msg, fg=color) # 重新配置
# 确认退出
def confirm_to_quit():
if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):
top.quit()
# 创建顶层窗口
top = tkinter.Tk()
# 设置窗口大小,geometry:几何图形
top.geometry('240x160')
# 设置窗口标题
top.title('小游戏')
# 创建标签对象并添加到顶层窗口,bg:背景,fg:前景。
label = tkinter.Label(top, text='Hello, world!', font='Arial -32', fg='red')
label.pack(expand=1) # 将标签添加到主窗口
# 创建一个装按钮的容器
panel = tkinter.Frame(top)
# 创建按钮对象 指定添加到哪个容器中 通过command参数绑定事件回调函数
button1 = tkinter.Button(panel, text='修改', command=change_label_text) # 修改颜色和文本
button1.pack(side='left')
button2 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
button2.pack(side='right')
panel.pack(side='bottom')
# 开启主事件循环
tkinter.mainloop()
if __name__ == '__main__':
main()
- Deve-se notar que os aplicativos GUI são geralmente orientados a eventos. O motivo para entrar no loop de evento principal é monitorar a ocorrência de vários eventos, como o mouse e o teclado, e executar o código correspondente para processar o evento, porque o evento continuará para ocorrer. Portanto, esse loop precisa estar em execução e aguardando a ocorrência do próximo evento.
- Por outro lado, Tk fornece três gerenciadores de layout para a colocação de controles. Os controles podem ser posicionados através do gerenciador de layout. Os três gerenciadores de layout são: Placer (o desenvolvedor fornece o tamanho e a localização do controle), Packer (preencher automaticamente o controle para a posição apropriada) e Grade (coloque o controle com base nas coordenadas da grade)
2. Use Pygame para desenvolvimento de jogos
- Pygame é um módulo Python de código aberto especificamente para o desenvolvimento de aplicativos multimídia (como videogames), que inclui suporte para imagens, sons, vídeos, eventos, colisões, etc.
- Pygame é construído com base em SDL. SDL é uma biblioteca de desenvolvimento multimídia de plataforma cruzada, implementada em linguagem C e é amplamente utilizada no desenvolvimento de jogos, simuladores, jogadores, etc.
- O Pygame permite que os desenvolvedores de jogos não sejam mais limitados pela linguagem subjacente e possam prestar mais atenção à função e à lógica do jogo.
Consulte o documento do pygame em chinês
1. pygame.init (): inicializa todos os módulos importados do pygame
2. pygame.display.set_mode (): inicializa uma interface pronta para ser exibida
3. pygame.display.set_caption (): define a legenda da janela atual
4. pygame.quit (): desinstala todos os módulos pygame importados
5. screen.fill (): Defina a cor de fundo da janela
6. pygame.draw.circle (): desenhe um círculo
7. pygame.display.flip (): atualiza a janela atual (a janela de renderização apresentará a imagem desenhada)
8. screen.blit (): coloca uma imagem em cima de um objeto (dois parâmetros: imagem: a imagem a ser colocada, posição: as coordenadas da imagem)
注意:
1.blit()不会更新屏幕,它在缓冲区中绘制图像;
2.需要结合update()/flip()将缓冲区发送到视频卡,才能绘制出图像来。
9. pygame.time.delay (10): Altere a posição da bola a cada 10 milissegundos e atualize a janela
Caso 2: fazer pequenos jogos, bolas grandes e pequenas bolas
O primeiro passo: fazer a janela do jogo
import pygame
def main():
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
running = True
# 开启一个事件"循环处理"发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if __name__ == '__main__':
main()
Etapa 2: Desenhar na janela
- Você pode desenhar na janela através da função do módulo de desenho no pygame. Os gráficos que podem ser desenhados incluem: linhas, retângulos, polígonos, círculos, elipses, arcos, etc.
- O sistema de coordenadas da tela deve definir o canto superior esquerdo da tela para a origem da coordenada (0, 0), à direita é a direção positiva do eixo xe para baixo é a direção positiva do eixo y. expressando a posição ou definindo o tamanho, nossas unidades padrão são todas É um pixel (um pixel é um ponto na tela)
- As cores no pygame são representadas pelas três cores primárias de cor e luz, ou seja, o valor RGB da cor é especificado por meio de uma tupla ou lista, e cada valor está entre 0 e 255, pois cada cor primária usa um 8 bits (bit) As três cores equivalem a um total de 24 bits, o que costuma ser chamado de "representação de cores de 24 bits".
import pygame
def main():
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
# 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
screen.fill((242, 242, 242))
# 绘制一个圆(参数分别是: 屏幕, 颜色, 圆心位置, 半径, 0表示填充圆)
pygame.draw.circle(screen, (255, 0, 0,), (100, 100), 10, 0)
# 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
pygame.display.flip()
running = True
# 开启一个事件循环处理发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if __name__ == '__main__':
main()
Etapa 3: carregue a imagem
- Se você precisa carregar uma imagem diretamente na janela, você pode usar a função do módulo de imagem no pygame para carregar a imagem e então renderizar a imagem através do método blit do objeto janela obtido anteriormente.
import pygame
def main():
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
# 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
screen.fill((255, 255, 255))
# 通过指定的文件名加载图像
ball_image = pygame.image.load('D:/360Safe/ball.png')
# 在窗口上渲染图像
screen.blit(ball_image, (50, 50))
# 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
pygame.display.flip()
running = True
# 开启一个事件循环处理发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if __name__ == '__main__':
main()
Etapa 4: perceber o efeito de animação
- Na verdade, para obter efeitos de animação, o próprio princípio também é muito simples, ou seja, a reprodução contínua de imagens descontínuas, desde que um certo número de quadros por segundo seja atingido, então um efeito de animação relativamente suave pode ser feito.
- Se você quiser fazer a bola no código acima se mover, você pode usar uma variável para indicar a posição da bola e modificar a posição da bola no loop e então atualizar a janela inteira.
import pygame
def main():
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
# 定义变量来表示小球在屏幕上的位置
x, y = 50, 50
running = True
# 开启一个事件循环处理发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
pygame.draw.circle(screen, (255, 0, 0,), (x, y), 30, 0)
pygame.display.flip()
# 每隔50毫秒就改变小球的位置再刷新窗口
pygame.time.delay(30)
x, y = x + 5, y + 5
if __name__ == '__main__':
main()
Etapa 5: detecção de colisão
- Normalmente existem muitos objetos em um jogo, e a "colisão" entre esses objetos é inevitável, como uma granada atingindo um avião, uma caixa atingindo o solo, etc.
- A detecção de colisão é uma questão crucial que deve ser tratada na maioria dos jogos.O módulo sprite do pygame fornece suporte para detecção de colisão.
- Para detectar se as duas bolas colidem, tão fácil:
- Basta verificar se a distância entre o centro da esfera é menor que a soma dos raios das duas esferas.
- Para fazer mais bolas pequenas, podemos processar eventos do mouse para criar bolas pequenas com cores, tamanhos e velocidades de movimento aleatórios na posição do clique do mouse, para que possamos aplicar o conhecimento orientado a objetos que aprendemos antes.
from enum import Enum, unique
from math import sqrt
from random import randint
import tkinter
import pygame
@unique
class Color(Enum):
"""颜色"""
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (242, 242, 242)
@staticmethod
def random_color():
"""获得随机颜色"""
r = randint(0, 255)
g = randint(0, 255)
b = randint(0, 255)
return (r, g, b)
class Ball(object):
"""球"""
def __init__(self, x, y, radius, sx, sy, color=Color.RED):
"""初始化方法"""
self.x = x
self.y = y
self.radius = radius
self.sx = sx
self.sy = sy
self.color = color
self.alive = True
def move(self, screen):
"""移动"""
self.x += self.sx
self.y += self.sy
if self.x - self.radius <= 0 or \
self.x + self.radius >= screen.get_width():
self.sx = -self.sx
if self.y - self.radius <= 0 or \
self.y + self.radius >= screen.get_height():
self.sy = -self.sy
def eat(self, other):
"""吃其他球"""
if self.alive and other.alive and self != other:
dx, dy = self.x - other.x, self.y - other.y
distance = sqrt(dx ** 2 + dy ** 2)
if distance < self.radius + other.radius \
and self.radius > other.radius:
other.alive = False
self.radius = self.radius + int(other.radius * 0.146)
def draw(self, screen):
"""在窗口上绘制球"""
pygame.draw.circle(screen, self.color,
(self.x, self.y), self.radius, 0)
Etapa 6: tratamento de eventos
- Os eventos de mouse podem ser processados no loop de eventos e o tipo de evento pode ser determinado por meio do atributo type do objeto de evento
- Então você pode obter a posição do clique do mouse através do atributo pos
- Se você deseja manipular eventos de teclado neste local, a abordagem é semelhante a manipular eventos de mouse
def main():
# 定义用来装所有球的容器
balls = []
# 初始化导入的pygame中的模块
pygame.init()
# 初始化用于显示的窗口并设置窗口尺寸
screen = pygame.display.set_mode((800, 600))
# 设置当前窗口的标题
pygame.display.set_caption('大球吃小球')
running = True
# 开启一个事件循环处理发生的事件
while running:
# 从消息队列中获取事件并对事件进行处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 处理鼠标事件的代码
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
# 获得点击鼠标的位置
x, y = event.pos
radius = randint(10, 100)
sx, sy = randint(-10, 10), randint(-10, 10)
color = Color.random_color()
# 在点击鼠标的位置创建一个球(大小、速度和颜色随机)
ball = Ball(x, y, radius, sx, sy, color)
# 将球添加到列表容器中
balls.append(ball)
screen.fill((255, 255, 255))
# 取出容器中的球 如果没被吃掉就绘制 被吃掉了就移除
for ball in balls:
if ball.alive:
ball.draw(screen)
else:
balls.remove(ball)
pygame.display.flip()
# 每隔50毫秒就改变球的位置再刷新窗口
pygame.time.delay(50)
for ball in balls:
ball.move(screen)
# 检查球有没有吃到其他的球
for other in balls:
ball.eat(other)
def confirm_to_quit():
if tkinter.messagebox.askokcancel('温馨提示', '确定要退出吗?'):
top.quit()
# # 创建顶层窗口
# top = tkinter.Tk()
# # 创建一个装按钮的容器
# panel = tkinter.Frame(top)
# # 创建按钮对象 指定添加到哪个容器中 通过command参数绑定事件回调函数
# button1 = tkinter.Button(panel, text='退出', command=confirm_to_quit)
# button1.pack(side='right')
# panel.pack(side='bottom')
# # 开启主事件循环
# tkinter.mainloop()
if __name__ == '__main__':
main()