带有Tkinter笔记本的Matplotlib



我正试图使用Tkinter和Matplotlib构建一个程序,用户可以通过复选按钮在多个函数中进行选择,并使用绘图按钮绘制所选函数。生成的绘图必须存储在Tkinter笔记本的选项卡中,我的意思是,每次单击绘图按钮,生成的图形都必须出现在新的选项卡中。为此,我创建了两个类,第一个创建GUI,第二个创建图形。我面临两个问题,当我将Matplotlib图表导入Tkinter笔记本的选项卡时,工具栏没有导入,我得到的只是函数的图像,但我真的需要带有光标位置工具的工具栏。此外,每次我点击绘图按钮时,下一个图形都与旧图形重叠,假设旧图形已被破坏。最后,如果我不将matplotlib图表导入Tkinter笔记本,程序第一次绘制正确,但当我第二次单击绘图按钮时,我得到的只是一块空白画布。我尝试了很多事情,但我不知道这里发生了什么。我知道有很多问题,但我非常感谢你的帮助。提前谢谢。

GUI:

from stack2 import *
import numpy as np
from tkinter import ttk
from tkinter.ttk import *
from tkinter import *

class Gui:
# Attributes of the class
# Array to store the objects
objects = np.array([])
# Dictionary to store the data
data = {
"x": np.array(
[
0,
2.216666667,
4.216666667,
6.216666667,
23.48333333,
70.83333333,
143.8333333,
]
),
"y": np.array([0, 0.3812, 0.59375, 0.6176, 0.6165, 0.39845, 0.2692]),
}
# Constructor function
def __init__(self, title, width, height, foreground, background):
# Attributes of the instance
self.root = Tk()  # Root
self.title = title  # Title
self.height = height  # Height
self.width = width  # Width
self.foreground = foreground  # Foreground
self.background = background  # Background color
# Method of the class
# Function for setting the style of each button
def buttonStyle(self):
# Creating object style
buttonStyle = ttk.Style()
# Setting style
buttonStyle.configure("TButton", foreground="black", background="blue", width=5)
return "TButton"
# Function for setting the style of each frame
def frameStyle(self):
# Creating object style
frameStyle = ttk.Style()
# Setting style
frameStyle.configure("TFrame", background=self.background)
return "TFrame"
# Function for setting the style of each frame
def notebookStyle(self):
# Creating object style
notebookStyle = ttk.Style()
# Setting style
notebookStyle.configure("TNotebook", background=self.background)
return "TNotebook"
# Function for setting the style of each checkbutton
def checkButtonStyle(self):
# Creating object style
checkButtonStyle = ttk.Style()
# Setting style
checkButtonStyle.configure(
"TCheckbutton", foreground="black", background="white"
)
return "TCheckbutton"
# Function for creating the appareance of Gui
def appareance(self):
# Setting tittle
self.root.title(self.title)
# Size of screen
self.root.geometry(str(self.width) + "x" + str(self.height))
# Changing background color
self.root.configure(bg=self.background)
# Creating a notebook
self.notebook = ttk.Notebook(self.root, style=self.notebookStyle())
self.notebook.pack(fill=BOTH, expand=True, pady=15)
# Creating frame for Gui
self.frameGui = ttk.Frame(self.notebook, style=self.frameStyle())
self.frameGui.pack(fill=BOTH, expand=True)
# Adding frame to tabs of notebook
self.notebook.add(self.frameGui, text="Data")
# Function to create a menu
def menu(self):
# Creating main menu
mainMenu = Menu(self.root)
# Setting main menu
self.root.config(menu=mainMenu)
plot = Menu(mainMenu, tearoff=FALSE)
# Adding submenus to main menu
mainMenu.add_cascade(label="Plot", menu=plot)
# Adding command to submenus
plot.add_command(label="Functions", command=self.secondMenu)
# Function to create the second menu
def secondMenu(self):
# Creating a second window
secondWindow = Toplevel(self.root, background=self.background)
# Size of screen
secondWindow.geometry("400x200")
# Getting the coordinates of root window
coordinateX = self.root.winfo_x()
coordinateY = self.root.winfo_y()
# Positioning the left upper toplevel window
secondWindow.geometry("+%d+%d" % (coordinateX + self.width, coordinateY))
# Creating first checkbutton
self.firstVariable = IntVar()
checkbuttonFirst = ttk.Checkbutton(
secondWindow,
text="Function",
style=self.checkButtonStyle(),
variable=self.firstVariable,
)
# Showing in screen
checkbuttonFirst.grid(row=1, column=0, padx=20, sticky="EW")
# Creating button to plot the selected function
buttonPlotFunction = ttk.Button(
secondWindow, text="Plot", style=self.buttonStyle(), command=self.plot
)
# Showing in screen
buttonPlotFunction.grid(row=3, column=0, pady=10)
# Function to plot the pharmacokinetics
def plot(self):
# Deleting each object
for object in self.objects:
del object
# Creating frame for Pharmakinetics plot
framePlot = ttk.Frame(self.notebook, style=self.frameStyle())
framePlot.pack(fill=BOTH, expand=True)
# Adding frame to tabs of notebook
self.notebook.add(framePlot, text="Plot")
# Creating an object from classPharmakinetics
objPlot = Plot(
framePlot,
"Test plot",
self.background,
"x",
"y",
self.data,
)
self.objects = np.append(self.objects, objPlot)
if self.firstVariable.get() == 1:
objPlot.plot()
# Function for calling each function from the class
def gui(self):
self.appareance()
self.menu()
# Creating infinite loop to show in screen
self.root.mainloop()

