@@ -889,57 +889,33 @@ def add_plot(
889
889
self .manager .add_plot (plot , plot_id )
890
890
891
891
892
- class SyncPlotWindow (QW .QMainWindow ):
893
- """Window for showing plots, optionally synchronized
894
-
895
- Args:
896
- parent: parent widget
897
- toolbar: show/hide toolbar
898
- options: plot options
899
- panels: additionnal panels
900
- auto_tools: If True, the plot tools are automatically registered.
901
- If False, the user must register the tools manually.
902
- title: The window title
903
- icon: The window icon
904
- size: The window size (width, height). Defaults to None (no resize)
905
-
906
- Usage: first, create a window, then add plots to it, then call the
907
- :py:meth:`.SyncPlotWindow.finalize_configuration` method to add panels and
908
- eventually register tools.
909
-
910
- Example::
911
-
912
- from plotpy.plot import BasePlot, SyncPlotWindow
913
- win = SyncPlotWindow(title="My window")
914
- plot = BasePlot()
915
- win.add_plot(plot)
916
- win.finalize_configuration()
917
- win.show()
918
- """
892
+ class BaseSyncPlot :
893
+ """Base class for synchronized plot windows and dialogs"""
919
894
920
895
def __init__ (
921
896
self ,
922
- parent : QWidget | None = None ,
923
897
toolbar : bool = True ,
924
898
options : PlotOptions | dict [str , Any ] | None = None ,
925
899
auto_tools : bool = True ,
926
900
title : str = "PlotPy" ,
927
901
icon : str = "plotpy.svg" ,
928
902
size : tuple [int , int ] | None = None ,
929
903
) -> None :
930
- super ().__init__ (parent )
931
- set_widget_title_icon (self , title , icon , size )
932
904
self .manager = PlotManager (None )
933
905
self .manager .set_main (self )
934
906
self .subplotwidget = SubplotWidget (self .manager , parent = self , options = options )
935
- self .setCentralWidget (self .subplotwidget )
936
907
self .toolbar = QW .QToolBar (_ ("Tools" ), self )
937
908
self .toolbar .setVisible (toolbar )
938
909
self .manager .add_toolbar (self .toolbar , "default" )
939
910
self .toolbar .setMovable (True )
940
911
self .toolbar .setFloatable (True )
941
- self .addToolBar (self .toolbar )
942
912
self .auto_tools = auto_tools
913
+ set_widget_title_icon (self , title , icon , size )
914
+ # Note: setup_layout() is called by subclasses after Qt widget initialization
915
+
916
+ def setup_layout (self ) -> None :
917
+ """Setup the layout - to be implemented by subclasses"""
918
+ raise NotImplementedError ("Subclasses must implement `setup_layout` method" )
943
919
944
920
def get_toolbar (self ) -> QW .QToolBar :
945
921
"""Return main toolbar
@@ -969,11 +945,6 @@ def rescale_plots(self) -> None:
969
945
for plot in self .subplotwidget .plots :
970
946
plot .do_autoscale ()
971
947
972
- def showEvent (self , event ): # pylint: disable=C0103
973
- """Reimplement Qt method"""
974
- super ().showEvent (event )
975
- QC .QTimer .singleShot (0 , self .rescale_plots )
976
-
977
948
def add_plot (
978
949
self ,
979
950
row : int ,
@@ -995,10 +966,15 @@ def add_plot(
995
966
plot_id = str (len (self .subplotwidget .plots ) + 1 )
996
967
self .subplotwidget .add_plot (plot , row , col , plot_id )
997
968
if sync and len (self .subplotwidget .plots ) > 1 :
998
- syncaxis = self .manager .synchronize_axis
999
- for i_plot in range (len (self .subplotwidget .plots ) - 1 ):
1000
- syncaxis (X_BOTTOM , [plot_id , f"{ i_plot + 1 } " ])
1001
- syncaxis (Y_LEFT , [plot_id , f"{ i_plot + 1 } " ])
969
+ self ._synchronize_with_existing_plots (plot_id )
970
+
971
+ def _synchronize_with_existing_plots (self , plot_id : str ) -> None :
972
+ """Synchronize the new plot with existing plots"""
973
+ syncaxis = self .manager .synchronize_axis
974
+ for i_plot in range (len (self .subplotwidget .plots ) - 1 ):
975
+ existing_plot_id = f"{ i_plot + 1 } "
976
+ syncaxis (X_BOTTOM , [plot_id , existing_plot_id ])
977
+ syncaxis (Y_LEFT , [plot_id , existing_plot_id ])
1002
978
1003
979
def get_plots (self ) -> list [BasePlot ]:
1004
980
"""Return the plots
@@ -1007,3 +983,117 @@ def get_plots(self) -> list[BasePlot]:
1007
983
list[BasePlot]: The plots
1008
984
"""
1009
985
return self .subplotwidget .get_plots ()
986
+
987
+
988
+ class SyncPlotWindow (QW .QMainWindow , BaseSyncPlot ):
989
+ """Window for showing plots, optionally synchronized
990
+
991
+ Args:
992
+ parent: parent widget
993
+ toolbar: show/hide toolbar
994
+ options: plot options
995
+ panels: additionnal panels
996
+ auto_tools: If True, the plot tools are automatically registered.
997
+ If False, the user must register the tools manually.
998
+ title: The window title
999
+ icon: The window icon
1000
+ size: The window size (width, height). Defaults to None (no resize)
1001
+
1002
+ Usage: first, create a window, then add plots to it, then call the
1003
+ :py:meth:`.SyncPlotWindow.finalize_configuration` method to add panels and
1004
+ eventually register tools.
1005
+
1006
+ Example::
1007
+
1008
+ from plotpy.plot import BasePlot, SyncPlotWindow
1009
+ win = SyncPlotWindow(title="My window")
1010
+ plot = BasePlot()
1011
+ win.add_plot(plot)
1012
+ win.finalize_configuration()
1013
+ win.show()
1014
+ """
1015
+
1016
+ def __init__ (
1017
+ self ,
1018
+ parent : QWidget | None = None ,
1019
+ toolbar : bool = True ,
1020
+ options : PlotOptions | dict [str , Any ] | None = None ,
1021
+ auto_tools : bool = True ,
1022
+ title : str = "PlotPy" ,
1023
+ icon : str = "plotpy.svg" ,
1024
+ size : tuple [int , int ] | None = None ,
1025
+ ) -> None :
1026
+ self .subplotwidget : SubplotWidget
1027
+ self .toolbar : QW .QToolBar
1028
+ QW .QMainWindow .__init__ (self , parent )
1029
+ BaseSyncPlot .__init__ (self , toolbar , options , auto_tools , title , icon , size )
1030
+ self .setup_layout ()
1031
+
1032
+ def showEvent (self , event ): # pylint: disable=C0103
1033
+ """Reimplement Qt method"""
1034
+ super ().showEvent (event )
1035
+ QC .QTimer .singleShot (0 , self .rescale_plots )
1036
+
1037
+ def setup_layout (self ) -> None :
1038
+ """Setup the main window layout"""
1039
+ self .setCentralWidget (self .subplotwidget )
1040
+ self .addToolBar (self .toolbar )
1041
+
1042
+
1043
+ class SyncPlotDialog (QW .QDialog , BaseSyncPlot ):
1044
+ """Dialog for showing plots, optionally synchronized
1045
+
1046
+ Args:
1047
+ parent: parent widget
1048
+ toolbar: show/hide toolbar
1049
+ options: plot options
1050
+ auto_tools: If True, the plot tools are automatically registered.
1051
+ If False, the user must register the tools manually.
1052
+ title: The window title
1053
+ icon: The window icon
1054
+ size: The window size (width, height). Defaults to None (no resize)
1055
+
1056
+ Usage: first, create a dialog, then add plots to it, then call the
1057
+ :py:meth:`.SyncPlotDialog.finalize_configuration` method to add panels and
1058
+ eventually register tools.
1059
+
1060
+ Example::
1061
+
1062
+ from plotpy.plot import BasePlot, SyncPlotDialog
1063
+ dlg = SyncPlotDialog(title="My dialog")
1064
+ plot = BasePlot()
1065
+ dlg.add_plot(plot)
1066
+ dlg.finalize_configuration()
1067
+ dlg.exec()
1068
+ """
1069
+
1070
+ def __init__ (
1071
+ self ,
1072
+ parent : QWidget | None = None ,
1073
+ toolbar : bool = True ,
1074
+ options : PlotOptions | dict [str , Any ] | None = None ,
1075
+ auto_tools : bool = True ,
1076
+ title : str = "PlotPy" ,
1077
+ icon : str = "plotpy.svg" ,
1078
+ size : tuple [int , int ] | None = None ,
1079
+ ) -> None :
1080
+ self .subplotwidget : SubplotWidget
1081
+ self .toolbar : QW .QToolBar
1082
+ QW .QDialog .__init__ (self , parent )
1083
+ BaseSyncPlot .__init__ (self , toolbar , options , auto_tools , title , icon , size )
1084
+ self .setup_layout ()
1085
+ self .setWindowFlags (QC .Qt .Window )
1086
+
1087
+ def showEvent (self , event ): # pylint: disable=C0103
1088
+ """Reimplement Qt method"""
1089
+ super ().showEvent (event )
1090
+ QC .QTimer .singleShot (0 , self .rescale_plots )
1091
+
1092
+ def setup_layout (self ) -> None :
1093
+ """Setup the dialog layout"""
1094
+ self .plot_layout = QW .QGridLayout ()
1095
+ self .plot_layout .addWidget (self .subplotwidget )
1096
+ layout = QW .QVBoxLayout ()
1097
+ layout .addWidget (self .toolbar )
1098
+ layout .addLayout (self .plot_layout )
1099
+ self .setLayout (layout )
0 commit comments