如何使用具有补丁矩形的艺术家同时移动 2 个 recngale
how use artists with patch rectangle to move 2 retcngale in same time
我在两个缩放面板 1 和缩放面板 2 中使用矩形补丁
这个想法是必须将矩形补丁放入面板中,当我移动 zooom 1 中的矩形时,两个矩形可以同时移动,在缩放面板 2
中同时移动相同区域
如何在这个例子中使用矩形艺术家和 matplotlib
import wx
from numpy import arange, sin, pi,cos
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
class MainFrame(wx.Frame):
def __init__(self, parent ):
wx.Panel.__init__(self, parent,name="Main", size = (800,800))
self.Panel = Panel(self)
class Panel(wx.Panel):
def __init__(self,parent):
super().__init__(parent)
panel = wx.Panel(self)
self.canvas_panel = CanvasPanel(self)
self.zoom_panel=Zoom(parent=self)
self.zoom_panel2=Zoom2(parent=self)
canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel2,1,wx.EXPAND)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel)
sizer.Add(canvas_sizer)
self.SetSizerAndFit(sizer)
self.Show()
class CanvasPanel(wx.Panel):
""" Panel du graphique matplotlib """
def __init__(self, parent , size=(200,350)):
super().__init__(parent)
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
self.Size = self.canvas.Size
self.parent = parent
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 0.02
self.rect = patches.Rectangle((x, y), 0.4,0.4,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.2
zy1 = y1 - 0.2
zx2 = x1 + 0.2
zy2 = y1 + 0.2
self.rect.set_x(x1 - 0.2) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.2) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
self.parent.zoom_panel.Update(self)
self.parent.zoom_panel2.Update(self)
class Zoom(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(200,200))
self.Show()
def Update(self,parent):
#Load axis values of the selected rectangle
zoom_axes=parent.zoom_axes
#duplicate the plot from the main panel
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
#Apply axis of drawn rectangle to the plot
self.axes.axis(zoom_axes)
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 0.01
self.rect = patches.Rectangle((x, y), 0.02, 0.02,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.01
zy1 = y1 - 0.01
zx2 = x1 + 0.01
zy2 = y1 + 0.01
self.rect.set_x(x1 - 0.01) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.01) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
class Zoom2(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(200,200))
self.Show()
def Update(self,parent):
#Load axis values of the selected rectangle
zoom_axes=parent.zoom_axes
#duplicate the plot from the main panel
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
#Apply axis of drawn rectangle to the plot
self.axes.axis(zoom_axes)
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 0.01
self.rect = patches.Rectangle((x, y), 0.02, 0.02,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.add_artist(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.01
zy1 = y1 - 0.01
zx2 = x1 + 0.01
zy2 = y1 + 0.01
self.rect.set_x(x1 - 0.01) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.01) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()
谢谢大家
所做的更改:
- 添加了 2 个 Zoom 面板之间的通信。每个人都可以通过
add_subscriber(subscriber_name, action_to_make)
添加一个订阅者,每次按下其中一个时,它都会呼叫所有 action_to_make(click)
.
- 由于 Zoom 和 Zoom2 基本上是相同 class 的两个实例(具有相同的代码)我删除了第二个 class 的定义并制作了
zoom_panel
和 zoom_panel2
相同 class. 的不同实例
- 将 Zoom 更改为仅实例化 Figure 和 Rectangle 等所有实例并更新它们,而不是创建新实例并将其放在旧实例之上。
import wx
from numpy import arange, sin, pi,cos
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
class MainFrame(wx.Frame):
def __init__(self, parent ):
wx.Panel.__init__(self, parent,name="Main", size = (1000,800))
self.Panel = Panel(self)
class Panel(wx.Panel):
def __init__(self,parent):
super().__init__(parent)
panel = wx.Panel(self)
self.canvas_panel = CanvasPanel(self)
self.zoom_panel=Zoom(parent=self)
self.zoom_panel2=Zoom(parent=self)
self.zoom_panel.add_subscriber("zoom_panel2", self.zoom_panel2.on_notified)
self.zoom_panel2.add_subscriber("zoom_panel", self.zoom_panel.on_notified)
canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel2,1,wx.EXPAND)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel)
sizer.Add(canvas_sizer)
self.SetSizerAndFit(sizer)
self.Show()
class CanvasPanel(wx.Panel):
""" Panel du graphique matplotlib """
def __init__(self, parent , size=(200,350)):
super().__init__(parent)
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
self.Size = self.canvas.Size
self.parent = parent
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = -0.2
self.rect = patches.Rectangle((x, y), 0.4,0.4,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.2
zy1 = y1 - 0.2
zx2 = x1 + 0.2
zy2 = y1 + 0.2
self.rect.set_x(x1 - 0.2) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.2) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
self.parent.zoom_panel.Update(self)
self.parent.zoom_panel2.Update(self)
class Zoom(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(200,200))
self.Show()
self.subscriber_list = {}
#init figure&canvas
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.axes.axis([-0.2,0.2,-0.2,0.2]) # set default display window
self.canvas.mpl_connect('button_press_event', self.on_press)
#add rectangle
x = y = 0.01
self.rect = patches.Rectangle((x, y), 0.02, 0.02,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
#first display
self.axes.plot()
self.canvas.draw()
def Update(self,parent):
#Load axis values of the selected rectangle
zoom_axes=parent.zoom_axes
#clear Axes
self.axes.clear()
#Apply axis of drawn rectangle to the plot
self.axes.axis(zoom_axes)
#draw same plot as on the main panel
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s, 'C0')
#draw rectangle
self.axes.add_patch(self.rect)
#display
self.axes.plot()
self.canvas.draw()
def on_press(self, click):
self.perform_press(click)
self.notify_subscribers(click)
def perform_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.01
zy1 = y1 - 0.01
zx2 = x1 + 0.01
zy2 = y1 + 0.01
self.rect.set_x(x1 - 0.01) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.01) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
def notify_subscribers(self, click):
for subscriber in self.subscriber_list:
self.subscriber_list.get(subscriber)(click)
# adds a new subscriber to the list. "name" is a subscriber identifier, "action" is called as "action(name)" every time this element is clicked
def add_subscriber(self, name, action):
self.subscriber_list[name]=action
def on_notified(self, click):
#Do something here
#print("Zoom received notification from Zoom2: ", click)
self.perform_press(click)
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()
我在两个缩放面板 1 和缩放面板 2 中使用矩形补丁 这个想法是必须将矩形补丁放入面板中,当我移动 zooom 1 中的矩形时,两个矩形可以同时移动,在缩放面板 2
中同时移动相同区域如何在这个例子中使用矩形艺术家和 matplotlib
import wx
from numpy import arange, sin, pi,cos
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
class MainFrame(wx.Frame):
def __init__(self, parent ):
wx.Panel.__init__(self, parent,name="Main", size = (800,800))
self.Panel = Panel(self)
class Panel(wx.Panel):
def __init__(self,parent):
super().__init__(parent)
panel = wx.Panel(self)
self.canvas_panel = CanvasPanel(self)
self.zoom_panel=Zoom(parent=self)
self.zoom_panel2=Zoom2(parent=self)
canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel2,1,wx.EXPAND)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel)
sizer.Add(canvas_sizer)
self.SetSizerAndFit(sizer)
self.Show()
class CanvasPanel(wx.Panel):
""" Panel du graphique matplotlib """
def __init__(self, parent , size=(200,350)):
super().__init__(parent)
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
self.Size = self.canvas.Size
self.parent = parent
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 0.02
self.rect = patches.Rectangle((x, y), 0.4,0.4,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.2
zy1 = y1 - 0.2
zx2 = x1 + 0.2
zy2 = y1 + 0.2
self.rect.set_x(x1 - 0.2) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.2) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
self.parent.zoom_panel.Update(self)
self.parent.zoom_panel2.Update(self)
class Zoom(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(200,200))
self.Show()
def Update(self,parent):
#Load axis values of the selected rectangle
zoom_axes=parent.zoom_axes
#duplicate the plot from the main panel
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
#Apply axis of drawn rectangle to the plot
self.axes.axis(zoom_axes)
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 0.01
self.rect = patches.Rectangle((x, y), 0.02, 0.02,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.01
zy1 = y1 - 0.01
zx2 = x1 + 0.01
zy2 = y1 + 0.01
self.rect.set_x(x1 - 0.01) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.01) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
class Zoom2(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(200,200))
self.Show()
def Update(self,parent):
#Load axis values of the selected rectangle
zoom_axes=parent.zoom_axes
#duplicate the plot from the main panel
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
#Apply axis of drawn rectangle to the plot
self.axes.axis(zoom_axes)
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 0.01
self.rect = patches.Rectangle((x, y), 0.02, 0.02,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.add_artist(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.01
zy1 = y1 - 0.01
zx2 = x1 + 0.01
zy2 = y1 + 0.01
self.rect.set_x(x1 - 0.01) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.01) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()
谢谢大家
所做的更改:
- 添加了 2 个 Zoom 面板之间的通信。每个人都可以通过
add_subscriber(subscriber_name, action_to_make)
添加一个订阅者,每次按下其中一个时,它都会呼叫所有action_to_make(click)
. - 由于 Zoom 和 Zoom2 基本上是相同 class 的两个实例(具有相同的代码)我删除了第二个 class 的定义并制作了
zoom_panel
和zoom_panel2
相同 class. 的不同实例
- 将 Zoom 更改为仅实例化 Figure 和 Rectangle 等所有实例并更新它们,而不是创建新实例并将其放在旧实例之上。
import wx
from numpy import arange, sin, pi,cos
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
class MainFrame(wx.Frame):
def __init__(self, parent ):
wx.Panel.__init__(self, parent,name="Main", size = (1000,800))
self.Panel = Panel(self)
class Panel(wx.Panel):
def __init__(self,parent):
super().__init__(parent)
panel = wx.Panel(self)
self.canvas_panel = CanvasPanel(self)
self.zoom_panel=Zoom(parent=self)
self.zoom_panel2=Zoom(parent=self)
self.zoom_panel.add_subscriber("zoom_panel2", self.zoom_panel2.on_notified)
self.zoom_panel2.add_subscriber("zoom_panel", self.zoom_panel.on_notified)
canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel,1,wx.EXPAND)
canvas_sizer.Add(self.zoom_panel2,1,wx.EXPAND)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel)
sizer.Add(canvas_sizer)
self.SetSizerAndFit(sizer)
self.Show()
class CanvasPanel(wx.Panel):
""" Panel du graphique matplotlib """
def __init__(self, parent , size=(200,350)):
super().__init__(parent)
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
self.Size = self.canvas.Size
self.parent = parent
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = -0.2
self.rect = patches.Rectangle((x, y), 0.4,0.4,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.2
zy1 = y1 - 0.2
zx2 = x1 + 0.2
zy2 = y1 + 0.2
self.rect.set_x(x1 - 0.2) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.2) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
self.parent.zoom_panel.Update(self)
self.parent.zoom_panel2.Update(self)
class Zoom(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(200,200))
self.Show()
self.subscriber_list = {}
#init figure&canvas
self.figure = Figure(figsize =(4,4))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.axes.axis([-0.2,0.2,-0.2,0.2]) # set default display window
self.canvas.mpl_connect('button_press_event', self.on_press)
#add rectangle
x = y = 0.01
self.rect = patches.Rectangle((x, y), 0.02, 0.02,edgecolor='g', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
#first display
self.axes.plot()
self.canvas.draw()
def Update(self,parent):
#Load axis values of the selected rectangle
zoom_axes=parent.zoom_axes
#clear Axes
self.axes.clear()
#Apply axis of drawn rectangle to the plot
self.axes.axis(zoom_axes)
#draw same plot as on the main panel
t = arange(0.5, 3.0, 0.01)
s = cos(2 * pi * t)
self.axes.plot(t, s, 'C0')
#draw rectangle
self.axes.add_patch(self.rect)
#display
self.axes.plot()
self.canvas.draw()
def on_press(self, click):
self.perform_press(click)
self.notify_subscribers(click)
def perform_press(self, click):
x1, y1 = click.xdata, click.ydata
zx1 = x1 - 0.01
zy1 = y1 - 0.01
zx2 = x1 + 0.01
zy2 = y1 + 0.01
self.rect.set_x(x1 - 0.01) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 0.01) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
self.zoom_axes=[zx1,zx2,zy1,zy2]
def notify_subscribers(self, click):
for subscriber in self.subscriber_list:
self.subscriber_list.get(subscriber)(click)
# adds a new subscriber to the list. "name" is a subscriber identifier, "action" is called as "action(name)" every time this element is clicked
def add_subscriber(self, name, action):
self.subscriber_list[name]=action
def on_notified(self, click):
#Do something here
#print("Zoom received notification from Zoom2: ", click)
self.perform_press(click)
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()