我在Tkinter GUI环境中嵌入了Matplotlib折线图。我的“实验”基本上从用户那里得到两个输入(数字),然后应该使用它们来画一条线。但是,我不知道如何根据用户输入绘制折线图。有人可以解释如何做吗?这是我的代码:
from tkinter import *
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt
import numpy as np
root = tk.Tk()
root.geometry('500x700')
first_input = StringVar()
second_input = StringVar()
class Graph():
def linechart():
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y = [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5]
plt.plot(x, y)
plt.xticks(np.arange(min(x), max(x)+1, 1.0))
plt.show()
class Random(Graph):
def __init__(self):
self.label1 = None
self.label2 = None
self.userEntry = None
def first_input(self):
self.label1 = ttk.Label(text="Insert:")
self.label1.pack()
self.userEntry = ttk.Entry(textvariable=first_input)
self.userEntry.pack()
self.button_2 = Button(root, text="Enter", command=self.second_input)
self.button_2.pack()
def second_input(self):
self.label2 = ttk.Label(text="Insert:")
self.label2.pack()
self.userEntry = ttk.Entry(textvariable=second_input)
self.userEntry.pack()
self.button_3 = Button(root, text="Enter", command=self.create_window)
self.button_3.pack()
def create_window(self):
Graph.linechart()
random = Random()
button_1 = Button(root, text="random", command=lambda:random.first_input())
button_1.pack()
root.mainloop()
答案 0 :(得分:2)
这里是如何在tkinter框架中嵌入matplotlib图,如何根据用户输入的坐标在该图上绘制线以及如何在tkinter级别直接覆盖轴的方法:
有关更简单的示例,请参见matplotlib docs。
彩色线条绘制在tkinter画布中嵌入的matplotlib图形上,其中一条线来自p0=(0, 0), p1=(500, 500)
,另一条线来自p0=(0, 500), p1=(500, 0)
。 (从弹出窗口输入)
黑白叠加层直接在tkinter画布上绘制
import matplotlib as mpl
import tkinter as tk
import matplotlib.backends.tkagg as tkagg
from matplotlib.backends.backend_agg import FigureCanvasAgg
def draw_figure(canvas, figure, loc=(0, 0)):
""" Draw a matplotlib figure onto a Tk canvas
loc: location of top-left corner of figure on canvas in pixels.
Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
"""
figure_canvas_agg = FigureCanvasAgg(figure)
figure_canvas_agg.draw()
figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
figure_w, figure_h = int(figure_w), int(figure_h)
photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
return photo
class LineCoordsEntry(tk.Toplevel):
def __init__(self, master):
self.master = master
super().__init__(self.master)
self.label_x0 = tk.Label(self, text='x0:')
self.label_x0.grid(row=0, column=0)
self.entry_x0 = tk.Entry(self, width=6)
self.entry_x0.grid(row=0, column=1)
self.label_y0 = tk.Label(self, text='y0:')
self.label_y0.grid(row=0, column=2)
self.entry_y0 = tk.Entry(self, width=6)
self.entry_y0.grid(row=0, column=3)
self.label_x1 = tk.Label(self, text='x1:')
self.label_x1.grid(row=1, column=0)
self.entry_x1 = tk.Entry(self, width=6)
self.entry_x1.grid(row=1, column=1)
self.label_y1 = tk.Label(self, text='y1:')
self.label_y1.grid(row=1, column=2)
self.entry_y1 = tk.Entry(self, width=6)
self.entry_y1.grid(row=1, column=3)
self.quit_button = tk.Button(self, text='quit', command=self.destroy)
self.quit_button.grid(row=2, column=0)
self.validate_button = tk.Button(self, text='validate', command=self.send_data)
self.validate_button.grid(row=2, column=1, columnspan=3)
def send_data(self):
p0 = float(self.entry_x0.get()), float(self.entry_y0.get())
p1 = float(self.entry_x1.get()), float(self.entry_y1.get())
self.master.retrieve_line_data(p0, p1)
class App(tk.Frame):
def __init__(self, master, w=500, h=500):
self.master = master
super().__init__(self.master)
self.w = w
self.h = h
self.canvas = tk.Canvas(self.master, width=self.w, height=self.h)
self.canvas.pack()
self.enter_line_coordinates_button = tk.Button(self, text='make new line', command=self.spawn_entry_coordinates)
self.enter_line_coordinates_button.pack()
self.draw_lines_button = tk.Button(self, text='draw lines', command=self.draw_lines)
self.draw_lines_button.pack()
self.draw_overlay_button = tk.Button(self, text='draw overlaid axis', command=self.draw_overlay)
self.draw_overlay_button.pack()
self.erase_overlay_button = tk.Button(self, text='remove overlaid axis', command=self.erase_overlay)
self.erase_overlay_button.pack()
self.lines = []
def spawn_entry_coordinates(self):
LineCoordsEntry(self)
def retrieve_line_data(self, p0, p1):
self.lines.append((p0, p1))
print(self.lines)
def draw_lines(self):
"""draw the lines on the matplotlib canvas
"""
fig = mpl.figure.Figure(figsize=(5, 5))
ax = fig.add_axes([0, 0, 1, 1])
for p0, p1 in self.lines:
x0, y0, x1, y1 = *p0, *p1
X = x0, x1
Y = y0, y1
print(X, Y)
ax.plot(X, Y)
self.fig_x, self.fig_y = 0, 0 #self.w, self.h
self.fig_photo = draw_figure(self.canvas, fig, loc=(self.fig_x, self.fig_y))
self.fig_w, self.fig_h = self.fig_photo.width(), self.fig_photo.height()
def draw_overlay(self):
"""draw lines on the tkinter canvas, overlaid on the matplotlib canvas
"""
self.canvas.create_line(0, self.h//2, self.w, self.h//2, tags=('overlay',))
self.canvas.create_line(self.w//2, 0, self.w//2, self.h, tags=('overlay',))
def erase_overlay(self):
self.canvas.delete('overlay')
root = tk.Tk()
App(root).pack()
root.mainloop()