在矩形类zoom(wx.frame)中选择区域时发生错误

时间:2019-04-28 10:40:38

标签: python-3.x matplotlib wxpython

在获得有关矩形选择器内绘图区域的帮助后,我工作了,但是当我在某些代码应用中应用时,出现了类似错误:

Traceback (most recent call last):
  File "C:\Users\majdoulina\Anaconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 215, in process
    func(*args, **kwargs)
  File "C:\Users\majdoulina\Anaconda3\lib\site-packages\matplotlib\widgets.py", line 1597, in release
    self._release(event)
  File "C:\Users\majdoulina\Anaconda3\lib\site-packages\matplotlib\widgets.py", line 2194, in _release
    self.onselect(self.eventpress, self.eventrelease)
TypeError: line_select_callback() missing 1 required positional argument: 'erelease'

我不知道为什么它不能在我的应用程序中运行class(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
import matplotlib.pyplot as plt
import os



class MainFrame(wx.Frame):
    def __init__(self, parent ):
        super().__init__(parent,title= "quick",size = (2000,1000))

        left = LeftPanel(self)
        middle = MiddlePanel(self)
        right = RightPanel(self)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(left, 3, wx.EXPAND)
        sizer.Add(middle, 5, wx.EXPAND)
        sizer.Add(right, 5, wx.EXPAND)
        self.SetSizer(sizer)


# ------------ LEFT ------------

class LeftPanelTop(wx.Panel):
    def __init__(self, parent,size = (610,350)):
        super().__init__(parent)
        self.figure = Figure(figsize =(5,3))
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.Size = self.canvas.Size
        self.zoom_axes = []




    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_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)


        self.RS = RectangleSelector(self.axes,line_select_callback,
                                       drawtype='box', useblit=False,
                                       button=[1, 3],minspanx=5, minspany=5,
                                       spancoords='pixels',
                                       interactive=True, rectprops = dict(facecolor='None',edgecolor='red',alpha=5,fill=False))


def line_select_callback(self,eclick, erelease):
    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

        #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 =(5,6))
        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.pcolormesh(air_dep,cmap=plt.get_cmap('binary'))
        self.canvas.draw()
        self.show()

    def OnExit(self, event):
        focus = event.GetActive()
        if focus == True : # Window lost focus
            self.Close()


class LeftPanelBottom(wx.Panel):
     def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER,size = (510,450) )
        self.SetBackgroundColour('snow2')
        panel_buttons = wx.Panel(self)
        canvas_panel = LeftPanelTop(self)
        panel_buttons_sizer = wx.GridSizer(1, 2, 0, 0)
        select_button = PickButton(
            panel_buttons,
            "netCDF4 files (nc)|*.nc",
            canvas_panel.load_from_file,
            label="Open file",)
        panel_buttons_sizer.Add(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 = 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 LeftPanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER)

        top = LeftPanelTop(self)
        bottom = LeftPanelBottom(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(top, 3, wx.EXPAND)
        sizer.Add(bottom, 4, wx.EXPAND)

        self.SetSizer(sizer)

# ------------ MIDDLE ------------

class MiddlePanelTop(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER)
        self.SetBackgroundColour('black')
        canal=wx.Button(self,-1,label ="Variable",size=(140,30),pos=(100,0))
        dynamique=wx.Button(self,-1,"Dynamique",size=(140,30),pos=(240,0))
        file = wx.Button(self,-1,"File", size = (110,30),pos=(0,0))
        dynamique.SetBackgroundColour('white')

        canal.SetBackgroundColour('white')
        file.SetBackgroundColour('white')
        dynamique.Bind(wx.EVT_BUTTON, self.OnClick)
        file.Bind(wx.EVT_BUTTON, self.onOpen)

    def onOpen(self, event):
        wildcard = "netCDF4 files (*.nc)|*.nc"
        dialog = wx.FileDialog(self, "Open netCDF4 Files", wildcard=wildcard,
                               style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)

        if dialog.ShowModal() == wx.ID_CANCEL:
            return


        path = dialog.GetPath()

        if os.path.exists(path):
            with open(path) as fobj:
                for line in fobj:
                    self.my_text.WriteText(line)

    def OnClick(self,event):
        dlg = wx.TextEntryDialog(self, 'Enter Dynamique of image','Dynamique de image') 

        if dlg.ShowModal() == wx.ID_OK: 
         self.text.SetValue("Dynamique:"+dlg.GetValue()) 
        dlg.Destroy()


class MiddlePanelBottom(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER)
        self.SetBackgroundColour('black')
        canal=wx.Button(self,-1,"Variable",size=(140,30),pos=(100,0))
        dynamique=wx.Button(self,-1,"Dynamique",size=(140,30),pos=(240,0))
        file = wx.Button(self,-1,"File", size = (110,30),pos=(0,0))
        dynamique.SetBackgroundColour('white')
        canal.SetBackgroundColour('white')
        file.SetBackgroundColour('white')
        dynamique.Bind(wx.EVT_BUTTON, self.OnClick)
        file.Bind(wx.EVT_BUTTON, self.onOpen)
        self.load_options = "netCDF4 files (nc)|*.nc| Text files (txt) |*.txt| All files |*.*"

    def onOpen(self, event):
        wildcard = "netCDF4 files (*.nc)|*.nc"
        dialog = wx.FileDialog(self, "Open netCDF4 Files", wildcard=wildcard,
                               style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)

        if dialog.ShowModal() == wx.ID_CANCEL:
            return
        path = dialog.GetPath()

        if os.path.exists(path):
            with open(path) as fobj:
                for line in fobj:
                    self.my_text.WriteText(line)

    def OnClick(self,event):
        dlg = wx.TextEntryDialog(self, 'Enter Dynamique of image','Dynamique de image') 

        if dlg.ShowModal() == wx.ID_OK: 
         self.text.SetValue("Dynamique:"+dlg.GetValue()) 
        dlg.Destroy()


class MiddlePanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent)

        top = MiddlePanelTop(self)
        bottom = MiddlePanelBottom(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(top, 2, wx.EXPAND)
        sizer.Add(bottom, 2, wx.EXPAND)
        self.SetSizer(sizer)


# ------------ RIGHT ------------

class RightPanelTop(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent)
        self.SetBackgroundColour('black')
        canal=wx.Button(self,-1,"Variable",size=(140,30),pos=(100,0))
        dynamique=wx.Button(self,-1,"Dynamique",size=(140,30),pos=(240,0))
        file = wx.Button(self,-1,"File", size = (110,30),pos=(0,0))
        dynamique.SetBackgroundColour('white')
        canal.SetBackgroundColour('white')
        file.SetBackgroundColour('white')
        dynamique.Bind(wx.EVT_BUTTON, self.OnClick)
        file.Bind(wx.EVT_BUTTON, self.onOpen)

    def onOpen(self, event):
        wildcard = "netCDF4 files (*.nc)|*.nc| HDF5 files (*.h5) |*.h5"
        dialog = wx.FileDialog(self, "Open netCDF4 Files| HDF5 files", wildcard=wildcard,
                               style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)

        if dialog.ShowModal() == wx.ID_CANCEL:
            return

        path = dialog.GetPath()

        if os.path.exists(path):
            with open(path) as fobj:
                for line in fobj:
                    self.my_text.WriteText(line)

    def OnClick(self,event):
        dlg = wx.TextEntryDialog(self, 'Enter Dynamique of image','Dynamique de image') 

        if dlg.ShowModal() == wx.ID_OK: 
         self.text.SetValue("Dynamique:"+dlg.GetValue()) 
        dlg.Destroy()

class RightPanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER)

        top = RightPanelTop(self)
        bottom = RightPanelBottom(self)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(top, 2, wx.EXPAND)
        sizer.Add(bottom, 2, wx.EXPAND)
        self.SetSizer(sizer)

