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

如何用Python实现3D窗口鼠标锁定(支持moderngl_window或替代库)

问题描述

我正在使用moderngl_window开发一款带有完整3D相机控制功能的交互式片段着色器,希望实现类似多数3D游戏的效果——将光标限制在活动窗口内,使其无法移出窗口或触碰边框。我需要基于Python的解决方案,若切换至其他具备隐藏光标功能的同类库是更简单的方案,我也可以接受。我不想使用pyautogui这类通过强制方式约束鼠标的工具,这类方案易出错且繁琐。我使用的是Arch Linux,也接受针对该系统的特定方案。

我已查阅网络资料及moderngl_window文档,但未找到有用信息。我了解到pygame具备内置解决方案,但希望先咨询是否存在更优、更简便的方案。

以下是我使用的moderngl_window样板代码:

import moderngl_window as mgl

class App(mgl.WindowConfig):
    window_size = 1336, 768
    resource_dir = "src"
    cursor = False
    fullscreen = True

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.quad = mgl.geometry.quad_fs()
        self.prog = self.load_program(
            vertex_shader = "vertex.glsl", 
            fragment_shader = "frag.glsl")
        self.prog["resolution"] = self.window_size

    def render(self, time, frame_time):
        self.ctx.clear()
        try:
            self.prog["time"] = time
        except:
            pass
        self.quad.render(self.prog)

if __name__ == "__main__":
    mgl.run_window_config(App)
解决方案

方案一:直接调用moderngl_window底层GLFW API

moderngl_window默认基于GLFW后端,可直接调用GLFW原生API实现光标锁定,属于原生系统级约束,稳定性高:

修改__init__方法,添加光标锁定逻辑:

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.quad = mgl.geometry.quad_fs()
    self.prog = self.load_program(
        vertex_shader = "vertex.glsl", 
        fragment_shader = "frag.glsl")
    self.prog["resolution"] = self.window_size
    
    # 锁定光标到窗口并隐藏
    self.wnd.cursor = 'hidden'
    self.wnd.center_cursor()
    # 调用GLFW原生API禁用光标自由移动
    import glfw
    glfw.set_input_mode(self.wnd._window, glfw.CURSOR, glfw.CURSOR_DISABLED)

方案二:切换至Pygame后端

moderngl_window支持Pygame作为窗口后端,Pygame内置成熟的光标锁定机制,实现简单:

  1. 先安装依赖:
pip install pygame
  1. 修改代码指定Pygame后端并启用光标锁定:
import moderngl_window as mgl
from moderngl_window.context.pygame.window import Window as PygameWindow

class App(mgl.WindowConfig):
    window_size = 1336, 768
    resource_dir = "src"
    cursor = False
    fullscreen = True
    window_cls = PygameWindow  # 指定使用Pygame窗口

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.quad = mgl.geometry.quad_fs()
        self.prog = self.load_program(
            vertex_shader = "vertex.glsl", 
            fragment_shader = "frag.glsl")
        self.prog["resolution"] = self.window_size
        
        # Pygame原生光标锁定
        import pygame
        pygame.mouse.set_visible(False)
        pygame.event.set_grab(True)  # 将光标限制在窗口内

    def render(self, time, frame_time):
        self.ctx.clear()
        try:
            self.prog["time"] = time
        except:
            pass
        self.quad.render(self.prog)

if __name__ == "__main__":
    mgl.run_window_config(App)

方案三:Arch Linux X11特定方法(可选)

若坚持使用现有后端,可通过X11工具辅助,但通用性较差,仅作备选:

  1. 安装工具:
sudo pacman -S xorg-xinput
  1. 程序启动时通过subprocess调用Xinput命令限制鼠标(需替换为你的实际鼠标设备名):
import subprocess
subprocess.run(["xinput", "set-prop", "你的鼠标设备名", "Device Accel Profile", "-1"])

内容的提问来源于stack exchange,提问作者Tomo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 21:37:43