matplotlib 弹出窗口中的错误(AttributeError: 'NoneType' 对象没有属性 'set_canvas') [英] Error in matplotlib popup window (AttributeError: 'NoneType' object has no attribute 'set_canvas')
问题描述
我试图在弹出窗口中绘制图形.它弹出.但是有一个错误.
I tried to plot the graph in pop up window. It pops up. But there is an error.
import tkinter as tk
window = tk.Tk()
window.configure(background='white')
label_1 = tk.Label(window, text="Conpyright 123456789123456798", anchor=tk.S)
label_1.pack()
ws = window.winfo_screenwidth()
hs = window.winfo_screenheight()
w = 980 # width for the Tk root
h = 600 # height for the Tk root
x = (ws / 2) - (w / 2)
y = (hs / 2) - (h / 2)
window.geometry('%dx%d+%d+%d' % (w, h, x, y))
canvas = tk.Canvas(window, bg="white", width=980, height=580, highlightthickness=0)
canvas.pack()
canvas_scroll = tk.Scrollbar(canvas, command=canvas.yview)
canvas_scroll.place(relx=1, rely=0, relheight=1, anchor=tk.NE)
canvas.configure(yscrollcommand=canvas_scroll.set, scrollregion=())
minw_var = tk.DoubleVar()
entry_minw_number = tk.Entry(canvas, textvariable=minw_var)
canvas.create_window(220,215, window=entry_minw_number)
maxw_var = tk.DoubleVar()
entry_maxw_number = tk.Entry(canvas, textvariable=maxw_var)
canvas.create_window(355,215, window=entry_maxw_number)
minl_var = tk.DoubleVar()
entry_minl_number = tk.Entry(canvas, textvariable=minl_var)
canvas.create_window(220,240, window=entry_minl_number)
maxl_var = tk.DoubleVar()
entry_maxl_number = tk.Entry(canvas, textvariable=maxl_var)
canvas.create_window(355,240, window=entry_maxl_number)
rect_var = tk.IntVar()
entry_rect_number = tk.Entry(canvas, textvariable=rect_var)
canvas.create_window(290,270, window=entry_rect_number)
这是 matplotlib 的部分
And this is the part for matplotlib
def plot_sheet(self):
fig,ax = plt.subplots(1)
ax.set_xlim([0, self.W])
ax.set_ylim([0, self.L])
recs = []
for i in range(len(self.rect_list)):
if self.rect_rotate[i]:
ax.add_patch(patches.Rectangle((self.rect_pos[i][0], self.rect_pos[i][1]), self.rect_list[i].l, self.rect_list[i].w,linewidth=3,edgecolor='r'))
else:
ax.add_patch(patches.Rectangle((self.rect_pos[i][0], self.rect_pos[i][1]), self.rect_list[i].w, self.rect_list[i].l,linewidth=3,edgecolor='r'))
#plt.show()
return fig
def plot_sheets(self):
for i in range(len(self.sheets)):
self.sheets[i].plot_sheet()
def cal_culate1():
fig = packing_options[best_index].plot_sheets()
dataPlot = FigureCanvasTkAgg(fig, master = window)
dataPlot.show()
dataPlot.get_tk_widget().pack(side='top', fill='both', expand=1)
window.mainloop()
我写了 dataPlot = FigureCanvasTkAgg(fig, master = window).master = window 有错误.
I wrote dataPlot = FigureCanvasTkAgg(fig, master = window). There is an error in master = window.
文件",第 687 行,在 cal_culate1 中dataPlot = FigureCanvasTkAgg(fig, master = window)
File "", line 687, in cal_culate1 dataPlot = FigureCanvasTkAgg(fig, master = window)
文件C:\Users\sel\Anaconda3\lib\site-packages\matplotlib\backends_backend_tk.py",第 204 行,initsuper(FigureCanvasTk, self).init(figure)
File "C:\Users\sel\Anaconda3\lib\site-packages\matplotlib\backends_backend_tk.py", line 204, in init super(FigureCanvasTk, self).init(figure)
文件C:\Users\sel\Anaconda3\lib\site-packages\matplotlib\backend_bases.py",第 1618 行,init图.set_canvas(self)
File "C:\Users\sel\Anaconda3\lib\site-packages\matplotlib\backend_bases.py", line 1618, in init figure.set_canvas(self)
AttributeError: 'NoneType' 对象没有属性 'set_canvas'
AttributeError: 'NoneType' object has no attribute 'set_canvas'
那里应该写什么?
推荐答案
我做了一个最小的工作示例来展示如何做到这一点.
I made minimal working example which shows how do this.
它需要更改您的代码,但我不知道您的代码中有什么,而且您没有创建最小的工作示例.
it will need changes for your code but I don't know what you have in code and you didn't create minimal working example.
它使用 plot_sheet
在 generate_all_figures
(在您的代码中将是 plot_sheets
和 s
)创建三个图形(没有 s
)并保留在列表中.
It creates three figures in generate_all_figures
(in your code it will be plot_sheets
with s
) using plot_sheet
(without s
) and keep on list.
window
显示此列表中的第一个图形.
window
display first figure from this list.
Buttons
删除带有图形的画布,并使用列表中的下一个/上一个图形创建新画布.
Buttons
remove canvas with figure and create new canvas with next/previous figure from list.
我使用 grid()
而不是 pack()
因为这样我可以轻松地将新画布放在同一个地方.
I use grid()
instead of pack()
because this way I can easily put new canvas in the same place.
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class MyClass():
def __init__(self):
self.sheets = [[1,2,3], [3,1,2], [1,5,1]]
self.W = 2
self.L = 5
self.all_figures = []
def plot_sheet(self, data):
"""plot single figure"""
fig, ax = plt.subplots(1)
ax.set_xlim([0, self.W])
ax.set_ylim([0, self.L])
ax.plot(data)
return fig
def generate_all_figures(self):
"""create all figures and keep them on list"""
for data in self.sheets:
fig = self.plot_sheet(data)
self.all_figures.append(fig)
def show_figure(number):
global dataPlot
# remove old canvas
if dataPlot is not None: # at start there is no canvas to destroy
dataPlot.get_tk_widget().destroy()
# get figure from list
one_figure = my_class.all_figures[number]
# display canvas with figuere
dataPlot = FigureCanvasTkAgg(one_figure, master=window)
dataPlot.draw()
dataPlot.get_tk_widget().grid(row=0, column=0)
def on_prev():
global selected_figure
# get number of previous figure
selected_figure -= 1
if selected_figure < 0:
selected_figure = len(my_class.all_figures)-1
show_figure(selected_figure)
def on_next():
global selected_figure
# get number of next figure
selected_figure += 1
if selected_figure > len(my_class.all_figures)-1:
selected_figure = 0
show_figure(selected_figure)
# --- main ---
my_class = MyClass()
my_class.generate_all_figures()
window = tk.Tk()
window.rowconfigure(0, minsize=500) # minimal height
window.columnconfigure(0, minsize=700) # minimal width
# display first figure
selected_figure = 0
dataPlot = None # default value for `show_figure`
show_figure(selected_figure)
# add buttons to change figures
frame = tk.Frame(window)
frame.grid(row=1, column=0)
b1 = tk.Button(frame, text="<<", command=on_prev)
b1.grid(row=0, column=0)
b2 = tk.Button(frame, text=">>", command=on_next)
b2.grid(row=0, column=1)
window.mainloop()
<小时>
可能可以在不替换画布的情况下通过替换绘图中的数据来完成 (fig.data
???, ax.data
??? 我不记得了)
Probably it could be done without replacing canvas but by replacing data in plot (fig.data
???, ax.data
??? I don't remember)
这篇关于matplotlib 弹出窗口中的错误(AttributeError: 'NoneType' 对象没有属性 'set_canvas')的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!