Получить координаты щелчка мышью в классе - python - PullRequest
0 голосов
/ 15 апреля 2020

Я хочу получить координаты щелчка мышью в классе. Я сделал это перед использованием tkinter, но у меня проблемы с интеграцией в более сложный контекст (внутри класса)

Мой текущий код переключается между двумя графиками, и это работает хорошо, однако я хочу иметь возможность получить координаты щелчка мыши на втором графике.

Вот мой код (пытался сделать его минимальным рабочим кодом):

import math
import scipy  as sp
from scipy import signal
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.widgets import Cursor
import tkinter as tk
from matplotlib.widgets import Button

matplotlib.use( 'tkagg' )

from tkinter import *
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler


# make some data:
x_axis = np.arange(0, 10, 0.1)
data = np.sin(x_axis)

zero_crossings = np.where(np.diff(np.sign(data)))[0]
y_axis = [0, 0, 0, 0]


def find_nearest(array, value):
    idx = (np.abs(array-value)).argmin()
    return array[idx]

def config_plot():
    tk, ax = plt.subplots()
    ax.set(title='Count the steps! \n Are there 10 steps??')
    return (tk, ax)


class matplotlibSwitchGraphs:
    def __init__(self, master):
        self.master = master
        self.frame = Frame(self.master)
        self.fig, self.ax = config_plot()
        self.graphIndex = 0
        self.canvas = FigureCanvasTkAgg(self.fig, self.master)  
        self.config_window()
        self.draw_graph_one()
        self.frame.pack(expand=YES, fill=BOTH)

    def config_window(self):
        self.canvas.mpl_connect("key_press_event", self.on_key_press)
        toolbar = NavigationToolbar2Tk(self.canvas, self.master)
        toolbar.update()
        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
        self.button = Button(self.master, text="YES", command=self._quit)
        self.button.pack(side=BOTTOM)
        self.button_switch = Button(self.master, text="NO", command=self.switch_graphs)
        self.button_switch.pack(side=BOTTOM)

    def draw_graph_one(self):
        self.ax.clear() # clear current axes
        self.ax.plot(data)
        self.ax.plot(zero_crossings, y_axis, marker='o', linestyle='none')
        self.ax.set(title='Check the data \n Are the touchdowns and toeoffs in the right spots? \n are there 10 steps?')
        self.canvas.draw()

    def draw_graph_two(self):
        self.ax.clear()
        self.ax.plot(data)
        self.ax.set(title='Instructions: \n 1) click the incorrect step \n 2)Click where it should be')
        self.ax.plot(zero_crossings, y_axis, marker='o', linestyle='none')
        self.canvas.draw()
        #Want to get imput from 2 mouse clicks!!!! 

    def on_key_press(event):
        print("you pressed {}".format(event.key))
        key_press_handler(event, self.canvas, toolbar)

    def _quit(self):
        self.master.quit()  # stops mainloop

    def switch_graphs(self):
        # Need to call the correct draw, whether we're on graph one or two
        self.graphIndex = (self.graphIndex + 1 ) % 2
        if self.graphIndex == 0:
            self.draw_graph_one()
        else:
            self.draw_graph_two()

def main():
    root = Tk()
    matplotlibSwitchGraphs(root)
    root.mainloop()

if __name__ == '__main__':
    main()

В идеале, в конце я хочу первым щелчком удалить один из маркеров (toeoff_cut или touchdown_cut) и для второго щелчка, чтобы поместить его в новое место ... но сейчас было бы просто получить координаты кликов!

Есть идеи? Спасибо!

1 Ответ

0 голосов
/ 15 апреля 2020

Если вы хотите щелкнуть мышью, вам нужно использовать "button_press_event" вместо "key_press_event", который предназначен для клавиш клавиатуры.

self.canvas.mpl_connect("button_press_event", self.on_key_press)

Или вы можете использовать оба - и вы можете назначить разные методы

self.canvas.mpl_connect("key_press_event", self.on_key_press)
self.canvas.mpl_connect("button_press_event", self.on_button_press)

и

def on_button_press(self, event):
    print('-----')
    print('button:', event.button)
    print('xdata, ydata:', event.xdata, event.ydata)
    print('x, y:', event.x, event.y)
    print('canvas:', event.canvas)
    print('inaxes:', event.inaxes)

Дополнительные типы событий вы можете найти в matplotlib.pyplot.connect или Обработка событий

(но мне кажется, что для мыши DoubleClick нет)


Если вы хотите отключить событие, вам нужно сохранить значение, возвращаемое mpl_connect

 # connect

 self.button_press_id = self.canvas.mpl_connect("button_press_event", self.on_button_press)

 # disconnect

 self.canvas.mpl_disconnect(self.button_press_id)

Таким образом, вы можете использовать различные функции для разных участков.


Минимальный рабочий код:

from tkinter import * # PEP8: `import *` is not preferred

import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure


# (not so) random data
import random
random.seed(0) # will give the same values in every execution
Z_filt_1 = [random.randint(0, 100) for _ in range(10)]
Z_filt_2 = [random.randint(0, 100) for _ in range(10)]


class MatPlotLibSwitchGraphs:

    def __init__(self, master):
        self.master = master

        self.frame = Frame(self.master)
        self.frame.pack(expand=YES, fill=BOTH)

        self.fig = Figure(figsize=(5, 4), dpi=100)
        self.ax = self.fig.gca() #config_plot()

        self.canvas = FigureCanvasTkAgg(self.fig, self.master)  
        self.config_window()

        self.graphIndex = 0
        self.draw_graph_one()

    def config_window(self):
        toolbar = NavigationToolbar2Tk(self.canvas, self.master)
        toolbar.update()

        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)

        print('connect')
        self.canvas.mpl_connect("key_press_event", self.on_key_press)
        self.canvas.mpl_connect("button_press_event", self.on_button_press)

        self.button = Button(self.master, text="QUIT", command=self._quit)
        self.button.pack(side=BOTTOM)
        self.button_switch = Button(self.master, text="CHANGE PLOT", command=self.switch_graphs)
        self.button_switch.pack(side=BOTTOM)

    def draw_graph_one(self):
        self.ax.clear()
        self.ax.plot(Z_filt_1)
        self.ax.set(title='First Plot')
        self.canvas.draw()

    def draw_graph_two(self):
        self.ax.clear()
        self.ax.plot(Z_filt_2)
        self.ax.set(title='Second Plot')
        self.canvas.draw()

    def on_key_press(self, event):
        print('key:', event.key)

    def on_button_press(self, event):
        print('-----')
        print('button:', event.button)
        print('xdata, ydata:', event.xdata, event.ydata)
        print('x, y:', event.x, event.y)
        print('canvas:', event.canvas)
        print('inaxes:', event.inaxes)

    def _quit(self):
        #self.master.quit()  # stops mainloop
        self.master.destroy() # works better then `quit()` (at least on Linux)

    def switch_graphs(self):
        # Need to call the correct draw, whether we're on graph one or two
        self.graphIndex = (self.graphIndex + 1 ) % 2
        if self.graphIndex == 0:
            self.draw_graph_one()
        else:
            self.draw_graph_two()

def main():
    root = Tk()
    MatPlotLibSwitchGraphs(root)
    root.mainloop()

if __name__ == '__main__':
    main()

BTW: PEP 8 - - Руководство по стилю для Python Код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...