2 回答
TA贡献1797条经验 获得超6个赞
如果您遇到此类问题,最好使用 googleSDL
来代替pygame
,因为 pygame 是一个相当低级的 SDL 包装器。
所以这不是 pygame 本身的问题,而是 sdl 和窗口管理器如何交互的问题。
尽管如此,如果您确实需要在调整大小时更新窗口,如果您使用的是 Windows,则可以侦听WM_SIZE
Windows 的实际事件,重绘屏幕,并通过调用 来更新“Windows”窗口RedrawWindow
。
这是一个简单的例子:
import pygame
import win32gui
import win32con
def wndProc(oldWndProc, draw_callback, hWnd, message, wParam, lParam):
if message == win32con.WM_SIZE:
draw_callback()
win32gui.RedrawWindow(hWnd, None, None, win32con.RDW_INVALIDATE | win32con.RDW_ERASE)
return win32gui.CallWindowProc(oldWndProc, hWnd, message, wParam, lParam)
def main():
pygame.init()
screen = pygame.display.set_mode((320, 240), pygame.RESIZABLE | pygame.DOUBLEBUF)
def draw_game():
screen.fill(pygame.Color('black'))
pygame.draw.rect(screen, pygame.Color('red'), pygame.Rect(0,0,screen.get_width(),screen.get_height()).inflate(-10, -10))
pygame.display.flip()
oldWndProc = win32gui.SetWindowLong(win32gui.GetForegroundWindow(), win32con.GWL_WNDPROC, lambda *args: wndProc(oldWndProc, draw_game, *args))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.VIDEORESIZE:
pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE| pygame.DOUBLEBUF)
draw_game()
if __name__ == '__main__':
main()
TA贡献2011条经验 获得超2个赞
ctypes如果未指定,则假定参数类型和返回类型为 “c_int指针” 。是一个32位值。LONG_PTR 和 LRESULT 是 64 位操作系统上的 64 位值。好的做法是定义所有使用的函数和。这样做解决了问题。c_intc_int.argtypes.restype
import ctypes as ct
from ctypes import wintypes as w
import pygame
# LPARAM is typedef'ed as LONG_PTR in winuser.h, so it can be used
# for LRESULT and LONG_PTR which are missing from wintypes.
LRESULT = LONG_PTR = w.LPARAM
WNDPROC = ct.WINFUNCTYPE(LRESULT, w.HWND, w.UINT, w.WPARAM, w.LPARAM)
WM_SIZE = 0x0005
RDW_INVALIDATE = 0x0001
RDW_ERASE = 0x0004
GWL_WNDPROC = -4
# ctypes.windll.user32 is a cached, shared version of user32.dll.
# Get our own copy and meticulously define argtypes/restype according
# to MSDN documentation of the C prototypes.
user32 = ct.WinDLL('user32')
user32.GetWindowLongPtrA.argtypes = w.HWND, ct.c_int
user32.GetWindowLongPtrA.restype = LONG_PTR
user32.GetForegroundWindow.argtypes = ()
user32.GetForegroundWindow.restype = w.HWND
user32.RedrawWindow.argtypes = w.HWND, w.LPRECT, w.HRGN, w.UINT
user32.RedrawWindow.restype = w.BOOL
user32.CallWindowProcA.argtypes = WNDPROC, w.HWND, w.UINT, w.WPARAM, w.LPARAM
user32.CallWindowProcA.restype = LRESULT
user32.SetWindowLongPtrA.argtypes = w.HWND, ct.c_int, LONG_PTR
user32.SetWindowLongPtrA.restype = LONG_PTR
def main():
pygame.init()
screen = pygame.display.set_mode((320, 240), pygame.RESIZABLE | pygame.DOUBLEBUF)
def draw_game():
screen.fill(pygame.Color('black'))
pygame.draw.rect(screen, pygame.Color('red'), pygame.Rect(0,0,screen.get_width(),screen.get_height()).inflate(-10, -10))
pygame.display.flip()
old_window_proc = user32.GetWindowLongPtrA(user32.GetForegroundWindow(), GWL_WNDPROC)
def new_window_proc(hwnd, msg, wparam, lparam):
if msg == WM_SIZE:
draw_game()
user32.RedrawWindow(hwnd, None, None, RDW_INVALIDATE | RDW_ERASE)
# LONG_PTR is the same bit width as WNDPROC, but
# need cast to use it here.
return user32.CallWindowProcA(ct.cast(old_window_proc, WNDPROC), hwnd, msg, wparam, lparam)
new_window_proc_cb = WNDPROC(new_window_proc)
# Can't cast a WNDPROC (pointer) to a LONG_PTR directly, but can cast to void*.
# The .value of a c_void_p instance is its integer address.
user32.SetWindowLongPtrA(user32.GetForegroundWindow(), GWL_WNDPROC, ct.cast(new_window_proc_cb, ct.c_void_p).value)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.VIDEORESIZE:
pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE| pygame.DOUBLEBUF)
draw_game()
if __name__ == '__main__':
main()
添加回答
举报