KristianEE
KristianEE

Reputation: 11

Issues with tkinter canvas & matplotlib figure resizing

Relatively new to tkinter and I am now stuck. I am building an application where the user is loading csv files with data. This is stored as DataFrames. The purpose of the app is to be able to plot the data that has been loaded. All is good until I started implementing the option of adding additional axis to the plot. Currently, I am only adding the option of adding a y-axis. All is fine, and I am able to plot the data, but here is where the issues start.

For plotting, I am using the FigureCanvasTkAgg implementation. I have a canvas that is created and the plot is drawn onto this. However, I am experiencing that the figure changes size such that the right axis is outside of the window. Increasing the size of the window reveals the axis. I have implemented a resizing of the figure binding the canvas to an event where the new size is picked up. However, the resizing is living its own life. I have recreated the a similar set-up with the parasite axis examples found in matplotlib. Can someone please explain why the figure is behaving as it does when changing the window size?

import tkinter as tk
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA

def resize_canvas(event):
    
    print(event)
    new_width = event.width
    new_height = event.height
    print(new_width, new_height)
        
    plot_window.get_tk_widget().configure(width=new_width, height=new_height)
        
    fig.set_figheight(new_height/96)
    fig.set_figwidth(new_width/96)
    
    plot_window.draw()
    
root = tk.Tk()

main_fr = tk.Frame()

main_fr.pack(side="top", fill="both", expand=True)

root.wm_geometry("736x670")
root.minsize(736,670)
root.maxsize(1600,800)

fig = Figure(figsize=(736/96,670/96), tight_layout=True, dpi=96)
plot_window = FigureCanvasTkAgg(fig, master=main_fr)


host = host_subplot(111, axes_class=AA.Axes, figure=fig)
        
par1 = host.twinx()
par2 = host.twinx()


offset = 50
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",
                            axes=par2,
                        offset=(offset, 0))

par1.axis["right"].toggle(all=True)
par2.axis["right"].toggle(all=True)

host.set_xlim(0, 2)
host.set_ylim(0, 2)

host.set_xlabel("Distance")
host.set_ylabel("Density")
par1.set_ylabel("Temperature")
par2.set_ylabel("Velocity")

p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature")
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity")

par1.set_ylim(0, 4)
par2.set_ylim(1, 65)

host.legend()

host.axis["left"].label.set_color(p1.get_color())
par1.axis["right"].label.set_color("red")
par2.axis["right"].label.set_color(p3.get_color())  

main_fr.columnconfigure(1,weight=1)
main_fr.rowconfigure(1,weight=1)

plot_window.get_tk_widget().grid(row=1, column=1, sticky="nsew")        
plot_window.get_tk_widget().bind('<Configure>', resize_canvas)
#plot_window.draw()

root.mainloop()

Upvotes: 1

Views: 2101

Answers (1)

imxitiz
imxitiz

Reputation: 3987

I think this is what you are trying to achieve :

import tkinter as tk
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
    
root = tk.Tk()

fig = Figure(figsize=(10,7), dpi=96)
plot_window = FigureCanvasTkAgg(fig, master=root)

host = host_subplot(111, axes_class=AA.Axes, figure=fig)
        
par1 = host.twinx()
par2 = host.twinx()


offset = 50
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",axes=par2,offset=(offset, 0))

par1.axis["right"].toggle(all=True)
par2.axis["right"].toggle(all=True)

host.set_xlim(0, 2)
host.set_ylim(0, 2)

host.set_xlabel("Distance")
host.set_ylabel("Density")
par1.set_ylabel("Temperature")
par2.set_ylabel("Velocity")

p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature")
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity")

par1.set_ylim(0, 4)
par2.set_ylim(1, 65)

host.legend()

host.axis["left"].label.set_color(p1.get_color())
par1.axis["right"].label.set_color("red")
par2.axis["right"].label.set_color(p3.get_color())  

plot_window.get_tk_widget().pack(side = tk.TOP, expand = True , fill = tk.BOTH)

root.mainloop()

I have removed that main_fr and pack that FigureCanvasTkAgg in root, and that tight_layout is causing problem.

Upvotes: 1

Related Questions