i need to define 2 rectangleselector that moves at the same time and in same region, when i move one another moves at the same time how i can do that ?
that is a simple code with 2 plot in 2 panel and 2 rectangle
is possible to make the two rectangle move in the same time cause i didn't find any exemple for that in the web or in matplotlib
i use wxpython 4 for python3.6
import wx
from numpy import arange, sin, pi,cos
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.widgets import RectangleSelector
from matplotlib.figure import Figure
class MainFrame(wx.Frame):
def __init__(self, parent ):
wx.Panel.__init__(self, parent,name="Main", size = (600,800))
Top = PanelTop(self)
Bottom = PanelBottom(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(Top, 1, wx.EXPAND)
sizer.Add(Bottom, 1, wx.EXPAND)
self.SetSizer(sizer)
class PanelTop(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size = (300,300))
self.SetBackgroundColour('white')
self.figure = Figure(figsize = (4,5))
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self,-1,self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.RS = RectangleSelector(self.axes,self.line_select_callback,
drawtype='box', useblit=False,
button=[1, 3],minspanx=1, minspany=1,
spancoords='pixels',
interactive=True, rectprops = dict(facecolor='None',edgecolor='red',alpha=5,fill=False))
self.RS.to_draw.set_visible(True)
self.RS.extents = (1,0,0,1)
def line_select_callback(self, eclick, erelease):
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
class PanelBottom(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self, parent, size = (300,300))
self.SetBackgroundColour('grey77')
self.figure = Figure(figsize = (4,5))
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self,-1,self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
t = arange(0.0, 3.0, 0.01)
s = sin(2 * pi * t)
self.axes.plot(t, s)
self.RS = RectangleSelector(self.axes,self.line_select_callback,
drawtype='box', useblit=False,
button=[1, 3],minspanx=1, minspany=1,
spancoords='pixels',
interactive=True, rectprops = dict(facecolor='None',edgecolor='red',alpha=5,fill=False))
self.RS.to_draw.set_visible(True)
self.RS.extents = (1,0,0,1)
def line_select_callback(self, eclick, erelease):
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()
thank you in advance
I have no idea if this is the way that it should be done but here is one way.
I've commented the code where appropriate.
The method simply grubs the cordinates of the first Rectangle forces them into the second and then redraws it.
The second rectangle is made Inactive as it is meant to be a slave of the first and
if it isn't inactive, the control points at the corners and middle, fail to move with the rectangle. This leads me to believe that there may be a less hacky way of achieving the same result.
import wx
from numpy import arange, sin, pi,cos
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.widgets import RectangleSelector
from matplotlib.figure import Figure
class MainFrame(wx.Frame):
def __init__(self, parent ):
wx.Panel.__init__(self, parent,name="Main", size = (600,800))
self.Top = PanelTop(self)
self.Bottom = PanelBottom(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.Top, 1, wx.EXPAND)
sizer.Add(self.Bottom, 1, wx.EXPAND)
self.SetSizer(sizer)
class PanelTop(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size = (300,300))
self.SetBackgroundColour('white')
self.figure = Figure(figsize = (4,5))
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self,-1,self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.RS = RectangleSelector(self.axes,self.line_select_callback,
drawtype='box', useblit=False,
button=[1, 3],minspanx=1, minspany=1,
spancoords='pixels',
interactive=True, rectprops = dict(facecolor='None',edgecolor='red',alpha=5,fill=False))
self.RS.to_draw.set_visible(True)
self.RS.extents = (1,0,0,1)
def line_select_callback(self, eclick, erelease):
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
rect = self.RS.artists[0] # Rectangle artist
slave_rect = self.Parent.Bottom.RS.artists[0] # Rectangle artist
slave_canvas = self.Parent.Bottom.canvas
# Force new positional values into slave rectangle
slave_rect.set_x(x1)
slave_rect.set_y(y1)
slave_rect.set_width(x2-x1)
slave_rect.set_height(y2-y1)
slave_rect.update(dict(facecolor='None',edgecolor='red',alpha=5,fill=False))
#Force visible in case slave rectangle has been clicked on
slave_rect.set_visible(True)
#Redraw slave rectangle
slave_canvas.draw()
class PanelBottom(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self, parent, size = (300,300))
self.SetBackgroundColour('grey77')
self.figure = Figure(figsize = (4,5))
self.axes = self.figure.add_subplot(111)
self.canvas = FigureCanvas(self,-1,self.figure)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
t = arange(0.0, 3.0, 0.01)
s = sin(2 * pi * t)
self.axes.plot(t, s)
self.RS = RectangleSelector(self.axes,self.line_select_callback,
drawtype='box', useblit=False,
button=[1, 3],minspanx=1, minspany=1,
spancoords='pixels',
interactive=False, rectprops = dict(facecolor='None',edgecolor='red',alpha=5,fill=False))
self.RS.to_draw.set_visible(True)
self.RS.extents = (1,0,0,1)
def line_select_callback(self, eclick, erelease):
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()