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

如何在Tkinter窗口指定位置放置Matplotlib绘制的图表?

解决Matplotlib图表在Tkinter中指定位置放置的问题

嘿,作为Python新手遇到这个布局问题太正常啦!你现在用pack()来放置Matplotlib的画布,自然没法自定义位置——要实现精准定位,只需要把pack()换成place()就可以,和你放按钮的思路完全一致。

问题根源

Matplotlib的FigureCanvasTkAgg会生成一个Tkinter兼容的控件,这个控件和普通按钮一样支持Tkinter的三种布局管理器:pack()、grid()、place()。你之前用pack()是让它自动填充顶部区域,但用place()就能精准控制它的位置、大小。

修改后的代码

我帮你调整了plot()方法,还加了个小细节避免多次点击PLOT按钮后图表重叠:

import tkinter as tk
from tkinter import ttk, messagebox
import serial
import serial.tools.list_ports
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt

root = tk.Tk()
root.title("ANALYSER")
root.geometry("1000x700")
root.configure(background='white')

def get_ports():
    ports = serial.tools.list_ports.comports()
    return ports

def findArduino(portsFound):
    commPort = 'None'
    numConnection = len(portsFound)
    for i in range(numConnection):
        port = portsFound[i]
        strPort = str(port)
        if 'Arduino' in strPort:
            splitPort = strPort.split(' ')
            commPort = splitPort[0]
    return commPort

class AppWindow:
    def __init__(self, window):
        self.window = window
        # 按钮用pack没问题,和place布局可以共存
        self.connect = ttk.Button(window, text="CONNECT", command=self.Connect)
        self.connect.pack(pady=10)
        self.getValue = ttk.Button(window, text="PLOT", command=self.plot)
        self.getValue.pack(pady=5)
        
        # 初始化画布属性,用于后续销毁旧图表
        self.canvas_widget = None

    def Connect(self):
        self.FoundPorts = get_ports()
        self.connectPort = findArduino(self.FoundPorts)
        if self.connectPort != 'None':
            ser = serial.Serial(self.connectPort, baudrate=9600)
            print('Connected to ' + self.connectPort)
            messagebox.showinfo('STATUS', 'CONNECTED')
        else:
            print('Connection Issue!')
            messagebox.showinfo('STATUS', 'NOT CONNECTED!')

    def plot(self):
        # 如果之前有画布,先销毁它避免重叠
        if self.canvas_widget:
            self.canvas_widget.destroy()
            
        fig = plt.figure(figsize=(8, 4), dpi=100)  # 按需调整图表大小
        a = fig.add_subplot(111)
        a.plot([1,1,1,1,2,3,3,4],[8,9,5,6,2,2,2,2])
        
        canvas = FigureCanvasTkAgg(fig, master=self.window)
        fig.canvas.draw()
        
        # 获取Tkinter控件,用place指定位置
        self.canvas_widget = canvas.get_tk_widget()
        # 这里设置x=50, y=100,你可以根据需求修改坐标和尺寸
        self.canvas_widget.place(x=50, y=100, width=800, height=400)
        # 也可以用相对位置,比如relx=0.05, rely=0.2, relwidth=0.9, relheight=0.7(按窗口比例适配)

start = AppWindow(root)
root.mainloop()

关键修改点

  1. 新增self.canvas_widget属性,每次绘图前销毁旧画布,避免多次点击PLOT后图表重叠
  2. 将canvas.get_tk_widget().pack(...)替换为place(),并指定了x、y坐标和width、height参数
  3. 调整了figsize让图表更适配窗口,你可以根据自己的需求修改这些数值

额外提示

place()的参数非常灵活:

  • x/y:绝对像素坐标
  • relx/rely:相对窗口的比例(取值0到1之间)
  • width/height:绝对宽度高度
  • relwidth/relheight:相对窗口的宽度高度比例

如果想让按钮也用place()定位,直接把按钮的pack()换成place()就行,比如self.connect.place(x=20, y=20)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 06:35:26