after have some help about plot area inside rectangle selector i worked but when i applicated in some code app i have error like :
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'
i don't know why it can't working the class(zoom) in my app all is good i thing but i dont know where is the problem inside code .
this is code for second application when i need to do the select area inside rectangle :
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()
It's a matter of rearranging things within the code to use a panel rather than a new frame. Although, a new frame is only created as needed by the user of the program, whilst an existing panel has to be there, whether it is needed or not!
I've rearranged a previous answer to show the zoom in another panel but for the life of me, I don't understand why you don't take advantage of the built in matplotlib toolbar using 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()
Related
I'm trying to draw a line interactively but I can't figure out how to do it. Anyone can help me?
I'm using PyQt5. I create a QGraphicsScene, I override mouse press event but when I try to draw the draw the it draw nothing.
Finally, I have another question. How can I snap this line to the grid?
import math
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class neGraphicScene(QGraphicsScene):
_colorBackGround: str
_colorLightLines: str
_colorDarkLines: str
_penLight: QPen
_penDark: QPen
gridSize: int = 20
gridSquares: int = 5
isLineDrawing = False
def __init__(self, parent=None):
QGraphicsScene.__init__(self, QRectF(-1000, -1000, 2000, 2000), parent)
self.setSceneColor()
self.begin, self.destination = QPoint(), QPoint()
def setSceneColor(self, _lightLines="#2f2f2f", _darkLines="#292929", _background="#393939"):
self._colorBackGround = _background
self._colorLightLines = _lightLines
self._colorDarkLines = _darkLines
self._penLight = QPen(QColor(self._colorLightLines))
self._penLight.setWidth(1)
self._penDark = QPen(QColor(self._colorDarkLines))
self._penDark.setWidth(2)
self.setBackgroundBrush(QColor(self._colorBackGround))
def setGraphicScene(self, width, height):
self.setSceneRect(-width // 2, -height // 2, width, height)
def mouseDoubleClickEvent(self, event):
QGraphicsScene.mouseMoveEvent(self, event)
def mousePressEvent(self, event):
self.isLineDrawing = True
if event.buttons() & Qt.LeftButton:
print('Point 1')
self.begin = event.pos()
self.destination = self.begin
self.update()
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
print('Point 2')
self.destination = event.pos()
self.update()
def mouseReleaseEvent(self, event):
self.isLineDrawing = False
print('Point 3')
def drawBackground(self, painter, rect):
super(neGraphicScene, self).drawBackground(painter, rect)
# self.drawBackgroundGrid(painter, rect)
if self.isLineDrawing:
if not self.begin.isNull() and not self.destination.isNull():
line = QLineF(self.begin, self.destination)
painter.setPen(Qt.red)
painter.drawLine(line)
This is the QGraphicsView and the QWidgetStuff to made the minimal example working properly:
class neGraphicView(QGraphicsView):
def __init__(self, graphicScene, parent=None):
super().__init__(parent)
# self._dragPos = QPoint(0, 0)
self.sharedGraphicScene = graphicScene
self.setScene(self.sharedGraphicScene)
self._mousePressed = False
self._isPanning = False
self.initUI()
def initUI(self):
self.setRenderHints(
QPainter.Antialiasing | QPainter.HighQualityAntialiasing |
QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setDragMode(QGraphicsView.RubberBandDrag)
class NodeEditorWindow(QWidget):
mainLayout: QVBoxLayout
mainGraphicsScene: neGraphicScene
view: neGraphicView
def __init__(self, parent=None):
super(NodeEditorWindow, self).__init__(parent)
self.initUI()
def initUI(self):
self.setGeometry(200, 200, 800, 600)
self.mainLayout = QVBoxLayout()
self.mainLayout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.mainLayout)
self.mainGraphicsScene = neGraphicScene()
self.view = neGraphicView(self.mainGraphicsScene, self)
self.mainLayout.addWidget(self.view)
self.setWindowTitle("Node Editor")
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle("Fusion")
win = NodeEditorWindow()
win.show()
sys.exit(app.exec())
This is the grid function:
def drawBackgroundGrid(self, _painter, _rect):
# here we create our grid
_left = int(math.floor(_rect.left()))
_right = int(math.ceil(_rect.right()))
_top = int(math.floor(_rect.top()))
_bottom = int(math.ceil(_rect.bottom()))
first_left = _left - (_left % self.gridSize)
first_top = _top - (_top % self.gridSize)
try:
# compute all lines to be drawn
lightLines, darkLines = [], []
for x in range(first_left, _right, self.gridSize):
if x % (self.gridSize * self.gridSquares) != 0:
lightLines.append(QLineF(x, _top, x, _bottom))
else:
darkLines.append(QLineF(x, _top, x, _bottom))
for y in range(first_top, _bottom, self.gridSize):
if y % (self.gridSize * self.gridSquares) != 0:
lightLines.append(QLineF(_left, y, _right, y))
else:
darkLines.append(QLineF(_left, y, _right, y))
# draw the lines
_painter.setPen(self._penLight)
_painter.drawLines(*lightLines)
_painter.setPen(self._penDark)
_painter.drawLines(*darkLines)
except Exception as e:
# print(e)
pass
Panels are dynamically added during the execution of the program. How do I add a Scrollbar to my MainFrame when it is initialized so that I can see the panels added below each other?
import wx
class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super().__init__(None, *args, **kwargs)
self.Title = 'Wx App'
screen_width, screen_height = wx.GetDisplaySize()
win_width = min(screen_width, 1280)
win_height = min(screen_height, 800)
self.Size = (win_width, win_height)
self.panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel)
self.SetSizer(sizer)
self.Center()
self.Show()
class MainPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
if __name__ == '__main__':
wx_app = wx.App()
MainFrame()
wx_app.MainLoop()
There may be a solution with wx.ScrolledWindow but a scrolled panel seems to work.
import wx
import wx.lib.scrolledpanel as scrolled
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial", size=(800,600))
self.panel = wx.Panel(self, wx.ID_ANY)
self.panel.SetBackgroundColour('green')
self.scrolled_panel = scrolled.ScrolledPanel(self.panel, -1, style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER, name="panel1")
self.scrolled_panel.SetAutoLayout(1)
self.scrolled_panel.SetupScrolling()
self.scrolled_panel.SetBackgroundColour('CYAN')
self.sizer = wx.BoxSizer(wx.VERTICAL)
text = wx.StaticText(self.scrolled_panel, wx.ID_ANY, 'My text')
self.sizer.Add(text)
panel_in1 = wx.Panel(self.scrolled_panel, wx.ID_ANY, wx.DefaultPosition, wx.Size(-1,250), style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
panel_in1.SetBackgroundColour('red')
self.sizer.Add(panel_in1,0,wx.EXPAND)
panel_in2 = wx.Panel(self.scrolled_panel, wx.ID_ANY, wx.DefaultPosition, wx.Size(-1,150), style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
panel_in2.SetBackgroundColour('grey')
self.sizer.Add(panel_in2,0,wx.EXPAND)
self.scrolled_panel.SetSizer(self.sizer)
panelSizer = wx.BoxSizer(wx.VERTICAL)
panelSizer.AddSpacer(50)
panelSizer.Add(self.scrolled_panel, 1, wx.EXPAND)
self.panel.SetSizer(panelSizer)
self.statusBar = self.CreateStatusBar( 1, wx.STB_SIZEGRIP, wx.ID_ANY )
self.Centre( wx.BOTH )
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm().Show()
app.MainLoop()
i need to know how i can read and show values of all pixel inside rectangle patch of matrix 5x5 ( 5 rows , 5 column) like a board in other panel
i do this example just to explain what i need to do :
what i need to show in paneltwo is like this example :
that the code :
import wx
import numpy as np
import netCDF4
from netCDF4 import Dataset
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
import matplotlib
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)
self.canvas_panel = CanvasPanel(self)
self.panel_two = PanelTwo(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.panel_two,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):
def __init__(self, parent, wildcard, func, **kwargs):
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):
""" Panel du graphique matplotlib """
def __init__(self, parent , size=(200,250)):
super().__init__(parent)
self.figure = Figure(figsize =(5,5))
self.canvas = FigureCanvas(self, -1, self.figure)
self.Size = self.canvas.Size
self.parent = parent
def load_from_file(self, file_name):
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):
fic='air.departure.sig995.2012.nc'
path='D:/data/'
nc = netCDF4.Dataset(path+fic,'r')
lons = nc.variables['lon'][:]
lats = nc.variables['lat'][:]
air_dep = nc.variables['air_dep'][:,:,:]
air_dep = air_dep[0,:,:]
self.axes.imshow(air_dep)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 1
self.rect = patches.Rectangle((x, y), 5,5,edgecolor='r', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
self.Show()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
self.parent.panel_two.Update(x1,y1)
zx1 = x1 - 2.5
zy1 = y1 - 2.5
zx2 = x1 + 2.5
zy2 = y1 + 2.5
self.rect.set_x(x1 - 2.5) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 2.5) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
class PanelTwo(wx.Panel): #here when i need to visualize pixel and coordinator cursor
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(300,250))
self.text_ctrl = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2, size=(200,170))
lbl = wx.StaticText(self,label="Coordinato cursor & Pixel ")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(lbl,0, wx.ALIGN_CENTRE,10)
sizer.Add(self.text_ctrl,0, wx.ALIGN_CENTRE,10)
self.SetSizer(sizer)
def Update(self,x1,y1):
self.text_ctrl.SetValue("Mouse click at;\nX "+str(x1)+"\nY "+str(y1))
class TopLevelCanvas(wx.Frame):
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()
is maybe i need to use something like : **air_dep[x-5:x+5,y-5:y+5]** in this line of code :
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
self.parent.panel_two.Update(x1,y1)
how i can show the values like matrix or board in example with all column and rows ?
thank you
other file netcdf4 : https://drive.google.com/open?id=1IT-F7AbIx4bCjMLosjBx4F4UCoIX5DU0 here
Currently the 5x5 grid is written into the 2nd panel, you could create a separate panel for them.
The 5x5 grid is a bit hacky, as around the edges the grid can become 3x5 or 5x3 and in the corners it has to become 3x3.
import wx
import numpy as np
import netCDF4
from netCDF4 import Dataset
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
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.panel_two = PanelTwo(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.panel_two,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 =(5,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 """
fic='air.departure.sig995.2012.nc'
#path='/home/data/'
path=''
nc = netCDF4.Dataset(path+fic,'r')
# print("model",nc.data_model)
# print("groups",nc.groups)
# print("dimensions",nc.dimensions)
# print("variables",nc.variables)
# for dimobj in nc.dimensions.values():
# print(dimobj)
# for name in nc.ncattrs():
# print("Global attr", name, "=", getattr(nc,name))
self.lons = nc.variables['lon'][:]
self.lats = nc.variables['lat'][:]
air_dep = nc.variables['air_dep'][:,:,:]
self.lonl = len(self.lons) -1
self.latl = len(self.lats) -1
self.air_dep = air_dep[0,:,:]
self.axes.imshow(self.air_dep)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 1
self.rect = patches.Rectangle((x, y), 5,5,edgecolor='r', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
def float_to_dms(self,f,orientation):
# convert to seconds
f = f * 3600
if f < 0:
div1 = -3600
div2 = -1
else:
div1 = 3600
div2 = 1
#Degrees,minutes,seconds
d,m = divmod(f,div1)
m,s = divmod(m*60,div1)
s, x = divmod(s*60,div1)
d,x = divmod(d,div2)
m,x = divmod(m,1)
s,x = divmod(s,1)
return (orientation+" "+str(int(d))+"° "+str(int(m)).zfill(2)+"' "+str(int(s)).zfill(2)+'"\n')
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
#Longititude values are 2.5 degrees apart for this data
try:
lon = x1*2.5
except:
print("Out of bounds - Click again")
return
if lon < 180.0:
Ew = "E"
else:
Ew = "W"
lon = (lon - 360.0) -1
#Latitude values from 90 to -90 2.5 degrees apart
#split the y value
i,f = divmod(y1,1)
lat = self.lats[int(i)]
#calculate the fraction of degrees
if lat > 0 and lat < 87.5:
lat = lat+(f*2.5)
elif lat < 0 and lat > -87.5:
lat = lat-(f*2.5)
if lat < 0.0:
Ns= "S"
else:
Ns = "N"
#Convert to ° ' "
lon_dms = self.float_to_dms(lon,Ew)
lat_dms = self.float_to_dms(lat,Ns)
#air_dep seems the wrong way round but what do I know
#The way below gives values that seem correct
air = self.air_dep[int(y1),int(x1)]
air_rect =[]
x = int(x1)
y = int(y1)
# Build valid values for rectangle
# to cater for values beyond the edge of the map
if x-1 < 0: x2 = 0
else: x2 = x-2
if x+2 > self.lonl: x3 = self.lonl+1
else: x3 = x+3
if y-2 < 0:
pass
else:
air_rect.append(self.air_dep[y-2,x2:x3])
if y-1 < 0:
pass
else:
air_rect.append(self.air_dep[y-1,x2:x3])
air_rect.append(self.air_dep[y,x2:x3])
if y+1 > self.latl:
pass
else:
air_rect.append(self.air_dep[y+1,x2:x3])
if y+2 > self.latl:
pass
else:
air_rect.append(self.air_dep[y+2,x2:x3])
self.parent.panel_two.Update(x1,y1,lon,lat,air,lon_dms,lat_dms,Ns,Ew,air_rect)
zx1 = x1 - 2.5
zy1 = y1 - 2.5
zx2 = x1 + 2.5
zy2 = y1 + 2.5
self.rect.set_x(x1 - 2.5) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 2.5) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
class PanelTwo(wx.Panel): #here when i need to visualize pixel and coordinator cursor
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(300,250))
self.text_ctrl = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2, size=(300,300))
lbl = wx.StaticText(self,label="Coordinato cursor & Pixel ")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(lbl,0, wx.ALIGN_CENTRE,10)
sizer.Add(self.text_ctrl,0, wx.ALIGN_CENTRE,10)
self.SetSizer(sizer)
def Update(self,x1,y1,lon,lat,air,lon_dms,lat_dms,Ns,Ew,air_rect):
update_str = "Mouse click at;\nX "+str(x1)+"\nLon "+Ew+" "+str(lon)+"\n"+lon_dms+"\nY "+str(y1)+"\nLat "+Ns+" "+str(lat)+"\n"+lat_dms+"\nAir Value at point "+str(air)+"\n"
self.text_ctrl.SetValue(update_str)
self.text_ctrl.write("Surrounding values\n")
#Table of surrounding temperatures
for i in range(len(air_rect)):
s = ""
line = air_rect[i]
for i2 in line:
s+="{:5.1f}".format(i2)+" "
self.text_ctrl.write(s+"\n")
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()
I have questions about code when I plot figure with imshow matplotlib I have a plot with x y and z= value of pixel like picture :
code :
import netCDF4
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
path = 'D/data/'
fic = 'air.departure.sig995.2012.nc'
nc = netCDF4.Dataset(path+fic,'r')
var = nc.variables.keys()
lats = nc.variables['lat'][:] # extract/copy the data
lons = nc.variables['lon'][:]
air_dep = nc.variables['air_dep'][:,:,:]
air_dep = air_dep[0,:,:]
plt.imshow(air_dep)
plt.show()
I have an app with wxpython I can show in other panel the cordinates cursor x y but I need to show the value of pixel z how can I do that?
This is the code for application:
import wx
import numpy as np
import netCDF4
from netCDF4 import Dataset
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
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.panel_two = PanelTwo(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.panel_two,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 =(5,5))
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 """
fic='air.departure.sig995.2012.nc'
path='D:/data/'
nc = netCDF4.Dataset(path+fic,'r')
lons = nc.variables['lon'][:]
lats = nc.variables['lat'][:]
air_dep = nc.variables['air_dep'][:,:,:]
air_dep = air_dep[0,:,:]
self.axes.imshow(air_dep)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 1
self.rect = patches.Rectangle((x, y), 5,5,edgecolor='r', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
self.Show()
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
self.parent.panel_two.Update(x1,y1)
zx1 = x1 - 2.5
zy1 = y1 - 2.5
zx2 = x1 + 2.5
zy2 = y1 + 2.5
self.rect.set_x(x1 - 2.5) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 2.5) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
class PanelTwo(wx.Panel): #here when i need to visualize pixel and coordinator cursor
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(300,250))
self.text_ctrl = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2, size=(200,170))
lbl = wx.StaticText(self,label="Coordinato cursor & Pixel ")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(lbl,0, wx.ALIGN_CENTRE,10)
sizer.Add(self.text_ctrl,0, wx.ALIGN_CENTRE,10)
self.SetSizer(sizer)
def Update(self,x1,y1):
self.text_ctrl.SetValue("Mouse click at;\nX "+str(x1)+"\nY "+str(y1))
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()
How can I show the value of pixel in the paneltwo like x y coordinates?
AND ALL VALUES OF AIR_DEP IN WINDOWS 5X5 like this example : IR_108 is other variables value
thank you
When you say "pixel z" do you mean the air_dep value?
import wx
import numpy as np
import netCDF4
from netCDF4 import Dataset
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.patches as patches
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.panel_two = PanelTwo(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.panel_two,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 =(5,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 """
fic='air.departure.sig995.2012.nc'
#path='/home/data/'
path=''
nc = netCDF4.Dataset(path+fic,'r')
self.lons = nc.variables['lon'][:]
self.lats = nc.variables['lat'][:]
air_dep = nc.variables['air_dep'][:,:,:]
self.air_dep = air_dep[0,:,:]
self.axes.imshow(self.air_dep)
self.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 1
self.rect = patches.Rectangle((x, y), 5,5,edgecolor='r', alpha=1, fill=None, label='Label')
self.axes.add_patch(self.rect)
self.axes.plot()
def float_to_dms(self,f):
# convert to seconds
f = f * 3600
if f < 0:
div1 = -3600
div2 = -1
else:
div1 = 3600
div2 = 1
#Degrees,minutes,seconds
d,m = divmod(f,div1)
m,s = divmod(m*60,div1)
s, x = divmod(s*60,div1)
d,x = divmod(d,div2)
m,x = divmod(m,1)
s,x = divmod(s,1)
return ("\n\t"+str(int(d))+"° "+str(int(m)).zfill(2)+"' "+str(int(s)).zfill(2)+'"\n')
def on_press(self, click):
x1, y1 = click.xdata, click.ydata
#Longititude values are 2.5 degrees apart for this data
lon = x1*2.5
#Latitude values from 90 to -90 2.5 degrees apart
#split the y value
i,f = divmod(y1,1)
lat = self.lats[int(i)]
#calculate the fraction of degrees
if lat > 0 and lat < 87.5:
lat = lat+(f*2.5)
elif lat < 0 and lat > -87.5:
lat = lat-(f*2.5)
#Convert to ° ' "
lon_dms = self.float_to_dms(lon)
lat_dms = self.float_to_dms(lat)
#air_dep seems the wrong way round but what do I know
#The way below gives values that seem correct
air = self.air_dep[int(y1),int(x1)]
self.parent.panel_two.Update(x1,y1,lon,lat,air,lon_dms,lat_dms)
zx1 = x1 - 2.5
zy1 = y1 - 2.5
zx2 = x1 + 2.5
zy2 = y1 + 2.5
self.rect.set_x(x1 - 2.5) #Move the rectangle and centre it on the X click point
self.rect.set_y(y1 - 2.5) #Move the rectangle and centre it on the Y click point
self.axes.plot()
self.canvas.draw()
class PanelTwo(wx.Panel): #here when i need to visualize pixel and coordinator cursor
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(300,250))
self.text_ctrl = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2, size=(200,200))
lbl = wx.StaticText(self,label="Coordinato cursor & Pixel ")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(lbl,0, wx.ALIGN_CENTRE,10)
sizer.Add(self.text_ctrl,0, wx.ALIGN_CENTRE,10)
self.SetSizer(sizer)
def Update(self,x1,y1,lon,lat,air,lon_dms,lat_dms):
update_str = "Mouse click at;\nX "+str(x1)+"\nLon "+str(lon)+"\n"+lon_dms+"\nY "+str(y1)+"\nLat "+str(lat)+"\n"+lat_dms+"\nAir Value "+str(air)
self.text_ctrl.SetValue(update_str)
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()
I am trying to put a cursor and rectangle patch that can moved and that can display the coordinates or rather pixel of an image select and display on another panel Paneltwo in the textctrl
each time I move the mouse ( automatically rectangel) the pixels of each point are displayed on the other panel
the first problem that the rectangle can't moved with mouse !
the second that what i need to do is when the rectangle moved with mouse i can visualize the pixel or position of mouse ( rectangle) in panel two textctrl !
how can I do that ?
that part of code :
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,400))
self.Panel = Panel(self)
class Panel(wx.Panel):
def __init__(self,parent):
super().__init__(parent)
panel = wx.Panel(self)
self.panel_two = PanelTwo(parent=self)
self.canvas_panel = CanvasPanel(self)
canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
canvas_sizer.Add(self.panel_two,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,250)):
super().__init__(parent)
self.figure = Figure(figsize =(4,3))
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)
#can'tmove rectangel with mouse
def on_press(self,event):
xpress, ypress = event.xdata, event.ydata
w = rect.get_width()
h = rect.get_height()
rect.set_xy((xpress-w/2, ypress-h/2))
ax.lines = []
ax.axvline(xpress, c='b')
ax.axhline(ypress, c='b')
self.fig.canvas.draw()
self.fig = plt.figure
self.axes = plt.subplot(111)
self.axes.imshow(t,s)
self.fig.canvas.mpl_connect('button_press_event',on_press)
self.rect = patches.Rectangle((x,y),0.01,0.01,linewidth=1,edgecolor='g',facecolor='none')
self.axes.add_patch(rect)
self.plt.show()
class PanelTwo(wx.Panel): #here when i need to visualize pixel and coordinator cursor
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(200,250))
self.text_ctrl = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|
wx.TE_RICH2, size=(200,170), pos = (40,20))
lbl = wx.StaticText(self,label="Coordinato cursor & Pixel " , pos=(40,0))
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()
THANK YOU
Try this and see if it moves you in the right direction.
Note: I have no idea how you are going to retrieve the pixel position from that plot.
Perhaps someone else, who actually knows what they are doing with matplotlib, because I certainly don't, can help with that.
import wx
from numpy import arange, sin, pi,cos
import numpy as np
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,400))
self.Panel = Panel(self)
class Panel(wx.Panel):
def __init__(self,parent):
super().__init__(parent)
panel = wx.Panel(self)
self.panel_two = PanelTwo(parent=self)
self.canvas_panel = CanvasPanel(self)
canvas_sizer = wx.BoxSizer(wx.HORIZONTAL)
canvas_sizer.Add(self.canvas_panel,1,wx.EXPAND)
canvas_sizer.Add(self.panel_two,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,250)):
super().__init__(parent)
self.figure = Figure(figsize =(4,3))
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.canvas.mpl_connect('button_press_event', self.on_press)
x = y = 0.2
self.rect = patches.Rectangle((x, y), 0.4, 0.4, 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
self.parent.panel_two.Update(x1,y1)
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()
class PanelTwo(wx.Panel): #here when i need to visualize pixel and coordinator cursor
def __init__(self,parent):
wx.Panel.__init__(self,parent,size=(300,250))
self.text_ctrl = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2, size=(200,170))
lbl = wx.StaticText(self,label="Coordinato cursor & Pixel ")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(lbl,0, wx.ALIGN_CENTRE,10)
sizer.Add(self.text_ctrl,0, wx.ALIGN_CENTRE,10)
self.SetSizer(sizer)
def Update(self,x1,y1):
self.text_ctrl.SetValue("Mouse click at;\nX "+str(x1)+"\nY "+str(y1))
app = wx.App()
frame = MainFrame(None).Show()
app.MainLoop()