I've been working on creating a matplotlib plot that you can dynamically adjust inside of a tkinter GUI. To change aspects of the chart such as the view frame I planned on using buttons that can change the number of candles shown, and what candles are shown in a given dataset. My code is not refractored since I've been changing many things on it but it is pasted below.
# Defining the chart
chart = Frame(charting)
width=.6
figure = Figure( figsize=(6,4),dpi=100)
canvas = FigureCanvasTkAgg(figure, chart)
canvas.get_tk_widget().pack(side=TOP, fill=BOTH)
plot = figure.add_axes([0.07,0.15,.8,.8])
candleCount = 30
startCandle = 0
def loadChart() :
chartData = loadData(ticker.get(),timeframe.get(),length.get())["chart"]
plot.clear()
plot.bar(x=chartData["positions"][startCandle:startCandle candleCount],height=chartData["hlheights"][startCandle:startCandle candleCount],bottom=chartData["hlbottoms"][startCandle:startCandle candleCount],color="black",width=width/15)
plot.bar(x=chartData["positions"][startCandle:startCandle candleCount],height=chartData["ocheights"][startCandle:startCandle candleCount],bottom=chartData["ocbottoms"][startCandle:startCandle candleCount],color=chartData['colors'][startCandle:startCandle candleCount],width=width)
plot.set_xticks(range(candleCount))
mplcursors.cursor(plot).connect("add", lambda sel: sel.annotation.set_text(chartData["summary"][sel.index]))
plot.set_xticklabels(chartData["labels"][startCandle:startCandle candleCount],rotation=65)
figure.canvas.draw()
print("Chart Loaded")
loadChart()
# Place Chart buttons
def shiftChart(shift=1) :
global startCandle
startCandle = shift
print("shifted Chart")
def zoomChart(zoom=1) :
global candleCount
candleCount = zoom
print("zoomed Chart")
leftButton = Button(chart,text = "<<",command=lambda:[shiftChart(-1),loadChart()]).pack(side=LEFT)
rightButton = Button(chart,text=">>",command=lambda:[shiftChart(1),loadChart()]).pack(side=LEFT)
zoomoutButton = Button(chart,text="-",command=lambda:[zoomChart(-1),loadChart()]).pack(side=LEFT)
zoominButton = Button(chart,text=" ",command=lambda:[zoomChart(1),loadChart()]).pack(side=LEFT)
loadChart = Button(chartingInput,text="Load Chart",command=loadChart)
loadChart.grid(row=2)
charting.add(chart)
charting.add(chartingInput)
Incase you would like to test the code here is a sample of the stock data that is used to build the chart
[(1640077200000, 171.84, 171.84, 171.6, 171.83, 1894), (1640077260000, 171.64, 171.8, 171.64, 171.8, 1007), (1640077320000, 171.68, 171.68, 171.28, 171.59, 2048), (1640077380000, 171.64, 171.7, 171.64, 171.7, 6521), (1640077500000, 171.69, 171.75, 171.69, 171.75, 823), (1640077560000, 171.81, 171.81, 171.81, 171.81, 476), (1640077620000, 171.8, 171.8, 171.8, 171.8, 625), (1640077740000, 171.78, 171.8, 171.78, 171.8, 2854), (1640077800000, 171.71, 171.71, 171.67, 171.67, 647)]
When I run the code the chart loads correctly, but when attempting to use a button to change an aspect of the chart such as the view frame or the number of candles displayed gives this error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:<my file path>", line 1884, in __call__
return self.func(*args)
File "c:<my file path>", line 85, in <lambda>
leftButton = Button(chart,text = "<<",command=lambda:[shiftChart(-1),loadChart()]).pack(side=LEFT)
TypeError: 'Button' object is not callable
I can't seem to figure out how to write the code to accept both functions when the button is clicked, and placing the loadChart function inside of either of the other two functions produces the same error.
CodePudding user response:
You have overwritten function loadChart() by the following line:
loadChart = Button(chartingInput,text="Load Chart",command=loadChart)
Use other name for the button:
loadChartBtn = Button(chartingInput,text="Load Chart",command=loadChart)
loadChartBtn.grid(row=2)
