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()
添加回答
舉報