2

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)

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()

I wrote dataPlot = FigureCanvasTkAgg(fig, master = window). There is an error in master = window.

File "", line 687, in cal_culate1 dataPlot = FigureCanvasTkAgg(fig, master = window)

File "C:\Users\sel\Anaconda3\lib\site-packages\matplotlib\backends_backend_tk.py", line 204, in init super(FigureCanvasTk, self).init(figure)

File "C:\Users\sel\Anaconda3\lib\site-packages\matplotlib\backend_bases.py", line 1618, in init figure.set_canvas(self)

AttributeError: 'NoneType' object has no attribute 'set_canvas'

What should be written there?

10
  • have you refined window somewhere? It works for me if i removed everything and kept the bare minimum to plot the graph. Commented Apr 16, 2019 at 12:50
  • I haven't. I don t know why is it showing up. Commented Apr 16, 2019 at 12:56
  • The code for pop up window is inside a function. I have updated the question. Does that make a difference? Commented Apr 16, 2019 at 12:59
  • check if your fig is None. The problem might not be the window part Commented Apr 16, 2019 at 13:02
  • How do I check that? Commented Apr 16, 2019 at 13:11

2 Answers 2

2

You didn't show how you create your class for plotting, so i can only go by assumption here. First create a empty list:

import tkinter as tk
window = tk.Tk()
window.configure(background='white')
figure_holder = []

Then append to the list when you create your figure:

def plot_sheets(self):
    for i in range(len(self.sheets)):
        a = self.sheets[i].plot_sheet()
        figure_holder.append(a)

Retrieve the figure object from the list when you plot it:

def cal_culate1():

    fig = figure_holder[0]

    dataPlot = FigureCanvasTkAgg(fig, master = window)
    #dataPlot.show()
    dataPlot.get_tk_widget().pack(side='top', fill='both', expand=1)
Sign up to request clarification or add additional context in comments.

1 Comment

Don't we have to do this: fig = packing_options[best_index].plot_sheets() ?
1

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.

enter image description here

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 display first figure from this list.

Buttons remove canvas with figure and create new canvas with next/previous figure from list.

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()

Probably it could be done without replacing canvas but by replacing data in plot (fig.data ???, ax.data ??? I don't remember)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.