绘图:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import numpy as np
from lmfit import Model
from tkinter import *

class Plot:
# Attributes of the class
# Creating the canvas and the axis
fig, ax = plt.subplots()
# Constructor function
def __init__(self, root, title, background, xLabel, yLabel, data):
self.root = root  # Root
self.title = title  # Title
self.background = background  # Background color
self.xLabel = xLabel  # Label of axis X
self.yLabel = yLabel  # Label of axis Y
self.data = data  # Dictionary to store the data
# Data to evaluate the functions
self.dataRange = np.linspace(
self.data["x"][0],
self.data["x"][len(self.data["x"]) - 1],
100,
endpoint=True,
)
# Double exponential function
def doubleExponential(self, time, A, B, C):
return A * (np.exp(-B * time) - np.exp(-C * time))
# Function to plot the double exponential function
def plot(self):
# Adding the function to fit as the Model
model = Model(self.doubleExponential)
# Initializing the parameters
params = model.make_params(A=0.5, B=0.005, C=0.5)
# Getting the fitting data
dataFitting = model.fit(self.data["y"], params, time=self.data["x"])
# Plotting the fitted function using the obtained parameters
self.ax.plot(
self.dataRange,
self.doubleExponential(
self.dataRange,
dataFitting.params["A"].value,
dataFitting.params["B"].value,
dataFitting.params["C"].value,
),
"-",
label="Fit",
)
# Inserting matplotlib charts into canvas
matplotlib_gui = self.root
# Creating the Tkinter canvas containing the Matplotlib figure
canvas = FigureCanvasTkAgg(self.fig, master=matplotlib_gui)
canvas.draw()
# Placing the canvas on the Tkinter window
canvas.get_tk_widget().pack()
# Creating the Matplotlib toolbar
toolbar = NavigationToolbar2Tk(canvas, matplotlib_gui)
toolbar.update()
# Placing the toolbar on the Tkinter window
canvas.get_tk_widget().pack()

Main:

from stack1 import *
# Main features of a GUI
title = "Plot"
width = 500
height = 500
foreground = "black"
background = "white"
# Creating an object from classGUI
a = Gui(title, width, height, foreground, background)
a.gui()

导入工具栏的问题是由于插入了框架而不是根窗口,作为的第二个参数CCD_ 1。显然,第二个论点一定是根窗口。

最新更新