I am quite new to here, please bare with me.
with "show polygon button", I generated 2 Matplotlib plots in my thinker canvas including a polygon plot and a scatter plot.
I want to have a 2 separate mouse pick events to get coordinates from polygon(in blue) and scatter points(in orange).
They(Pick events) seem working along but get an error when I try to run both at once since Matplotlib picker events interfering with other.
I appreciate your help.
Code is given below:
import numpy as np
import pandas as pd
from pandastable import Table
from shapely.geometry import Polygon
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import ttk as ttk
matplotlib.use('TkAgg')
root = tk.Tk()
root.geometry('700x400')
root.state('zoomed')
df2 = pd.DataFrame({
'x': [0,100,100,-100,-100,0,],
'y': [0,0,500,500,0,0,],
})
df= pd.DataFrame()
frame = tk.Frame(root)
frame.place(x=500, y=500)
pt = Table(frame, dataframe=df, width=150,height=400)
pt.show()
class App():
def __init__(self, master):
self.master = master
self.points = []
self.pointSelect = None
self.dotSelect=None
# Frame
self.frame =tk.Frame(master, width=400, height =950,highlightbackground="blue", highlightthickness=5)
self.frame.place(x=10, y=40)
# button
self.button = tk.Button(self.frame,text = "Show Polygon", command=self.plot_section, width =15, height =2 )
self.button.place (x=30, y=150)
def plot_section(self):
pt.model.df = df2 # writing into pd data frame
pt.redraw()
poly_new=list(tuple(map(tuple,np.asarray(df2))))
print(poly_new)
polygon2 = Polygon(poly_new)
self.x,self.y = polygon2.exterior.xy
fig.clear()
ax=fig.add_subplot(111)
self.x2=(0,50)
self.y2=(110,110)
ax.plot(self.x,self.y, color ='blue',picker=True, pickradius=5)
ax.scatter(self.x2, self.y2, s=32, color ='orange',picker=True)
canvas.draw_idle()
print(pt.model.df)
def onpick(event):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
print(xdata[ind][0] )
self.points=[]
self.points.append([xdata[ind][0], ydata[ind][0]])
print('this point click on polygon', self.points)
def onpick2(event):
#This function is called whenever a point on the Tkinter Canvas is Clicked
index = event.ind
xy = event.artist.get_offsets()
print ('hi scatter',xy[index])
self.pointSelect=fig.canvas.mpl_connect('pick_event', onpick)
self.dotSelects=fig.canvas.mpl_connect('pick_event', onpick2)
fig = Figure(figsize=(8,6), dpi=100)
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.RIGHT)
app = App(root)
root.mainloop()
Error message 1: (most recent call last): File "C:\Users\xxx\Anaconda3\envs\pls\lib\site-packages\matplotlib\cbook_init_.py", line 287, in process func(*args, **kwargs) File "C:\Users\xxx\AppData\Local\Temp\ipykernel_39168\1909536620.py", line 77, in onpick xdata = thisline.get_xdata() AttributeError: 'PathCollection' object has no attribute 'get_xdata'
Error message 2: (most recent call last): File "C:\Users\xxxxx\lib\site-packages\matplotlib\cbook_init_.py", line 287, in process func(*args, **kwargs) File "C:\Users\xxxx\AppData\Local\Temp\ipykernel_39168\1909536620.py", line 89, in onpick2 xy = event.artist.get_offsets() AttributeError: 'Line2D' object has no attribute 'get_offsets'
CodePudding user response:
event
doesn't care what you clicked. It runs both functions when you click object on canvas.
And different objects have different functions and you should check instance
of event.artist
to run correct code for clicked object.
def onpick(event):
print('onpick', event.artist)
if isinstance(event.artist, matplotlib.lines.Line2D):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
print(xdata[ind][0])
self.points = []
self.points.append([xdata[ind][0], ydata[ind][0]])
print('this point click on polygon', self.points)
def onpick2(event):
print('onpick2', event.artist)
if isinstance(event.artist, matplotlib.collections.PathCollection):
index = event.ind
xy = event.artist.get_offsets()
print ('hi scatter', xy[index])
You can even put all in one function.
def onpick(event):
print('onpick', event.artist)
if isinstance(event.artist, matplotlib.lines.Line2D):
thisline = event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
ind = event.ind
print(xdata[ind][0])
self.points = []
self.points.append([xdata[ind][0], ydata[ind][0]])
print('this point click on polygon', self.points)
if isinstance(event.artist, matplotlib.collections.PathCollection):
index = event.ind
xy = event.artist.get_offsets()
print ('hi scatter', xy[index])