Pygame使用NOFRAME无边框标识做自定义标题栏后如何移动及调整窗口大小
Pygame NOFRAME无框窗口拖拽移动、边缘调整大小实现方案
你可以通过自行监听鼠标事件,手动实现窗口位置、大小的控制逻辑,以下是具体实现方案:
核心实现逻辑
1. 拖拽移动窗口
- 划定自定义标题栏的响应区域,监听该区域的
pygame.MOUSEBUTTONDOWN事件,记录此时鼠标坐标与窗口左上角坐标的偏移量 - 监听
pygame.MOUSEMOTION事件,若鼠标左键处于按下状态且拖拽开关已激活,就用当前鼠标坐标减去偏移量得到窗口新的左上角坐标,更新窗口位置即可
2. 边缘拖拽调整大小
- 设置边缘检测阈值(一般8~10像素即可),实时判定鼠标是否落在窗口的边缘/角落区域,匹配对应调整方向后切换鼠标样式提示用户可拖拽
- 监听边缘区域的
pygame.MOUSEBUTTONDOWN事件,标记当前调整方向,记录初始窗口大小、初始鼠标坐标 - 监听
pygame.MOUSEMOTION事件,调整大小状态下根据鼠标位移差修改窗口宽高,若调整的是左边缘、上边缘还需要同步修改窗口位置,避免窗口偏移
可运行示例代码
import pygame # 初始化参数 pygame.init() SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 EDGE_THRESHOLD = 8 # 边缘检测阈值 TITLE_BAR_HEIGHT = 40 # 自定义标题栏高度 # 创建无框窗口,用pygame2的Window类方便控制位置大小 window = pygame.Window("自定义标题栏窗口", (SCREEN_WIDTH, SCREEN_HEIGHT), flags=pygame.NOFRAME) screen = window.get_surface() # 状态变量 dragging = False # 拖拽移动状态 resizing = False # 调整大小状态 drag_offset = (0, 0) resize_dir = None # 调整方向:top, bottom, left, right, top-left等组合 original_size = (0, 0) original_pos = (0, 0) resize_start_pos = (0, 0) clock = pygame.time.Clock() running = True while running: mouse_pos = pygame.mouse.get_pos() current_size = window.size current_pos = window.position # 事件处理 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: # 左键按下 # 判定是否点在标题栏,准备拖拽移动 if 0 <= mouse_pos[1] <= TITLE_BAR_HEIGHT and not resizing: dragging = True drag_offset = (mouse_pos[0], mouse_pos[1]) # 判定是否点在边缘,准备调整大小 else: # 判定调整方向 on_top = mouse_pos[1] < EDGE_THRESHOLD on_bottom = mouse_pos[1] > current_size[1] - EDGE_THRESHOLD on_left = mouse_pos[0] < EDGE_THRESHOLD on_right = mouse_pos[0] > current_size[0] - EDGE_THRESHOLD if on_top or on_bottom or on_left or on_right: resizing = True resize_start_pos = pygame.mouse.get_pos() original_size = current_size original_pos = current_pos # 组合方向 resize_dir = [] if on_top: resize_dir.append("top") if on_bottom: resize_dir.append("bottom") if on_left: resize_dir.append("left") if on_right: resize_dir.append("right") resize_dir = "-".join(resize_dir) if event.type == pygame.MOUSEBUTTONUP: if event.button == 1: dragging = False resizing = False resize_dir = None if event.type == pygame.MOUSEMOTION: # 处理拖拽移动 if dragging: global_mouse_pos = pygame.mouse.get_pos() new_x = current_pos[0] + (global_mouse_pos[0] - drag_offset[0]) new_y = current_pos[1] + (global_mouse_pos[1] - drag_offset[1]) window.position = (new_x, new_y) # 处理调整大小 if resizing and resize_dir: dx = event.pos[0] - resize_start_pos[0] dy = event.pos[1] - resize_start_pos[1] new_w = original_size[0] new_h = original_size[1] new_x = original_pos[0] new_y = original_pos[1] if "right" in resize_dir: new_w = max(200, original_size[0] + dx) # 限制最小宽度200 if "left" in resize_dir: new_w = max(200, original_size[0] - dx) new_x = original_pos[0] + (original_size[0] - new_w) if "bottom" in resize_dir: new_h = max(200, original_size[1] + dy) # 限制最小高度200 if "top" in resize_dir: new_h = max(200, original_size[1] - dy) new_y = original_pos[1] + (original_size[1] - new_h) window.size = (new_w, new_h) window.position = (new_x, new_y) # 绘制界面 screen.fill((30, 30, 30)) # 绘制自定义标题栏 pygame.draw.rect(screen, (60, 60, 180), (0, 0, current_size[0], TITLE_BAR_HEIGHT)) # 绘制内容区提示 font = pygame.font.SysFont("arial", 20) text = font.render("拖拽标题栏移动窗口,拖拽边缘调整大小", True, (255,255,255)) screen.blit(text, (20, TITLE_BAR_HEIGHT + 20)) window.flip() clock.tick(60) pygame.quit()
注:以上示例基于Pygame 2.0+的
pygame.Window类实现,如果你使用的是旧版本Pygame,可以通过修改os.environ['SDL_VIDEO_WINDOW_POS']后重新调用pygame.display.set_mode()更新窗口位置和大小,逻辑和上述示例一致。
内容的提问来源于stack exchange,提问作者Luphaestus
相关产品推荐
相关产品推荐

