当我添加矩形选择器但单击后无法移动时,我有了应用程序 我需要在其他框架中绘制矩形内的区域,我该怎么做? 我认为我的代码中有问题,矩形无法在情节中移动,我无法移动! 在我如何绘制其他框架中选择的区域之后?
谢谢大家
import wx
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.widgets import RectangleSelector
import matplotlib
import matplotlib.pyplot as plt
import netCDF4
def line_select_callback(eclick, erelease):
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2))
#print(" The button you used were: %s %s" % (eclick.button, erelease.button))
class Window(wx.Frame):
def __init__(self, **kwargs):
super().__init__(None, **kwargs)
RootPanel(self)
class RootPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
panel_buttons = wx.Panel(self)
panel_buttons_sizer = wx.GridSizer(1, 2, 0, 0)
canvas_panel = CanvasPanel(self)
select_button = PickButton(
panel_buttons,
"netCDF4 files (nc)|*.nc",
canvas_panel.load_from_file,
label="Show on this window (nc)",
)
toplevel_select_button = TopLevelPickButton(
panel_buttons,
"Text files (txt)|*.txt|All files|*.*",
label="Show on separate window (txt)",
)
panel_buttons_sizer.Add(select_button)
panel_buttons_sizer.Add(toplevel_select_button)
panel_buttons.SetSizer(panel_buttons_sizer)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel_buttons)
sizer.Add(canvas_panel)
self.SetSizer(sizer)
class PickButton(wx.Button):
def __init__(self, parent, wildcard, func, **kwargs):
# func est la méthode à laquelle devra être foruni le fichier sélectionné
super().__init__(parent, **kwargs)
self.wildcard = wildcard
self.func = func
self.Bind(wx.EVT_BUTTON, self.pick_file)
def pick_file(self, evt):
style = style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
with wx.FileDialog(
self, "Pick files", wildcard=self.wildcard, style=style
) as fileDialog:
if fileDialog.ShowModal() != wx.ID_CANCEL:
chosen_file = fileDialog.GetPath()
self.func(chosen_file)
class TopLevelPickButton(PickButton):
def __init__(self, parent, wildcard, **kwargs):
super().__init__(parent, wildcard, self.create_toplevel, **kwargs)
def create_toplevel(self, file_name):
""" Ouvre une toplevel et affiche le graphique """
self.win = TopLevelCanvas(self.Parent)
self.win.canvas_panel.load_from_file(file_name)
self.win.Show()
class CanvasPanel(wx.Panel):
def __init__(self, parent , size=(200,250)):
super().__init__(parent)
self.figure = Figure(figsize =(8,7))
self.canvas = FigureCanvas(self, -1, self.figure)
self.Size = self.canvas.Size
def load_from_file(self, file_name):
"""
son type
"""
self.axes = self.figure.add_subplot(111)
if file_name.endswith(".nc"):
self._load_nc(file_name)
else:
self._load_txt(file_name)
self.canvas.draw()
#print(" The button you used were: %s %s" % (eclick.button, erelease.button))
def _load_nc(self, file_name):
t = np.arange(0.0, 8.0, 0.01)
s = np.sin(3 * np.pi * t)
self.axes.plot(t, s)
# drawtype is 'box' or 'line' or 'none'
RS = RectangleSelector(self.axes,line_select_callback,
drawtype='box', useblit=False,
button=[3],
minspanx=5, minspany=5,
spancoords='pixels',
interactive=True)
RS.to_draw.set_visible(True)
RS.extents = (1,20,1,15)
self.figure.canvas.draw()
plt.show()
class TopLevelCanvas(wx.Frame):
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.canvas_panel = CanvasPanel(self)
self.Size = self.canvas_panel.Size
class App(wx.App):
def OnInit(self):
win = Window(title="A test dialog", size=(1000, 800))
win.Show()
return True
if __name__ == "__main__":
app = App()
app.MainLoop()
答案 0 :(得分:1)
通过拖动矩形中间的方框移动矩形。
我确定matplotlib
有很多方法可以在另一个绘图中绘制选定的矩形,这是一种手动缩放,但无论如何我都不是matplotlib
专家。
下面的方法通过存储矩形选择的轴,然后调用一个新框架来实现我认为的目标,在该框架中重复绘制但具有调整后的轴。
新框架在失去焦点时会自动取消,因此您不会最终遇到多个Zoom
窗口。
希望对您有帮助!
import wx
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.widgets import RectangleSelector
import matplotlib
class Window(wx.Frame):
""" Fenêtre principale de l'application """
def __init__(self, **kwargs):
super().__init__(None, **kwargs)
RootPanel(self)
class RootPanel(wx.Panel):
""" Panel contenant tous les autres widgets de l'application """
def __init__(self, parent):
super().__init__(parent)
panel_buttons = wx.Panel(self)
panel_buttons_sizer = wx.GridSizer(1, 2, 0, 0)
canvas_panel = CanvasPanel(self)
select_button = PickButton(
panel_buttons,
"netCDF4 files (nc)|*.nc",
canvas_panel.load_from_file,
label="Show on this window (nc)",
)
toplevel_select_button = TopLevelPickButton(
panel_buttons,
"Text files (txt)|*.txt|All files|*.*",
label="Show on separate window (txt)",
)
panel_buttons_sizer.Add(select_button)
panel_buttons_sizer.Add(toplevel_select_button)
panel_buttons.SetSizer(panel_buttons_sizer)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panel_buttons)
sizer.Add(canvas_panel)
self.SetSizer(sizer)
class PickButton(wx.Button):
""" Bouton permettant de choisir un fichier """
def __init__(self, parent, wildcard, func, **kwargs):
# func est la méthode à laquelle devra être foruni le fichier sélectionné
super().__init__(parent, **kwargs)
self.wildcard = wildcard
self.func = func
self.Bind(wx.EVT_BUTTON, self.pick_file)
def pick_file(self, evt):
style = style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_MULTIPLE
with wx.FileDialog(
self, "Pick files", wildcard=self.wildcard, style=style
) as fileDialog:
if fileDialog.ShowModal() != wx.ID_CANCEL:
chosen_file = fileDialog.GetPath()
self.func(chosen_file)
class TopLevelPickButton(PickButton):
""" Permet de choisir un fichier et d'ouvrir une toplevel """
def __init__(self, parent, wildcard, **kwargs):
super().__init__(parent, wildcard, self.create_toplevel, **kwargs)
def create_toplevel(self, file_name):
""" Ouvre une toplevel et affiche le graphique """
self.win = TopLevelCanvas(self.Parent)
self.win.canvas_panel.load_from_file(file_name)
self.win.Show()
class CanvasPanel(wx.Panel):
""" Panel du graphique matplotlib """
def __init__(self, parent , size=(200,250)):
super().__init__(parent)
self.figure = Figure(figsize =(8,7))
self.canvas = FigureCanvas(self, -1, self.figure)
self.Size = self.canvas.Size
self.zoom_axis = []
def load_from_file(self, file_name):
"""
Méthode effectuant l'intermédiaire pour charger le fichier selon
son type
"""
self.axes = self.figure.add_subplot(111)
if file_name.endswith(".nc"):
self._load_nc(file_name)
else:
self._load_txt(file_name)
self.canvas.draw()
def _load_txt(self, file_name):
self._load_nc(file_name)
def _load_nc(self, file_name):
""" Simule le chargement et affichage à partir d'un fichier nc """
t = np.arange(0.0, 8.0, 0.01)
s = np.sin(3 * np.pi * t)
self.axes.plot(t, s)
# drawtype is 'box' or 'line' or 'none'
self.RS = RectangleSelector(self.axes,self.line_select_callback,
drawtype='box', useblit=True,
button=[1, 3],minspanx=5, minspany=5,
spancoords='pixels',
interactive=True, rectprops = dict(facecolor='None',edgecolor='red',alpha=5,fill=False))
#self.RS.to_draw.set_visible(True)
#self.figure.canvas.draw()
#self.RS.extents = (0,1,0,1)
def line_select_callback(self, eclick, erelease):
'eclick and erelease are the press and release events'
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
self.zoom_axis=[x1,x2,y1,y2]
Zoom(parent=self)
class Zoom(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,-1,("Zoom"))
self.parent = parent
#Make this zoom window self cancelling if it loses focus
self.Bind(wx.EVT_ACTIVATE, self.OnExit)
#Load axis values of the selected rectangle
zoom_axis=parent.zoom_axis
#duplicate the plot from the main panel
self.figure = Figure(figsize =(8,7))
self.canvas = FigureCanvas(self, -1, self.figure)
self.axes = self.figure.add_subplot(111)
""" Simule le chargement et affichage à partir d'un fichier nc """
t = np.arange(0.0, 8.0, 0.01)
s = np.sin(3 * np.pi * t)
#Apply axis of drawn rectangle to the plot
self.axes.axis(zoom_axis)
self.axes.plot(t, s)
self.canvas.draw()
self.Show()
def OnExit(self, event):
focus = event.GetActive()
if focus == False: # Window lost focus
self.Close()
class TopLevelCanvas(wx.Frame):
""" Fenêtre affichant uniquement un graph matplotlib """
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.canvas_panel = CanvasPanel(self)
self.Size = self.canvas_panel.Size
class App(wx.App):
def OnInit(self):
win = Window(title="A test dialog", size=(1000, 800))
win.Show()
return True
if __name__ == "__main__":
app = App()
app.MainLoop()