@@ -185,7 +185,13 @@ class PlotArea(pg.GraphicsWidget):
185
185
# Emitted when the ViewBox X range has changed
186
186
sigXRangeChanged = pyqtSignal (object , object )
187
187
188
- def __init__ (self , name = None , parent = None ):
188
+ cross_toggled_sgn = pyqtSignal (bool )
189
+
190
+ _METER_ROW = 0
191
+ _TITLE_ROW = 1
192
+
193
+ def __init__ (self , name = None , * ,
194
+ enable_meter = True , enable_transform = True , parent = None ):
189
195
super ().__init__ (parent = parent )
190
196
191
197
self .setSizePolicy (QSizePolicy .Expanding , QSizePolicy .Expanding )
@@ -200,9 +206,13 @@ def __init__(self, name=None, parent=None):
200
206
201
207
self ._legend = None
202
208
self ._axes = {}
209
+ self ._meter = pg .LabelItem (
210
+ '' , size = '11pt' , justify = 'left' , color = '6A3D9A' , parent = self )
203
211
self ._title = pg .LabelItem ('' , size = '11pt' , parent = self )
204
212
205
213
# context menu
214
+ self ._show_cross_cb = QCheckBox ("Cross cursor" )
215
+
206
216
self ._show_x_grid_cb = QCheckBox ("Show X Grid" )
207
217
self ._show_y_grid_cb = QCheckBox ("Show Y Grid" )
208
218
self ._grid_opacity_sld = QSlider (Qt .Horizontal )
@@ -215,7 +225,10 @@ def __init__(self, name=None, parent=None):
215
225
self ._log_y_cb = QCheckBox ("Log Y" )
216
226
217
227
self ._menu = None
218
- self ._enable_log_menu = True
228
+ self ._enable_transform = enable_transform
229
+ self ._enable_meter = enable_meter
230
+
231
+ self ._show_meter = False
219
232
220
233
self ._layout = QGraphicsGridLayout ()
221
234
@@ -229,13 +242,11 @@ def initUI(self):
229
242
layout .setHorizontalSpacing (0 )
230
243
layout .setVerticalSpacing (0 )
231
244
232
- layout .addItem (self ._title , 0 , 1 )
233
- layout .addItem (self ._vb , 2 , 1 )
234
-
235
- self ._initAxisItems ()
236
- self .setTitle ()
245
+ layout .addItem (self ._meter , self ._METER_ROW , 1 )
246
+ layout .addItem (self ._title , self ._TITLE_ROW , 1 )
247
+ layout .addItem (self ._vb , 3 , 1 )
237
248
238
- for i in range (4 ):
249
+ for i in range (5 ):
239
250
layout .setRowPreferredHeight (i , 0 )
240
251
layout .setRowMinimumHeight (i , 0 )
241
252
layout .setRowSpacing (i , 0 )
@@ -252,13 +263,19 @@ def initUI(self):
252
263
253
264
self .setLayout (layout )
254
265
266
+ self ._initAxisItems ()
267
+ self .setTitle ()
268
+ self .showMeter (self ._show_meter )
269
+
255
270
self ._initContextMenu ()
256
271
257
272
def initConnections (self ):
258
273
self ._vb .sigRangeChanged .connect (self .range_changed_sgn )
259
274
self ._vb .sigXRangeChanged .connect (self .sigXRangeChanged )
260
275
self ._vb .sigYRangeChanged .connect (self .sigYRangeChanged )
261
276
277
+ self ._show_cross_cb .toggled .connect (self ._onShowCrossChanged )
278
+
262
279
self ._show_x_grid_cb .toggled .connect (self ._onShowGridChanged )
263
280
self ._show_y_grid_cb .toggled .connect (self ._onShowGridChanged )
264
281
self ._grid_opacity_sld .sliderReleased .connect (self ._onShowGridChanged )
@@ -268,11 +285,17 @@ def initConnections(self):
268
285
269
286
def _initContextMenu (self ):
270
287
self ._menu = [
288
+ QMenu ("Meter" ),
271
289
QMenu ("Grid" ),
272
290
QMenu ("Transform" )
273
291
]
274
292
275
- grid_menu = self ._menu [0 ]
293
+ meter_menu = self ._menu [0 ]
294
+ cross_act = QWidgetAction (meter_menu )
295
+ cross_act .setDefaultWidget (self ._show_cross_cb )
296
+ meter_menu .addAction (cross_act )
297
+
298
+ grid_menu = self ._menu [1 ]
276
299
show_x_act = QWidgetAction (grid_menu )
277
300
show_x_act .setDefaultWidget (self ._show_x_grid_cb )
278
301
grid_menu .addAction (show_x_act )
@@ -288,7 +311,7 @@ def _initContextMenu(self):
288
311
opacity_act .setDefaultWidget (widget )
289
312
grid_menu .addAction (opacity_act )
290
313
291
- transform_menu = self ._menu [1 ]
314
+ transform_menu = self ._menu [2 ]
292
315
log_x_act = QWidgetAction (transform_menu )
293
316
log_x_act .setDefaultWidget (self ._log_x_cb )
294
317
transform_menu .addAction (log_x_act )
@@ -297,10 +320,10 @@ def _initContextMenu(self):
297
320
transform_menu .addAction (log_y_act )
298
321
299
322
def _initAxisItems (self ):
300
- for orient , pos in (('top' , (1 , 1 )),
301
- ('bottom' , (3 , 1 )),
302
- ('left' , (2 , 0 )),
303
- ('right' , (2 , 2 ))):
323
+ for orient , pos in (('top' , (2 , 1 )),
324
+ ('bottom' , (4 , 1 )),
325
+ ('left' , (3 , 0 )),
326
+ ('right' , (3 , 2 ))):
304
327
axis = pg .AxisItem (orientation = orient , parent = self )
305
328
306
329
axis .linkToView (self ._vb )
@@ -320,6 +343,11 @@ def clearAllPlotItems(self):
320
343
# TODO: introduce a method which set empty data
321
344
item .setData ([], [])
322
345
346
+ @pyqtSlot (bool )
347
+ def _onShowCrossChanged (self , state ):
348
+ self .showMeter (state )
349
+ self .cross_toggled_sgn .emit (state )
350
+
323
351
@pyqtSlot ()
324
352
def _onShowGridChanged (self ):
325
353
alpha = self ._grid_opacity_sld .value ()
@@ -385,12 +413,13 @@ def removeAllItems(self):
385
413
386
414
def getContextMenus (self , event ):
387
415
"""Override."""
388
- if self ._enable_log_menu :
389
- return self ._menu
390
- return self ._menu [:- 1 ]
391
-
392
- def enableLogMenu (self , enable ):
393
- self ._enable_log_menu = enable
416
+ start = 0
417
+ end = len (self ._menu )
418
+ if not self ._enable_transform :
419
+ end -= 1
420
+ if not self ._enable_meter :
421
+ start += 1
422
+ return self ._menu [start :end ]
394
423
395
424
def getAxis (self , axis ):
396
425
"""Return the specified AxisItem.
@@ -449,18 +478,47 @@ def showLabel(self, axis, show=True):
449
478
"""
450
479
self .getAxis (axis ).showLabel (show )
451
480
481
+ def showMeter (self , show = True ):
482
+ """Show or hide the meter bar.
483
+
484
+ :param bool show: whether to show the meter bar.
485
+ """
486
+ row = self ._METER_ROW
487
+ if not show :
488
+ self ._meter .setMaximumHeight (0 )
489
+ self ._layout .setRowFixedHeight (row , 0 )
490
+ self ._meter .setVisible (False )
491
+ else :
492
+ self ._meter .setMaximumHeight (30 )
493
+ self ._layout .setRowFixedHeight (row , 30 )
494
+ self ._meter .setVisible (True )
495
+
496
+ self ._show_meter = show
497
+
498
+ def setMeter (self , pos ):
499
+ """Set the meter of the plot."""
500
+ if not self ._show_meter :
501
+ return
502
+
503
+ if pos is None :
504
+ self ._meter .setText ("" )
505
+ else :
506
+ x , y = pos
507
+ self ._meter .setText (f"x = { x } , y = { y } " )
508
+
452
509
def setTitle (self , title = None , ** args ):
453
510
"""Set the title of the plot.
454
511
455
512
:param str title: text to display along the axis. HTML allowed.
456
513
"""
514
+ row = self ._TITLE_ROW
457
515
if title is None :
458
516
self ._title .setMaximumHeight (0 )
459
- self ._layout .setRowFixedHeight (0 , 0 )
517
+ self ._layout .setRowFixedHeight (row , 0 )
460
518
self ._title .setVisible (False )
461
519
else :
462
520
self ._title .setMaximumHeight (30 )
463
- self ._layout .setRowFixedHeight (0 , 30 )
521
+ self ._layout .setRowFixedHeight (row , 30 )
464
522
self ._title .setText (title , ** args )
465
523
self ._title .setVisible (True )
466
524
@@ -472,3 +530,6 @@ def invertY(self, *args, **kwargs):
472
530
473
531
def invertX (self , * args , ** kwargs ):
474
532
self ._vb .invertX (* args , ** kwargs )
533
+
534
+ def mapSceneToView (self , * args , ** kwargs ):
535
+ return self ._vb .mapSceneToView (* args , ** kwargs )
0 commit comments