Related
I'm trying to make a sort of image viewer in which I put a background image ("Affichage du mur" button) and then I load images with the "Importer l'oeuvre" button (you can load as many images you want). It works fine but I would like that we could delete the images ... in fact I would like the image that we delete is the image selected by the user. I can't get the selected image to be deleted with the "Suppression de l'oeuvre" button ... it seems that there is a selectedItems() method but I don't know how to use it in my code. Can you help me please ? Here is a very simplified code of what I am doing :
import os, sys
try : import Image
except ImportError : from PIL import Image
# Imports PyQt5 -----------------------------------------------------------------------
from PyQt5.QtWidgets import QPushButton, QGridLayout, QGraphicsScene, QGraphicsView, \
QGraphicsPixmapItem, QGraphicsItem, QApplication, \
QMainWindow, QFileDialog, QWidget
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QColor, QTransform
# --------------------------------------------------------------------------------------
class TEST(QMainWindow):
def __init__(self):
super(TEST, self).__init__()
self.setWindowTitle('TEST')
self.setGeometry(10, 20, 1280, 760)
self.setMinimumSize(1280, 760)
# ----------------------------------------
self.graphe_vue = MonGraphiqueVueMur()
# ----------------------------------------
bout_visio_mur = QPushButton("Affichage du mur")
bout_visio_mur.setMaximumWidth(230)
bout_visio_mur.setMinimumWidth(230)
bout_visio_oeuvre = QPushButton("Importer l'oeuvre")
bout_visio_oeuvre.setMaximumWidth(230)
bout_visio_oeuvre.setMinimumWidth(230)
bout_supprimer_oeuvre = QPushButton("Suppression de l'oeuvre")
bout_supprimer_oeuvre.setMaximumWidth(230)
bout_supprimer_oeuvre.setMinimumWidth(230)
# ------------------------------------------------------------
bout_visio_mur.clicked.connect(self.graphe_vue.afficher_mur)
bout_visio_oeuvre.clicked.connect(self.graphe_vue.afficher_image_oeuvre)
bout_supprimer_oeuvre.clicked.connect(self.graphe_vue.supprimer_image_oeuvre)
# ------------------------------------------------------------
grid = QGridLayout()
grid.addWidget(self.graphe_vue, 0, 0)
grid.addWidget(bout_visio_mur, 1, 0)
grid.addWidget(bout_visio_oeuvre, 2, 0)
grid.addWidget(bout_supprimer_oeuvre, 3, 0)
widget = QWidget()
widget.setLayout(grid)
self.setCentralWidget(widget)
class MaScene(QGraphicsScene) :
def __init__(self, parent=None) :
super(MaScene, self).__init__(parent)
class MonGraphiquePixmapItemMur(QGraphicsPixmapItem) :
def __init__(self, parent=None):
super(MonGraphiquePixmapItemMur, self).__init__(parent)
class MonGraphiquePixmapItemOeuvre(QGraphicsPixmapItem) :
def __init__(self, parent=None):
super(MonGraphiquePixmapItemOeuvre, self).__init__(parent)
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
self.setAcceptHoverEvents(True)
def hoverEnterEvent(self, event):
print('setAcceptHoverEvents --> Position', event.pos(), type(event.pos()), type(event.pos().x()), type(event.pos().x()))
print("Position X", event.pos().x(), "Position Y", event.pos().y())
class MonGraphiqueVueMur(QGraphicsView) :
backgroundcolor = QColor(100, 100, 100)
def __init__(self, parent=None) :
super(MonGraphiqueVueMur, self).__init__(parent)
self.setBackgroundBrush(self.backgroundcolor)
self.scene = MaScene()
self.setScene(self.scene)
def wheelEvent(self, event):
zoomInFactor = 1.1
zoomOutFactor = 1 / zoomInFactor
self.setTransformationAnchor(QGraphicsView.NoAnchor)
self.setResizeAnchor(QGraphicsView.NoAnchor)
oldPos = self.mapToScene(event.pos())
if event.angleDelta().y() > 0:
zoomFactor = zoomInFactor
else:
zoomFactor = zoomOutFactor
self.scale(zoomFactor, zoomFactor)
newPos = self.mapToScene(event.pos())
delta = newPos - oldPos
self.translate(delta.x(), delta.y())
def afficher_mur(self) :
ouv = QFileDialog.getOpenFileName(self, 'Ouvrir une image', os.path.expanduser('~'), 'Images (*.jpg *.jpeg *.JPG *.JPEG *.png *.gif)')[0]
chemin_fichier = str(ouv)
img_mur = Image.open(chemin_fichier)
self.scene.clear()
self.items().clear()
largeur, hauteur = img_mur.size
pixmap = QPixmap(chemin_fichier)
item = MonGraphiquePixmapItemMur(pixmap)
item.setTransformationMode(Qt.SmoothTransformation)
self.scene.addItem(item)
self.setScene(self.scene)
self.fitInView(item, Qt.KeepAspectRatio)
x, y = 0, 0
self.setSceneRect(-x, -y, largeur, hauteur)
self.centerOn(10, 10)
self.show()
def afficher_image_oeuvre(self) :
ouv = QFileDialog.getOpenFileName(self, 'Ouvrir une image', os.path.expanduser('~'), 'Images (*.jpg *.jpeg *.JPG *.JPEG *.png *.gif)')[0]
chemin_fichier = str(ouv)
pixmap = QPixmap(chemin_fichier)
pixmap = pixmap.scaled(700, 700, Qt.KeepAspectRatio, Qt.SmoothTransformation)
item = MonGraphiquePixmapItemOeuvre(pixmap)
item.setTransformationMode(Qt.SmoothTransformation)
item.setFlag(QGraphicsItem.ItemIsFocusable)
self.scene.addItem(item)
self.setScene(self.scene)
###################################################################################
iteme = self.scene.selectedItems()
print("iteme", iteme) # Return []
###################################################################################
self.show()
def supprimer_image_oeuvre(self) :
import sip
tous_items = list(self.scene.items())
print("len(tous_items)", len(tous_items))
print("tous_items", tous_items)
for i in tous_items :
if str(type(i)) != "<class '__main__.MonGraphiquePixmapItemMur'>" :
self.scene.removeItem(tous_items[0])
sip.delete(tous_items[0])
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = TEST()
ex.show()
sys.exit(app.exec_())
Thanks in advance.
I'd have other questions to ask but we'll see that later.
You just have to cycle through selectedItems(), there's absolutely no need to use the sip module, nor check the class using the string (which is not a good way to do so).
def supprimer_image_oeuvre(self) :
for item in self.scene.selectedItems():
self.scene.removeItem(item)
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()
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()
I am using PyQt5 to create a GUI program.
I have a problem when creating a label beside the QComboBox.
If I didnt create a label beside the QComboBox , it would look like the picture down below.
But if I added the label it would be like this :
The selection list just moved down a little bit automatically.
How can I do to make it be align to the label at the left-hand side?
(I mean just beside the CASE TYPE)
(I comment the critical part in my code)
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtWidgets
import xml.etree.cElementTree as ET
class App(QMainWindow):
def __init__(self,parent=None):
super().__init__()
self.title = "Automation"
self.left = 10
self.top = 10
self.width = 400
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# Create textbox
self.textbox = QLineEdit(self)
self.textbox.move(80, 20)
#self.textbox.resize(50,40)
self.textbox2 = QLineEdit(self)
self.textbox2.move(80, 80)
#self.textbox2.resize(50,40)
# Create text beside editor
wid1 = QWidget(self)
self.setCentralWidget(wid1)
mytext = QFormLayout()
mytext.addRow("CASE INDEX",self.textbox)
mytext.addRow("CASE TYPE",self.textbox2)
wid1.setLayout(mytext)
#################### Critical Part #######################
self.CB = QComboBox()
self.CB.addItems(["RvR","Turntable","Fixrate"])
self.CB.currentIndexChanged.connect(self.selectionchange)
label = QLabel("CASE TYPE")
mytext.addRow(label,self.CB) # this one makes the list shift down a little bit
mytext.addWidget(self.CB)
wid1.setLayout(mytext)
##########################################################
# Create a button in the window
self.button = QPushButton('Show text', self)
self.button.move(20,150)
# connect button to function on_click
self.button.clicked.connect(self.on_click)
self.center()
self.show()
#pyqtSlot()
def on_click(self):
textboxValue = self.textbox.text()
textboxValue2 = self.textbox2.text()
QMessageBox.question(self, 'Message - pythonspot.com', "You typed: "+ textboxValue + " , second msg is: " + textboxValue2, QMessageBox.Ok, QMessageBox.Ok)
print(textboxValue)
self.textbox.setText("")
self.textbox2.setText("")
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def selectionchange(self,i):
print ("Items in the list are :")
for count in range(self.CB.count()):
print (self.CB.itemText(count))
print ("Current index",i,"selection changed ",self.CB.currentText())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Please , I need your help.
Thanks.
Try it:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtWidgets
import xml.etree.cElementTree as ET
class App(QMainWindow):
def __init__(self,parent=None):
super().__init__()
self.title = "Automation"
self.left = 10
self.top = 10
self.width = 400
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# Create textbox
self.textbox = QLineEdit(self)
# self.textbox.move(80, 20)
#self.textbox.resize(50,40)
self.textbox2 = QLineEdit(self)
# self.textbox2.move(80, 80)
#self.textbox2.resize(50,40)
# Create text beside editor
wid1 = QWidget(self)
self.setCentralWidget(wid1)
mytext = QFormLayout()
mytext.addRow("CASE INDEX", self.textbox)
mytext.addRow("CASE TYPE", self.textbox2)
# wid1.setLayout(mytext)
#################### Critical Part #######################
self.CB = QComboBox()
self.CB.addItems(["RvR","Turntable","Fixrate"])
self.CB.currentIndexChanged.connect(self.selectionchange)
label = QLabel("CASE TYPE")
mytext.addRow(label, self.CB) # this one makes the list shift down a little bit
# mytext.addWidget(self.CB)
# wid1.setLayout(mytext)
##########################################################
# Create a button in the window
self.button = QPushButton('Show text', self)
# self.button.move(20,150)
# connect button to function on_click
self.button.clicked.connect(self.on_click)
layoutV = QVBoxLayout(wid1) # + wid1 <<<========
layoutV.addLayout(mytext) # +
layoutV.addWidget(self.button, alignment=Qt.AlignLeft) # +
self.center()
self.show()
#pyqtSlot()
def on_click(self):
textboxValue = self.textbox.text()
textboxValue2 = self.textbox2.text()
QMessageBox.question(self, 'Message - pythonspot.com', "You typed: "+ textboxValue + " , second msg is: " + textboxValue2, QMessageBox.Ok, QMessageBox.Ok)
print(textboxValue)
self.textbox.setText("")
self.textbox2.setText("")
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def selectionchange(self,i):
print ("Items in the list are :")
for count in range(self.CB.count()):
print (self.CB.itemText(count))
print ("Current index",i,"selection changed ",self.CB.currentText())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())