如何在PySimpleGUI中实现窗口resize时Graph元素及绘图同步缩放
解决PySimpleGUI Graph元素同步窗口缩放的问题
核心思路是用相对比例而非固定像素值定义绘图元素,同时通过尺寸判断避免resize循环事件。以下是可直接运行的实现方案:
关键步骤
- 初始化时记录Graph的原始尺寸,并用相对比例保存绘图元素的参数(比如圆心位置、半径占Graph宽高的比例)
- 处理窗口resize事件时,仅当Graph的实际尺寸发生变化时才更新
- 重新计算所有绘图元素的绝对坐标和大小,刷新Graph内容
完整代码示例
import PySimpleGUI as sg # 初始化参数 DEFAULT_WIDTH = 400 DEFAULT_HEIGHT = 300 # 用相对比例定义绘图元素(圆心在中心,半径占短边的20%) circle_params = {"center_ratio": (0.5, 0.5), "radius_ratio": 0.2} # 布局:让Graph占满窗口 layout = [ [sg.Graph( canvas_size=(DEFAULT_WIDTH, DEFAULT_HEIGHT), graph_bottom_left=(0, 0), graph_top_right=(DEFAULT_WIDTH, DEFAULT_HEIGHT), key="-GRAPH-", expand_x=True, expand_y=True )] ] window = sg.Window("同步缩放示例", layout, resizable=True, finalize=True) graph = window["-GRAPH-"] # 绘制/重绘圆圈的函数 def draw_circle(graph, width, height): center_x = width * circle_params["center_ratio"][0] center_y = height * circle_params["center_ratio"][1] # 取宽高中的较小值计算半径,保证圆圈不变形 radius = min(width, height) * circle_params["radius_ratio"] # 清除旧元素(如果存在) if graph.get_figures(): graph.delete_figure(graph.get_figures()[0]) # 绘制新圆圈 graph.draw_circle((center_x, center_y), radius, fill_color="red") # 首次绘制 draw_circle(graph, DEFAULT_WIDTH, DEFAULT_HEIGHT) last_size = (DEFAULT_WIDTH, DEFAULT_HEIGHT) while True: event, values = window.read() if event == sg.WINDOW_CLOSED: break # 处理窗口resize事件 if event == sg.EVENT_WINDOW_RESIZED: current_size = graph.get_size() # 仅当尺寸真的变化时执行更新,避免循环触发resize if current_size != last_size: last_size = current_size # 同步Graph的坐标范围与当前画布尺寸 graph.change_coordinates((0, 0), current_size) # 重绘圆圈 draw_circle(graph, *current_size) window.close()
代码说明
- 相对比例定义:圆圈的圆心和半径都用占Graph宽高的比例表示,无论窗口如何调整,元素始终保持相对位置和比例
- 避免resize循环:通过
last_size记录上一次的Graph尺寸,仅当当前尺寸与上次不同时才执行更新,防止change_coordinates或重绘触发重复resize事件 - 坐标范围同步:每次resize时调用
change_coordinates,让Graph的坐标范围与画布尺寸匹配,保证绘图逻辑的一致性 - 清除旧元素:重绘前删除旧图形,避免画布残留多个元素
这样实现后,拖动窗口边缘调整大小时,Graph会自动占满窗口,圆圈同步缩放且保持比例,不会出现循环触发resize的问题。
内容的提问来源于stack exchange,提问作者agtoever
相关产品推荐
相关产品推荐

