Как сделать так, чтобы matplotlib button_press_event игнорировал нажатия на кнопки с цифрами? event.inaxes не работает, потому что кнопка является объектом оси - PullRequest
0 голосов
/ 30 января 2020

Вот проблема. Мне нужно создать "Ловец кликов". Мне нужно включить режим захвата кликов, нажав на кнопку (Отметить), а затем, когда я нажимаю на свой график, моя программа должна запомнить список точек, координаты и т. Д. c. Что особенно важно - другие кнопки должны работать нормально, когда включен режим захвата кликов. Например я реализовал кнопку Печать. Я хотел бы щелкнуть пару раз на своем графике, затем, , не выходя из , нажмите режим захвата, нажмите кнопку Печать и затем увидите список точек наблюдения. Проблема в том, что моя программа видит matplotlib.widgets кнопки как axes и ловит точки на них всякий раз, когда я использую любую кнопку.

Я пытался использовать event.inaxes which, который должен проверять, находится ли курсор в области осей. Итак, я реализовал некоторые логи c. К сожалению, он отлично работает только за пределами графика, но совсем не работает для кнопок. Кажется, что matplotlib видит кнопки как объект оси, поэтому он полностью не работает.

Пожалуйста, помогите мне с этим, я довольно новичок в программировании и сам все учил (так что любой обзор кода приветствуется).

* tl; dr: Вы можете видеть ошибка очень хорошо, когда вы включаете режим ловли, нажмите на график, а затем нажмите несколько раз на кнопку Печать. Каждый щелчок по кнопке «Печать» добавит в список точек дополнительные координаты. *

Здесь идет код:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button


class ClickCatcher:

    def __init__(self, window_object):
        self.window_object = window_object
        self.fig = self.window_object.fig
        self.ax = self.window_object.ax
        self.window_object.is_click_catcher_working = True

        self.cid = window_object.fig.canvas.mpl_connect('button_press_event', self)
        self.points, = self.ax.plot([], [], marker='.', ls='None', color='red')

        self.data_x = []
        self.data_y = []

    def __call__(self, event):
        if event.button == 1 and event.inaxes:
            self.data_x.append(event.xdata)
            self.data_y.append(event.ydata)
            self.update_plot()
            print('{:8.2f} {:8.2f}'.format(event.xdata, event.ydata))

            self.window_object.click_data = (self.data_x, self.data_y)

    def update_plot(self):
        self.points.set_data(self.data_x, self.data_y)
        self.fig.canvas.draw()


class Window:

    def __init__(self):
        self.is_click_catcher_working = False
        self.click_data = ()

        self.fig, self.ax = plt.subplots()
        self.configure_appearance()
        self._plot, = plt.plot(np.arange(0, 10, 0.1), np.sin(np.arange(0, 10, 0.1)),
                               drawstyle='steps-mid', color='black', lw=1)
        self._add_buttons()

    def configure_appearance(self):
        self.fig.set_size_inches(10, 5)
        self.ax.tick_params(axis='both', labelsize=14)
        self.ax.set_xlabel('Energy (keV)', fontsize=12)
        self.ax.set_ylabel('Number of counts', fontsize=12)
        plt.subplots_adjust(bottom=0.25)

    def _add_buttons(self):
        self.button_mark = Button(plt.axes([0.4, 0.05, 0.1, 0.075]), 'Mark')
        self.button_mark.on_clicked(self.activate_marking)
        self.button_print = Button(plt.axes([0.6, 0.05, 0.1, 0.075]), 'Print')
        self.button_print.on_clicked(self.print_points)

    def catch_coordinates(self):
        click = ClickCatcher(self)

    def activate_marking(self, event):
        if self.is_click_catcher_working:
            pass
        else:
            self.is_click_catcher_working = True
            self.catch_coordinates()

    def print_points(self, event):
        output = '({:.2f}, {:.2f}) ; '*len(self.click_data[0])
        print(output.format(*self.click_data[0], *self.click_data[1]))


if __name__ == '__main__':

    win = Window()
    plt.show()



...