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

如何在Tkinter中实现折线图下方放置同尺寸表格图片

Tkinter GUI 表格图片显示问题解决

需求描述

当前基于Tkinter的GUI布局包含:

  • 左侧带滚动条的多个径向图表框架
  • 上方中间显示折线图的框架
  • 下方中间用于展示表格图片的框架
  • 右侧显示另一种径向图表的框架

需要实现:

  1. 表格图片放置在折线图框架的正下方,且两者尺寸保持一致
  2. 勾选复选框1和2时,同步显示line_plot_1_2.png与table_1_2.png
  3. 勾选3和4时,切换显示line_plot_3_4.png与table_3_4.png

修改方案

以下是调整后的完整代码,解决了表格图片的显示问题:

import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk

# 创建主窗口
root = tk.Tk()
root.title("Radial Charts")
root.geometry("1200x800")  # 调整窗口高度以容纳上下两个图片

# 创建主框架
main_frame = ttk.Frame(root)
main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

# 左侧带滚动条的径向图表框架
left_frame = ttk.Frame(main_frame)
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

canvas = tk.Canvas(left_frame)
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

scrollbar = ttk.Scrollbar(left_frame, orient=tk.VERTICAL, command=canvas.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

canvas.configure(yscrollcommand=scrollbar.set)
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox('all')))

frame = tk.Frame(canvas)
canvas.create_window((0, 0), window=frame, anchor=tk.NW)

# 中间区域容器:包含折线图和表格图片框架(垂直排列)
middle_container = ttk.Frame(main_frame)
middle_container.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# 上方折线图框架
upper_middle_frame = ttk.Frame(middle_container)
upper_middle_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

# 下方表格图片框架
lower_middle_frame = ttk.Frame(middle_container)
lower_middle_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

# 折线图画布
line_plot_canvas = tk.Canvas(upper_middle_frame, background='white')
line_plot_canvas.pack(fill=tk.BOTH, expand=True)

# 表格图片画布
table_plot_canvas = tk.Canvas(lower_middle_frame, background='white')
table_plot_canvas.pack(fill=tk.BOTH, expand=True)

# 全局变量
checkbuttons = []
selected_checkbuttons = []
line_plot_image_tk = None
table_plot_image_tk = None
desired_width = 600
desired_height = 300  # 统一两者高度,确保上下对齐

def generate_plot_path(prefix, start_visit, end_visit):
    return f"path/{prefix}_{start_visit}_{end_visit}.png"

def display_line_plot(image_path):
    global line_plot_image_tk
    line_plot_canvas.delete("all")
    try:
        image = Image.open(image_path)
        resized_image = image.resize((desired_width, desired_height), Image.Resampling.LANCZOS)
        line_plot_image_tk = ImageTk.PhotoImage(resized_image)
        line_plot_canvas.create_image(0, 0, anchor=tk.NW, image=line_plot_image_tk)
        # 保持引用防止垃圾回收
        line_plot_canvas.image = line_plot_image_tk
    except Exception as e:
        print(f"加载折线图失败: {e}")

def display_table_plot(image_path):
    global table_plot_image_tk
    table_plot_canvas.delete("all")
    try:
        image = Image.open(image_path)
        resized_image = image.resize((desired_width, desired_height), Image.Resampling.LANCZOS)
        table_plot_image_tk = ImageTk.PhotoImage(resized_image)
        table_plot_canvas.create_image(0, 0, anchor=tk.NW, image=table_plot_image_tk)
        # 保持引用防止垃圾回收
        table_plot_canvas.image = table_plot_image_tk
    except Exception as e:
        print(f"加载表格图片失败: {e}")

def checkbox_selected():
    selected_checkbuttons.clear()
    for cb, var in checkbuttons:
        if var.get() == 1:
            selected_checkbuttons.append(cb)
    # 只处理选中恰好两个复选框的情况
    if len(selected_checkbuttons) == 2:
        start_visit = int(selected_checkbuttons[0]["text"].split("_")[1])
        end_visit = int(selected_checkbuttons[1]["text"].split("_")[1])
        
        line_path = generate_plot_path("line_plot", start_visit, end_visit)
        table_path = generate_plot_path("table", start_visit, end_visit)
        
        display_line_plot(line_path)
        display_table_plot(table_path)
    else:
        # 选中数量不为2时清空显示
        line_plot_canvas.delete("all")
        table_plot_canvas.delete("all")

# 加载左侧径向图表
for i in range(1, 10):
    image_path = f"path/visit_{i}.png"
    try:
        image = Image.open(image_path)
        image = image.resize((400, 400), Image.Resampling.LANCZOS)
        image_tk = ImageTk.PhotoImage(image)
        
        label = tk.Label(frame, image=image_tk)
        label.pack(pady=5)
        label.image = image_tk
        
        check_var = tk.IntVar()
        checkbutton = tk.Checkbutton(label, text=f"visit_{i}", variable=check_var, command=checkbox_selected)
        checkbutton.place(relx=1, rely=1, anchor=tk.SE)
        
        checkbuttons.append((checkbutton, check_var))
    except Exception as e:
        print(f"加载visit_{i}图片失败: {e}")

# 启动事件循环
root.mainloop()

关键修改说明

  • 布局调整:新增middle_container框架,将upper_middle_frame和lower_middle_frame放入其中,通过side=tk.TOP实现垂直排列,确保表格在折线图正下方
  • 尺寸统一:定义desired_width和desired_height变量,统一折线图和表格图片的显示尺寸
  • 同步显示逻辑:在checkbox_selected函数中,同时生成折线图和表格图片的路径,调用对应的显示函数同步加载
  • 引用保留:在画布上存储图片引用(如line_plot_canvas.image),避免图片被垃圾回收导致不显示
  • 异常处理:添加图片加载异常捕获,方便调试错误
  • 窗口高度调整:将主窗口高度从600改为800,确保能完整显示上下两个图片

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 00:34:53