I have a plot in which the x axis contains datetime.datetime objects. I am trying to change the range of the x axis with multiple matplotlib.widgets.Buttons. One button shows all datetimes, while another button shows only the last two seconds. When a button is clicked it should become green while the other button should become red.
Below is a minimal working example that shows my problem. There are two scenarios:
- Run script. Click on "Show only last two seconds". Works. Then click on "Show all times". Works. At this point, the "Show only last two seconds" stops working.
- Run script. Click on "Show all times". Works. Then click on "Show only last two seconds". This does nothing.
I added some print statements (commented out in the minimal working example) to try to find out the problem. It appears that when one button becomes activated, the other does not become immediately unactivated, which is what is intended. That is, setting the activated attribute to False in the while loop does not work as intended. There is also a problem with the button color.
How do I modify the minimal working example to produce the intended behavior? Feel free to suggest any other modifications.
#!/usr/bin/env python3
from datetime import datetime
from datetime import timedelta
from matplotlib.widgets import Button
import matplotlib.pyplot as plt
import random
class ButtonClickProcessor:
def __init__(self, axes, label):
self.button = Button(axes, label, color = 'red')
self.button.on_clicked(self.process)
self.activated = False
def process(self, event):
self.activated = True
self.button.color = 'green'
plt.gcf().canvas.draw()
#print('ButtonClickProcessor.process', self.activated)
def main():
start_time = datetime.now()
fig, axes = plt.subplots()
datetimes = []
y_values = []
button_show_all_times = ButtonClickProcessor(axes = plt.axes([0.0, 0.0, 0.5, 0.1]), label = 'Show all times')
button_show_only_last_2_seconds = ButtonClickProcessor(axes = plt.axes([0.5, 0.0, 0.5, 0.1]), label = 'Show only last 2 seconds')
while True:
#print('Start of while True; button_show_all_times', button_show_all_times.activated)
#print('Start of while True; button_show_only_last_2_seconds', button_show_only_last_2_seconds.activated)
now = datetime.now()
datetimes.append(now)
y_values.append(random.randint(a = 0, b = 10))
axes.plot(datetimes, y_values)
time_difference = now - start_time
if time_difference.total_seconds() > 2:
delta = timedelta(seconds = 2)
if button_show_all_times.activated is True:
button_show_only_last_2_seconds.activated = False
button_show_only_last_2_seconds.button.color = 'red'
fig.canvas.draw()
axes.set_xlim(left = datetimes[0])
#print('button_show_all_times.activated is True:', button_show_all_times.activated, button_show_only_last_2_seconds.activated)
if button_show_only_last_2_seconds.activated is True:
button_show_all_times.activated = False
button_show_all_times.button.color = 'red'
fig.canvas.draw()
axes.set_xlim(left = now - delta)
#print('button_show_only_last_2_seconds.activated', button_show_all_times.activated, button_show_only_last_2_seconds.activated)
fig.tight_layout(rect = [0, 0.1, 1, 1])
plt.pause(0.0001)
axes.clear()
plt.show()
if __name__ == '__main__':
main()