You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 14:45:02