class PanelBottom(wx.Panel):
    def __init__(self,parent):
        super().__init__(parent)
        self.SetBackgroundColour('grey77')
class PanelTop(wx.Panel):
    def __init__(self,parent):
        super().__init__(parent)
        left = SubPanelLeft(self)
        right = SubPanelRight(self)
        midlle = SubPanelMiddle(self)
        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        sizer1.Add(left, 1, wx.EXPAND)
        sizer1.Add(midlle, 1, wx.EXPAND)
        sizer1.Add(right, 1, wx.EXPAND)

        self.SetSizer(sizer1)

class RightPanelBottom(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent)
        self.SetBackgroundColour('snow2')

        top = PanelTop(self)
        bottom = PanelBottom(self)
        sizer1 = wx.BoxSizer(wx.VERTICAL)
        sizer1.Add(top, 2, wx.EXPAND)
        sizer1.Add(bottom, 4, wx.EXPAND)
        self.SetSizer(sizer1)


class SubPanelLeft(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER)
        self.SetBackgroundColour('black')

class SubPanelMiddle(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER)
        self.SetBackgroundColour('black')

class SubPanelRight(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent,style = wx.SUNKEN_BORDER)
        self.SetBackgroundColour('black')




app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()

1 个答案:

答案 0 :(得分:1)

要重新安排代码中的内容以使用panel而不是新的frame。尽管仅根据程序用户的需要创建新框架,而现有panel必须存在,无论是否需要!

我已经重新排列了先前的答案,以在另一个面板中显示zoom,但是为了我的生命,我不明白为什么您不利用内置的matplotlib工具栏使用NavigationToolbar2Wx

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)

        self.canvas_panel = CanvasPanel(self)
        self.zoom_panel = Zoom(parent=self)

        select_button = PickButton(
            panel_buttons,
            "netCDF4 files (nc)|*.nc",
            self.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)

        canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
        canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
        canvas_sizer.Add(self.zoom_panel,1,wx.EXPAND)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panel_buttons)
        sizer.Add(canvas_sizer)
        self.SetSizerAndFit(sizer)
        self.Show()

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 =(4,3))
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.Size = self.canvas.Size
        self.parent = parent

    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 """
        N = 100000
        x = np.linspace(0.0, 10.0, N)
        self.axes.plot(x, +np.sin(.2*np.pi*x), lw=3.5, c='b', alpha=.7)
        self.axes.plot(x, +np.cos(.2*np.pi*x), lw=3.5, c='r', alpha=.5)
        self.axes.plot(x, -np.sin(.2*np.pi*x), lw=3.5, c='g', alpha=.3)

        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=0.5,fill=False))


    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_axes=[x1,x2,y1,y2]
        self.parent.zoom_panel.Update(self)


class Zoom(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent,size=(200,250))
        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,3))
        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)

        N = 100000
        x = np.linspace(0.0, 10.0, N)
        self.axes.plot(x, +np.sin(.2*np.pi*x), lw=3.5, c='b', alpha=.7)
        self.axes.plot(x, +np.cos(.2*np.pi*x), lw=3.5, c='r', alpha=.5)
        self.axes.plot(x, -np.sin(.2*np.pi*x), lw=3.5, c='g', alpha=.3)
        self.canvas.draw()
        self.Refresh()

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.zoom_panel = Zoom(parent=self)
        self.Size = self.canvas_panel.Size
        canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
        canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
        canvas_sizer.Add(self.zoom_panel,1,wx.EXPAND)
        self.SetSizerAndFit(canvas_sizer)
        self.Show()

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()

enter image description here