I have been stuck on this for a while and cannot work out the issue, so was hoping somebody on here could assist.
I am attempting to create a program to graph some data stored in a .csv file. My program starts with an empty graph and requires the user to first select a file, and then prompts the user to specify which columns from the csv file should be plotted. For the purposes of getting assistance, I have created a smaller program to outline the issue that I am experiencing.
As part of the graphing process, I want to have 5 gridlines displayed on the x-axis at all times, with the interval between these lines determined by the current viewable x-axis limits. For this reason, I have created a 'CustomFormatter' class which inherits from matplotlib.ticker's Formatter class, and overridden the 'call' method to try and get the desired behaviour. I believe that I need to do this in order to keep track of the current viewable xlimits of the graph, which then enable me to calculate the required intervals.
When I run my code, the following GUI is generated, which seems to be working as intended: enter image description here
However, once I click the 'Load Data' button, my specified data is loaded into the graph, but the graph's x-axis labels and gridlines disappear, as shown in the below image. enter image description here
It is not until I use the built-in pan tool to pan the graph that these gridlines and labels reappear, as shown in the below image. enter image description here
The same thing happens when I zoom in on the graph. After zooming, it is not until I pan again that the x-axis labels and gridlines re-calibrate themselves to the desired positions.
Any help that anyone is willing to provide to help me solve this issue would be greatly appreciated. Hopefully it is just something basic or silly that I am overlooking.
Cheers.
The code I used to generate my matplotlib graph embedded in a tkinter frame is shown below:
import tkinter as tk
import matplotlib
import matplotlib.dates as mdates
from matplotlib.ticker import Formatter
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
class CustomFormatter(Formatter):
def __init__(self, ax, graph):
super().__init__()
self.set_axis(ax)
self.ax = ax
self.graph = graph
def __call__(self, x, pos=None):
xlims = self.ax.get_xlim()
ylims = self.ax.get_ylim()
xmin, xmax = xlims[0], xlims[1]
xmin = mdates.num2date(xmin)
xmax = mdates.num2date(xmax)
x = mdates.num2date(x)
interval = (xmax - xmin) / 6
self.ax.set_xticks([xmin, xmin + 1 * interval, xmin + 2 * interval, xmin + 3 * interval, xmin + 4 * interval, xmin + 5 * interval, xmax])
self.ax.grid(b=True, which='major', axis='both')
return f"{x.hour}:{x.minute}:{x.second}\n{x.day}/{x.month}/{x.year}"
class App(object):
def __init__(self, master):
initialFrame = tk.Frame(master)
initialFrame.pack(fill=tk.BOTH, expand=1)
master.title('Tkinter Graph Example')
self.master = master
self._load_data_button = tk.Button(initialFrame, takefocus=0, text='Load data')
self._load_data_button.bind('<Button-1>', self.load_data)
self._load_data_button.pack(side=tk.TOP, fill=tk.BOTH, padx=2, pady=2, ipady=5)
self.graphFrame = tk.Frame(initialFrame, borderwidth=5, relief=tk.SUNKEN)
self.graphFrame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.f=Figure(figsize=(5,5), dpi=100)
self.a=self.f.add_subplot(111)
self.graph = FigureCanvasTkAgg(self.f, self.graphFrame)
self.graph.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
self.toolbar = NavigationToolbar2Tk(self.graph, self.graphFrame)
self.toolbar.update()
self.graph._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.a.set_xlabel('Time')
self.a.set_ylabel('Y-Axis')
self.a.set_title('Test')
self.a.grid(b=True)
self.a.xaxis.set_major_formatter(CustomFormatter(self.a, self.graph))#, self.df, self.toPlot, self.index_dict, self.name_dict))
self.graph.draw()
def load_data(self, event):
data = [1, 4, 2, 7, 4, 6]
time = [18820.410517624932, 18820.414807940015, 18820.41623804504, 18820.41766815007, 18820.41862155342, 18820.420528360122]
self.a.plot(time, data)
self.a.set_xlim(xmin=time[0], xmax=time[-1])
self.graph.draw()
def main():
root = tk.Tk()
app = App(root)
root.geometry('%dx%d+0+0'%(800,600))
root.mainloop()
if __name__ == '__main__':
main()