我有一个绘图,其中x轴包含datetime.datetime
个对象。我正在尝试使用多个matplotlib.widgets.Button
来更改x轴的范围。一个按钮显示所有日期时间,而另一个按钮仅显示最后两秒钟。单击一个按钮后,该按钮应变为绿色,而另一个按钮应变为红色。
下面是一个显示我的问题的最小工作示例。有两种情况:
我添加了一些打印语句(在最小的工作示例中作了注释)以尝试找出问题所在。看起来当一个按钮被激活时,另一个按钮并没有立即被取消激活,这正是本意。也就是说,在activated
循环中将False
属性设置为while
并不能正常工作。按钮的颜色也有问题。
如何修改最小工作示例以产生预期的行为?随时提出其他修改建议。
#!/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()
答案 0 :(得分:0)
以防将来有人偶然发现此问题,下面是我的解决方案。我最终通过all_buttons
属性使每个按钮了解所有按钮。这解决了激活我单击的按钮并同时停用其他按钮的问题。为了更改颜色,关键要素是button.ax.set_facecolor
方法。没有这个,在我移动鼠标之前按钮的颜色不会改变。这样,一旦我单击按钮,颜色就会改变。我不知道这是最好还是最有效的解决方案,但是它有效。我仍然愿意提出改进建议。
#!/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(ax = axes, label = label, color = 'red', hovercolor = 'red')
self.button.on_clicked(self.process)
self.activated = False
self.all_buttons = None
def process(self, event):
for button in self.all_buttons:
button.activated = False
button.button.color = 'red'
button.button.hovercolor = button.button.color
button.button.ax.set_facecolor(button.button.color)
self.activated = True
self.button.color = 'green'
self.button.hovercolor = self.button.color
self.button.ax.set_facecolor(self.button.color)
self.button.ax.figure.canvas.draw()
def main():
start_time = datetime.now()
fig, axes = plt.subplots()
datetimes = []
y_values = []
button_show_all_times = ButtonClickProcessor(axes = plt.axes([0.01, 0.01, 0.5, 0.1]), label = 'Show all times')
button_show_only_last_2_seconds = ButtonClickProcessor(axes = plt.axes([0.5, 0.01, 0.49, 0.1]), label = 'Show only last 2 seconds')
all_buttons = (button_show_all_times, button_show_only_last_2_seconds)
button_show_all_times.all_buttons = all_buttons
button_show_only_last_2_seconds.all_buttons = all_buttons
while True:
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:
axes.set_xlim(left = datetimes[0])
if button_show_only_last_2_seconds.activated is True:
axes.set_xlim(left = now - delta)
fig.tight_layout(rect = [0, 0.1, 1, 1])
plt.pause(0.0001)
axes.clear()
plt.show()
if __name__ == '__main__':
main()