【问题标题】:Change axis range using matplotlib.widgets.Button使用 matplotlib.widgets.Button 更改轴范围
【发布时间】:2020-11-10 15:38:00
【问题描述】:

我有一个图,其中 x 轴包含 datetime.datetime 对象。我正在尝试使用多个matplotlib.widgets.Buttons 更改 x 轴的范围。一个按钮显示所有日期时间,而另一个按钮仅显示最后两秒。当一个按钮被点击时,它应该变成绿色,而另一个按钮应该变成红色。

下面是一个显示我的问题的最小工作示例。有两种情况:

  1. 运行脚本。单击“仅显示最后两秒”。作品。然后点击“显示所有时间”。作品。此时,“仅显示最后两秒”停止工作。
  2. 运行脚本。点击“显示所有时间”。作品。然后单击“仅显示最后两秒”。这无济于事。

我添加了一些打印语句(在最小的工作示例中注释掉)来尝试找出问题。似乎当一个按钮被激活时,另一个按钮不会立即变为未激活,这是预期的。也就是说,在while 循环中将activated 属性设置为False 无法按预期工作。按钮颜色也有问题。

如何修改最小的工作示例以产生预期的行为?随意提出任何其他修改建议。

#!/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()

【问题讨论】:

    标签: matplotlib matplotlib-widget


    【解决方案1】:

    如果将来有人偶然发现此问题,以下是我的解决方案。我最终通过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()
    

    【讨论】:

      猜你喜欢
      • 2018-03-19
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 2017-08-02
      • 2015-09-14
      • 1970-01-01
      • 2016-02-26
      • 1970-01-01
      相关资源
      最近更新 更多