Skip to main content
 首页 » 编程设计

python之如何将 matplotlib 直方图嵌入到 tkinter GUI 中

2024年08月28日36softidea

我有这个程序,它根据特定参数(上限、样本量)内随机生成的数字的中位数列表创建直方图。我怎样才能使创建的直方图出现在 tkinter GUI 中,就在刻度上方?我到处都看过,但仍然无法弄清楚。提前致谢!我正在使用 python 3。

奖金问题(不需要回答,但如果你愿意,它会帮助很多):我将如何做到这一点,以便比例控制 number_lists 的值(这基本上是生成中位数的次数)然后通过添加新计算的中位数来更新直方图的外观?

import random 
import matplotlib, sys 
matplotlib.use('TkAgg') 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
from matplotlib.figure import Figure 
import matplotlib.pyplot as plt 
import matplotlib.mlab as mlab 
import numpy as np 
from tkinter import * 
from tkinter import ttk 
 
 
#root 
root = Tk() 
root.title("Sample Size and the Normal Distribution") 
 
#mainframe 
mainframe = ttk.Frame(root, padding = "3 3 12 12") 
mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) 
mainframe.columnconfigure(0, weight=1) 
mainframe.rowconfigure(0, weight=1) 
 
def create_list(sampleSize, upperLimit): 
    numbList = [] 
    sampleSize = int(sample.get()) 
    upperLimit = int(upper.get()) 
    while sampleSize > 0: 
        sampleSize -= 1 
        randomNum = random.randrange(0,upperLimit+1) 
        numbList.append(randomNum) 
    numbList.sort(key=int) 
    return numbList 
 
def medians_variance(median_list): 
    sum_of_medians = sum(median_list) 
    variance = sum_of_medians / len(median_list) 
    return variance 
 
 
def median(numbList): 
 
        srtd = sorted(numbList) 
        mid = len(numbList)//2 
        if len(numbList) % 2 == 0: 
            return (srtd[mid-1] + srtd[mid]) / 2.0 
        else: 
            return srtd[mid] 
 
 
def main(): 
 
    number_lists = 10 
    lists = [] 
    median_list = [] 
 
    binsize = 10 
 
    for i in range(number_lists): 
        lists.append(create_list(sampleSize, upperLimit)) 
 
    for current_list in lists: 
        current_median = median(current_list) 
        median_list.append(current_median) 
        median_list.sort(key=float) 
 
 
    plt.hist(median_list, binsize) 
 
    plt.xlabel('Median Value', fontsize = 15) 
    plt.ylabel('Frequency', fontsize = 15) 
 
    plt.show() 
 
 
    med = median(median_list) 
    std = np.std(median_list) 
    var = (std**2) 
 
 
#sampleSize Entry 
sample = StringVar() 
sampleSize = ttk.Entry(mainframe, width = 7, textvariable = sample) 
sampleSize.grid(column = 2, row = 1, sticky =(W, E)) 
 
#upperLimit Entry 
upper = StringVar() 
upperLimit = ttk.Entry(mainframe, width = 7, textvariable = upper) 
upperLimit.grid(column = 2, row = 3, sticky = (W, E)) 
 
#binsize Entry 
Bin = StringVar() 
binsize = ttk.Entry(mainframe, width = 7, textvariable = Bin) 
binsize.grid(column = 2, row = 5, sticky = (W, E)) 
 
#sampleSize and upperLimit Labels 
ttk.Label(mainframe, text="Sample Size ").grid(column = 1, row = 1, sticky = W) 
ttk.Label(mainframe, text="Upper Limit ").grid(column = 1, row = 3, sticky = W) 
ttk.Label(mainframe, text="Bin Size").grid(column = 1, row = 5, sticky = W) 
 
#histogram embed 
f = Figure(figsize = (5,4), dpi=100) 
 
#button for new histogram 
button = ttk.Button(mainframe, text="New Histogram", command=main).grid(column=1, row=7, sticky=W) 
 
#scale 
scale = Scale(mainframe, from_=0, to=10, orient=HORIZONTAL,length=400).grid(column = 5, row = 12, sticky= S) 
 
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5) 
 
sampleSize.focus() 
upperLimit.focus() 
root.bind('<Return>', main) 
 
root.mainloop() 

请您参考如下方法:

创建一个 FigureCanvasTkAgg 对象并将其放入框架内:

f = Figure(figsize=(5,4), dpi=100) 
canvas = FigureCanvasTkAgg(f, master=mainframe) 
canvas.get_tk_widget().grid(row=1, column=3, rowspan=6) 

在 main 中,不使用 plt,而是使用 Figure 对象 f:

p = f.gca() 
p.hist(median_list, binsize) 
p.set_xlabel('Median Value', fontsize = 15) 
p.set_ylabel('Frequency', fontsize = 15) 
canvas.show() 

顺便说一句,幻灯片网格略有修改以获得上述结果:

scale = Scale(mainframe, from_=0, to=10, orient=HORIZONTAL,length=400) 
scale.grid(column=3, row=12, sticky=S)