@@ -267,8 +267,7 @@ def __init__(self, ax, orientation, closedmin, closedmax,
267
267
self ._fmt .set_useOffset (False ) # No additive offset.
268
268
self ._fmt .set_useMathText (True ) # x sign before multiplicative offset.
269
269
270
- ax .set_xticks ([])
271
- ax .set_yticks ([])
270
+ ax .set_axis_off ()
272
271
ax .set_navigate (False )
273
272
self .connect_event ("button_press_event" , self ._update )
274
273
self .connect_event ("button_release_event" , self ._update )
@@ -329,7 +328,9 @@ class Slider(SliderBase):
329
328
def __init__ (self , ax , label , valmin , valmax , valinit = 0.5 , valfmt = None ,
330
329
closedmin = True , closedmax = True , slidermin = None ,
331
330
slidermax = None , dragging = True , valstep = None ,
332
- orientation = 'horizontal' , * , initcolor = 'r' , ** kwargs ):
331
+ orientation = 'horizontal' , * , initcolor = 'r' ,
332
+ handle_color_grabbed = None , handle_color_released = 'white' ,
333
+ handle_edgecolor = '.75' , handle_size = 10 , ** kwargs ):
333
334
"""
334
335
Parameters
335
336
----------
@@ -380,6 +381,19 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
380
381
The color of the line at the *valinit* position. Set to ``'none'``
381
382
for no line.
382
383
384
+ handle_color_grabbed : color or None, default: None
385
+ The color of the circular slider handle when grabbed. If *None*
386
+ the same color as active part of the slider will be used.
387
+
388
+ handle_color_released : color, default: 'white'
389
+ The color of the circular slider handle when released.
390
+
391
+ handle_edgecolor : color, default: '.75'
392
+ The edgecolor of the circle slider handle.
393
+
394
+ handle_size : int, deafult: 10
395
+ The size of circular slider handle.
396
+
383
397
Notes
384
398
-----
385
399
Additional kwargs are passed on to ``self.poly`` which is the
@@ -404,11 +418,41 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
404
418
self .val = valinit
405
419
self .valinit = valinit
406
420
if orientation == 'vertical' :
407
- self .poly = ax .axhspan (valmin , valinit , 0 , 1 , ** kwargs )
408
- self .hline = ax .axhline (valinit , 0 , 1 , color = initcolor , lw = 1 )
421
+ self .poly = ax .axhspan (valmin , valinit , .25 , .75 , ** kwargs )
422
+ self .hline = ax .axhline (valinit , .25 , .75 , color = initcolor , lw = 1 )
423
+ handleXY = [[0.5 ], [valinit ]]
424
+ self ._above_rect = Rectangle (
425
+ (0.25 , valinit ),
426
+ height = valmax - valinit ,
427
+ width = 0.5 ,
428
+ transform = ax .get_yaxis_transform (),
429
+ )
409
430
else :
410
- self .poly = ax .axvspan (valmin , valinit , 0 , 1 , ** kwargs )
411
- self .vline = ax .axvline (valinit , 0 , 1 , color = initcolor , lw = 1 )
431
+ self .poly = ax .axvspan (valmin , valinit , .25 , .75 , ** kwargs )
432
+ self .vline = ax .axvline (valinit , .25 , .75 , color = initcolor , lw = 1 )
433
+ handleXY = [[valinit ], [0.5 ]]
434
+ self ._above_rect = Rectangle (
435
+ (valinit , 0.25 ),
436
+ width = valmax - valinit ,
437
+ height = 0.5 ,
438
+ transform = ax .get_xaxis_transform (),
439
+ )
440
+ self ._above_rect .set_facecolor ('grey' )
441
+ self ._handle , = ax .plot (
442
+ * handleXY ,
443
+ "o" ,
444
+ markersize = handle_size ,
445
+ markeredgecolor = handle_edgecolor ,
446
+ markerfacecolor = handle_color_released ,
447
+ clip_on = False
448
+ )
449
+ ax .add_patch (self ._above_rect )
450
+
451
+ self ._handle_color_released = handle_color_released
452
+ self ._handle_edgecolor = handle_edgecolor
453
+ if handle_color_grabbed is None :
454
+ handle_color_grabbed = self .poly .get_facecolor ()
455
+ self ._handle_color_grabbed = handle_color_grabbed
412
456
413
457
if orientation == 'vertical' :
414
458
self .label = ax .text (0.5 , 1.02 , label , transform = ax .transAxes ,
@@ -472,7 +516,13 @@ def _update(self, event):
472
516
event .inaxes != self .ax )):
473
517
self .drag_active = False
474
518
event .canvas .release_mouse (self .ax )
519
+ self ._handle .set_markeredgecolor (self ._handle_edgecolor )
520
+ self ._handle .set_markerfacecolor (self ._handle_color_released )
521
+ self .ax .figure .canvas .draw_idle ()
475
522
return
523
+ if event .name == 'button_press_event' :
524
+ self ._handle .set_markeredgecolor (self ._handle_color_grabbed )
525
+ self ._handle .set_markerfacecolor (self ._handle_color_grabbed )
476
526
if self .orientation == 'vertical' :
477
527
val = self ._value_in_bounds (event .ydata )
478
528
else :
@@ -499,11 +549,17 @@ def set_val(self, val):
499
549
"""
500
550
xy = self .poly .xy
501
551
if self .orientation == 'vertical' :
502
- xy [1 ] = 0 , val
503
- xy [2 ] = 1 , val
552
+ xy [1 ] = .25 , val
553
+ xy [2 ] = .75 , val
554
+ self ._above_rect .set_y (val )
555
+ self ._above_rect .set_height (self .valmax - val )
556
+ self ._handle .set_ydata ([val ])
504
557
else :
505
- xy [2 ] = val , 1
506
- xy [3 ] = val , 0
558
+ xy [2 ] = val , .75
559
+ xy [3 ] = val , .25
560
+ self ._above_rect .set_x (val )
561
+ self ._above_rect .set_width (self .valmax - val )
562
+ self ._handle .set_xdata ([val ])
507
563
self .poly .xy = xy
508
564
self .valtext .set_text (self ._format (val ))
509
565
if self .drawon :
@@ -558,6 +614,10 @@ def __init__(
558
614
dragging = True ,
559
615
valstep = None ,
560
616
orientation = "horizontal" ,
617
+ handle_color_grabbed = None ,
618
+ handle_color_released = 'white' ,
619
+ handle_edgecolor = '.75' ,
620
+ handle_size = 10 ,
561
621
** kwargs ,
562
622
):
563
623
"""
@@ -598,6 +658,19 @@ def __init__(
598
658
orientation : {'horizontal', 'vertical'}, default: 'horizontal'
599
659
The orientation of the slider.
600
660
661
+ handle_color_grabbed : color or None, default: None
662
+ The color of the circular slider handles when grabbed. If *None*
663
+ the same color as active part of the slider will be used.
664
+
665
+ handle_color_released : color, default: 'white'
666
+ The color of the circular slider handles when released.
667
+
668
+ handle_edgecolor : color, default: '.75'
669
+ The edgecolor of the circular slider handles.
670
+
671
+ handle_size : int, deafult: 10
672
+ The size of circular slider handles.
673
+
601
674
Notes
602
675
-----
603
676
Additional kwargs are passed on to ``self.poly`` which is the
@@ -620,8 +693,64 @@ def __init__(
620
693
self .valinit = valinit
621
694
if orientation == "vertical" :
622
695
self .poly = ax .axhspan (valinit [0 ], valinit [1 ], 0 , 1 , ** kwargs )
696
+ handleXY_1 = [.5 , valinit [0 ]]
697
+ handleXY_2 = [.5 , valinit [1 ]]
698
+ self ._above_rect = Rectangle (
699
+ (.25 , valinit [1 ]),
700
+ height = valmax - valinit [1 ],
701
+ width = 0.5 ,
702
+ transform = ax .get_yaxis_transform (),
703
+ )
704
+ self ._below_rect = Rectangle (
705
+ (valmin , 0.25 ),
706
+ width = valinit [0 ] - valmin ,
707
+ height = 0.5 ,
708
+ transform = ax .get_xaxis_transform (),
709
+ )
623
710
else :
624
711
self .poly = ax .axvspan (valinit [0 ], valinit [1 ], 0 , 1 , ** kwargs )
712
+ handleXY_1 = [valinit [0 ], .5 ]
713
+ handleXY_2 = [valinit [1 ], .5 ]
714
+ self ._above_rect = Rectangle (
715
+ (valinit [1 ], 0.25 ),
716
+ width = valmax - valinit [1 ],
717
+ height = 0.5 ,
718
+ transform = ax .get_xaxis_transform (),
719
+ )
720
+ self ._below_rect = Rectangle (
721
+ (valmin , 0.25 ),
722
+ width = valinit [0 ] - valmin ,
723
+ height = 0.5 ,
724
+ transform = ax .get_xaxis_transform (),
725
+ )
726
+ self ._above_rect .set_facecolor ('grey' )
727
+ self ._below_rect .set_facecolor ('grey' )
728
+ ax .add_patch (self ._above_rect )
729
+ ax .add_patch (self ._below_rect )
730
+ self ._handles = [
731
+ ax .plot (
732
+ * handleXY_1 ,
733
+ "o" ,
734
+ markersize = handle_size ,
735
+ markeredgecolor = handle_edgecolor ,
736
+ markerfacecolor = handle_color_released ,
737
+ clip_on = False
738
+ )[0 ],
739
+ ax .plot (
740
+ * handleXY_2 ,
741
+ "o" ,
742
+ markersize = handle_size ,
743
+ markeredgecolor = handle_edgecolor ,
744
+ markerfacecolor = handle_color_released ,
745
+ clip_on = False
746
+ )[0 ]
747
+ ]
748
+
749
+ self ._handle_color_released = handle_color_released
750
+ self ._handle_edgecolor = handle_edgecolor
751
+ if handle_color_grabbed is None :
752
+ handle_color_grabbed = self .poly .get_facecolor ()
753
+ self ._handle_color_grabbed = handle_color_grabbed
625
754
626
755
if orientation == "vertical" :
627
756
self .label = ax .text (
@@ -660,6 +789,7 @@ def __init__(
660
789
horizontalalignment = "left" ,
661
790
)
662
791
792
+ self ._active_handle = None
663
793
self .set_val (valinit )
664
794
665
795
def _min_in_bounds (self , min ):
@@ -696,6 +826,8 @@ def _update_val_from_pos(self, pos):
696
826
else :
697
827
val = self ._max_in_bounds (pos )
698
828
self .set_max (val )
829
+ if self ._active_handle :
830
+ self ._active_handle .set_xdata ([val ])
699
831
700
832
def _update (self , event ):
701
833
"""Update the slider position."""
@@ -714,7 +846,33 @@ def _update(self, event):
714
846
):
715
847
self .drag_active = False
716
848
event .canvas .release_mouse (self .ax )
849
+ self .ax .figure .canvas .draw_idle ()
850
+ for handle in self ._handles :
851
+ handle .set_markeredgecolor (self ._handle_edgecolor )
852
+ handle .set_markerfacecolor (self ._handle_color_released )
853
+ self ._active_handle = None
717
854
return
855
+
856
+ # determine which handle was grabbed
857
+ handle = self ._handles [
858
+ np .argmin (
859
+ np .abs ([h .get_xdata ()[0 ] - event .xdata for h in self ._handles ])
860
+ )
861
+ ]
862
+ # these checks ensure smooth behavior if the handles swap which one
863
+ # has a higher value. i.e. if one is dragged over and past the other.
864
+ if handle is not self ._active_handle :
865
+ if self ._active_handle is not None :
866
+ self ._active_handle .set_markeredgecolor (
867
+ self ._handle_edgecolor
868
+ )
869
+ self ._active_handle .set_markerfacecolor (
870
+ self ._handle_color_released
871
+ )
872
+ self ._active_handle = handle
873
+ self ._active_handle .set_markeredgecolor (self ._handle_color_grabbed )
874
+ self ._active_handle .set_markerfacecolor (self ._handle_color_grabbed )
875
+
718
876
if self .orientation == "vertical" :
719
877
self ._update_val_from_pos (event .ydata )
720
878
else :
@@ -771,17 +929,23 @@ def set_val(self, val):
771
929
val [1 ] = self ._max_in_bounds (val [1 ])
772
930
xy = self .poly .xy
773
931
if self .orientation == "vertical" :
774
- xy [0 ] = 0 , val [0 ]
775
- xy [1 ] = 0 , val [1 ]
776
- xy [2 ] = 1 , val [1 ]
777
- xy [3 ] = 1 , val [0 ]
778
- xy [4 ] = 0 , val [0 ]
932
+ xy [0 ] = .25 , val [0 ]
933
+ xy [1 ] = .25 , val [1 ]
934
+ xy [2 ] = .75 , val [1 ]
935
+ xy [3 ] = .75 , val [0 ]
936
+ xy [4 ] = .25 , val [0 ]
937
+ self ._above_rect .set_height (self .valmax - val [1 ])
938
+ self ._above_rect .set_y (val [1 ])
939
+ self ._below_rect .set_height (val [0 ] - self .valmin )
779
940
else :
780
- xy [0 ] = val [0 ], 0
781
- xy [1 ] = val [0 ], 1
782
- xy [2 ] = val [1 ], 1
783
- xy [3 ] = val [1 ], 0
784
- xy [4 ] = val [0 ], 0
941
+ xy [0 ] = val [0 ], .25
942
+ xy [1 ] = val [0 ], .75
943
+ xy [2 ] = val [1 ], .75
944
+ xy [3 ] = val [1 ], .25
945
+ xy [4 ] = val [0 ], .25
946
+ self ._above_rect .set_width (self .valmax - val [1 ])
947
+ self ._above_rect .set_x (val [1 ])
948
+ self ._below_rect .set_width (val [0 ] - self .valmin )
785
949
self .poly .xy = xy
786
950
self .valtext .set_text (self ._format (val ))
787
951
if self .drawon :
0 commit comments