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

Windows下TkAgg后端全屏显示matplotlib图表内容偏移问题

Windows 10下TkAgg后端Matplotlib全屏显示图片网格内容超出屏幕的解决方法

问题场景

我编写了Python函数,用Matplotlib的pyplot全屏显示3×3图片网格。在Windows 10系统的TkAgg交互式后端环境下,窗口打开后图表部分内容超出屏幕,无法完整显示预期的3×3网格。尝试通过plt.get_current_fig_manager().window.state('zoomed')设置全屏时出现该问题,调整figsize为1×1英寸无效果,手动退出全屏再重新进入后图表可正常显示。

原代码如下:

from PIL import Image
import matplotlib.pyplot as plt

def imageGrid(data_obj, grid=(3,3), start_idx=0):
    # 设置画布尺寸为1×1英寸
    figure = plt.figure(figsize=(1,1))
    cols, rows = grid
    idx = start_idx
    for i in range(1, cols * rows + 1):
        img = data_obj[idx]
        figure.add_subplot(rows, cols, i)
        plt.axis("off")
        plt.imshow(img, cmap="gray")
        idx += 1
    
    plt.subplots_adjust(wspace=0, hspace=0, left=0, right=1, bottom=0, top=1)

    # 设置窗口全屏(此代码导致内容溢出)
    plt.get_current_fig_manager().window.state('zoomed')

    plt.show()

list_of_images = [Image.open("Screenshot 2023-08-30 170601.png") for i in range(9)]
imageGrid(list_of_images)

问题原因

在TkAgg后端中,先定义小尺寸画布再调用state('zoomed')会导致图表布局与窗口尺寸不同步:窗口被强制放大到全屏,但图表的子图位置、边距等布局参数是基于初始小尺寸计算的,没有随窗口放大自动重新适配,最终导致内容溢出屏幕。

解决方法

方法1:延迟触发全屏,等待布局完成

利用Tkinter的after()方法,给Matplotlib留足布局计算时间,再设置窗口全屏:

from PIL import Image
import matplotlib.pyplot as plt
import tkinter as tk

def imageGrid(data_obj, grid=(3,3), start_idx=0):
    figure = plt.figure(figsize=(1,1))
    cols, rows = grid
    idx = start_idx
    for i in range(1, cols * rows + 1):
        img = data_obj[idx]
        figure.add_subplot(rows, cols, i)
        plt.axis("off")
        plt.imshow(img, cmap="gray")
        idx += 1
    
    plt.subplots_adjust(wspace=0, hspace=0, left=0, right=1, bottom=0, top=1)

    # 延迟100毫秒设置全屏,确保布局完成
    def set_fullscreen():
        plt.get_current_fig_manager().window.state('zoomed')
    
    root = tk.Tk()
    root.withdraw()  # 隐藏默认Tk窗口
    root.after(100, set_fullscreen)

    plt.show()

list_of_images = [Image.open("Screenshot 2023-08-30 170601.png") for i in range(9)]
imageGrid(list_of_images)

方法2:基于屏幕尺寸设置初始画布

先获取屏幕分辨率,直接将画布尺寸设置为与屏幕匹配的大小,让初始布局就适配全屏窗口:

from PIL import Image
import matplotlib.pyplot as plt
import tkinter as tk

def imageGrid(data_obj, grid=(3,3), start_idx=0):
    # 获取屏幕尺寸
    root = tk.Tk()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    root.destroy()

    # 根据屏幕尺寸和DPI设置画布大小
    dpi = 100
    figure = plt.figure(figsize=(screen_width/dpi, screen_height/dpi), dpi=dpi)
    
    cols, rows = grid
    idx = start_idx
    for i in range(1, cols * rows + 1):
        img = data_obj[idx]
        figure.add_subplot(rows, cols, i)
        plt.axis("off")
        plt.imshow(img, cmap="gray")
        idx += 1
    
    plt.subplots_adjust(wspace=0, hspace=0, left=0, right=1, bottom=0, top=1)

    plt.get_current_fig_manager().window.state('zoomed')
    plt.show()

list_of_images = [Image.open("Screenshot 2023-08-30 170601.png") for i in range(9)]
imageGrid(list_of_images)

方法3:设置全屏后强制刷新布局

在设置全屏后,手动触发图表布局刷新,让Matplotlib重新计算子图位置:

from PIL import Image
import matplotlib.pyplot as plt

def imageGrid(data_obj, grid=(3,3), start_idx=0):
    figure = plt.figure(figsize=(1,1))
    cols, rows = grid
    idx = start_idx
    for i in range(1, cols * rows + 1):
        img = data_obj[idx]
        figure.add_subplot(rows, cols, i)
        plt.axis("off")
        plt.imshow(img, cmap="gray")
        idx += 1
    
    plt.subplots_adjust(wspace=0, hspace=0, left=0, right=1, bottom=0, top=1)

    plt.get_current_fig_manager().window.state('zoomed')
    # 强制刷新布局
    figure.canvas.draw()
    plt.show()

list_of_images = [Image.open("Screenshot 2023-08-30 170601.png") for i in range(9)]
imageGrid(list_of_images)

效果验证

三种方法均可实现3×3图片网格在全屏窗口中完整显示,无需手动调整窗口。其中方法1兼容性最好,方法2更贴合屏幕原生分辨率,可根据实际需求选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:33:14