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

为何Tkinter窗口与Matplotlib图表在不同显示器及PyInstaller打包前后显示异常?

问题根源与解决方案

你的问题本质是Windows高DPI显示器下的Tkinter与Matplotlib缩放适配问题,具体原因和解决步骤如下:

核心原因

  1. Tkinter默认不支持高DPI缩放:Windows 10的4K屏通常启用200%(或更高)缩放,Tkinter默认忽略系统缩放设置,导致窗口和控件按96DPI的原始尺寸渲染,在高DPI屏上显得极小。
  2. Matplotlib硬编码DPI不匹配:你固定设置plt.rcParams["figure.dpi"] = 96,但4K屏的实际DPI是192(200%缩放),图表渲染后会被系统缩放挤压,显示异常。
  3. PyInstaller打包未处理高DPI清单:打包后的程序缺少高DPI兼容的清单文件,Windows无法识别它需要适配系统缩放。

解决步骤

1. 启用Tkinter高DPI缩放支持

在创建Tk()根窗口前,添加Windows API调用,让程序识别系统缩放:

import ctypes
try:
    # 启用高DPI感知
    ctypes.windll.shcore.SetProcessDpiAwareness(1)
except:
    pass  # 不支持的系统版本忽略

2. 动态适配Matplotlib DPI

不要硬编码DPI,改为让Matplotlib自动使用系统DPI,或者动态获取:

# 替换硬编码的DPI设置,改为获取系统实际DPI
dpi = root.winfo_fpixels('1i')  # 获取系统每英寸像素数
plt.rcParams["figure.dpi"] = dpi

3. 改用更稳定的布局方式

避免使用place()布局(依赖固定比例,缩放后容易错位),改用pack()或grid()布局,更适配窗口尺寸变化。

4. PyInstaller打包添加高DPI支持

打包时需嵌入高DPI清单,可通过命令行参数或spec文件实现。

修改后的完整代码

import ctypes
try:
    # 启用Windows高DPI感知
    ctypes.windll.shcore.SetProcessDpiAwareness(1)
except:
    pass

import tkinter as tk
import numpy as np

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)

from matplotlib import pyplot as plt, cm
from tkinter import *

# window settings
root = tk.Tk()
root.geometry('678x600')

# 动态适配Matplotlib DPI
dpi = root.winfo_fpixels('1i')
plt.rcParams["figure.dpi"] = dpi
plt.rcParams["figure.figsize"] = [6.75, 4.0]

fig = plt.figure()

# 创建控件
pulse_txt = tk.Text(root, height=1, width=6, font=("Arial", 14))
pulse_lbl = tk.Label(root, text="label label hi", bg="#EEEDEB")
end_count_btn = tk.Button(root, text="button", width=10)

# 绑定Matplotlib画布到窗口
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True, padx=10, pady=10)

# 顶部控件用Frame+Pack布局
top_frame = tk.Frame(root, bg="#EEEDEB")
top_frame.pack(side=tk.TOP, fill=tk.X, padx=10, pady=10)

pulse_lbl.pack(in_=top_frame, side=tk.LEFT, padx=5)
pulse_txt.pack(in_=top_frame, side=tk.LEFT, padx=5)
end_count_btn.pack(in_=top_frame, side=tk.LEFT, padx=5)

# 绘制柱状图
ax = fig.add_subplot(111)
bars = plt.bar(np.linspace(1,1000,1000), np.zeros(1000), facecolor='#990000', width=1)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("plot")
ax.set_xlim([0,500])

# 添加Matplotlib工具栏
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()

root.mainloop()

打包补充说明

使用PyInstaller打包时,可通过spec文件嵌入高DPI清单:

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='your_app',
          debug=False,
          console=False,
          # 嵌入高DPI兼容清单
          manifest='''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
    </windowsSettings>
  </application>
</assembly>''')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:25:32