Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Update Slider Range (valmin and valmax)#30556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
melwyncarlo wants to merge13 commits intomatplotlib:main
base:main
Choose a base branch
Loading
frommelwyncarlo:main

Conversation

melwyncarlo
Copy link

Added two functions:

  1. update_range in class Slider
  2. update_bounds in class SliderBase

PR summary

This PR is a solution to issue#30555 and thisdiscourse.matplotlib.org post.
This PRcloses#30555.

Thisvideo demonstrates the change.

Added two functions:1. update_range in class Slider2. update_bounds in class SliderBase
Copy link
Member

@timhoffmtimhoffm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks for the contribution.

Comment on lines 608 to 609
val=self._value_in_bounds(self.val)
ifvalnotin [None,self.val]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Can val be None here? I thought_value_in_bounds always returns a value (coerced if necessary). Please recheck.

Also, please add a remark to the docstring what happens to the value if bounds change so that it's outside.
Also, please check what happens to the existing value if it is in bounds and document that. Can it change because the steps are now different.
Also, I thinkset_val() updates the slider rectangle so even if the value does not change, e.g. val=5 valstep1; change range from (1, 7) to (3, 9) -> val does not change, but the slider position changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Here's an example where_value_in_bounds returnsNone:

def_value_in_bounds(self,val):
"""Makes sure *val* is with given bounds."""
val=self._stepped_value(val)
ifval<=self.valmin:
ifnotself.closedmin:
return

Here's another example where the_value_in_bounds result is checked forNone:

valinit=self._value_in_bounds(valinit)
ifvalinitisNone:
valinit=valmin


Whether the value is within or outside bounds does not matter; slider, bounds, and val change accordingly. (I don't know how to document that.)

Yes, regarding your last statement. The val does not change, but the slider position changes. That is intended.5 is within(1, 7) and within(3, 9) as well, soval doesNOT change. The slider position changes because the limits change: in(1, 7),5 is4 positions away, but in(3, 9),5 is only2 positions away, and so the slider goes downward.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Oh, nevermind the None value. I've overlooked this.

slider, bounds, and val change accordingly. (I don't know how to document that.)

Something like "The slider value is coerced to the nearest valid position based on the limits and valstep." (if that's the actual behavior, which I would intuitively expect).

The slider position changes

Ok so there's some kind of automatic update/draw triggered. That's what I wanted to ensure [not an expert in the widgets topic.

melwyncarlo reacted with thumbs up emoji
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yes, there is an automatic update triggered.
Also, I have updated the docstring as per your suggestion (slider value is coerced to nearest . . .).

melwyncarloand others added9 commitsSeptember 15, 2025 20:55
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com>
Copy link
Member

@timhoffmtimhoffm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I'm considering a name different fromupdate_range() because if we want to later expand this toRangeSlider, thererange also has a dedicated and different meaning.

update_limits() would be good in terms of valmin, valmax, but is slightly worse in expressing that it also covers valstep. It would be nice if we could come up with something even better, but if not I would go withupdate_limits

@melwyncarlo
Copy link
Author

I'm considering a name different fromupdate_range() because if we want to later expand this toRangeSlider, thererange also has a dedicated and different meaning.

update_limits() would be good in terms of valmin, valmax, but is slightly worse in expressing that it also covers valstep. It would be nice if we could come up with something even better, but if not I would go withupdate_limits

range sounds more generic whereaslimits imply just upper and lower bounds.
The termrange should not clash withRangeSlider as it's a commonly used word when speaking about any slider.
Synonyms forrange are as follows:span,scope,scale,extent
Regardless, it's upto you to choose the name.
I choseupdate_range because that was suggested on theMatplotlib Discourse post.

@timhoffm
Copy link
Member

The point is that "Range" in RangeSlider refers to the value range, whereas inset_range() it would refer to the definition range.
Using the same word for different aspects in the same context is confusing.

image
melwyncarlo reacted with thumbs up emoji

@melwyncarlo
Copy link
Author

Oh, okay, yes, that's confusing. You can set the appropriate function name.

@timhoffm
Copy link
Member

timhoffm commentedSep 19, 2025
edited
Loading

Semi-OT: While thinking about naming and howvalstep is integrated into that, I realized that we have some sloppy behavior / unclear definitions. We can have the following cases forvalstep:

  • None - continuous slider [ok]
  • number: stepped slider, basically atnp.arange(valmin, valmax, valstep) [ok]
  • array_like: Explicitly giben values - these may be outside the interval [valmin, valmax] with surprising behavior: During operation via UI, the valstep values are effectively clipped by [valmin, valmax] because you can't move the handler past the limits. But you canset_val() to a valstep value outside the interval, in which case the slider button vanishes. There are also some other quirks already on initialization ifval, is not invalstep.

Overall, the interaction between val, array-like valstep and valmin/valmax is ill-defined.

Why is this relevant for this PR? Selective changes of valstep, valmin, valmax make this inconsistency worse. The way out of the inconsistency may affect the the way we specify the data range and thus how the API to modify must look like.


Edit: Additional issue: we cannot useset_range(...valstep=None) in the meaning "keep the existing value" becausevalstep=None is used to indicate a continuous range. - Preliminary way out: do not support "keep the existing value".

We can later add that behavior by using custom sentinels as default.


Edit: Ok the way forward is the following:

  • Ifvalstep is array-like, we must raise a value error ifvalmin != valstep[0] or valmax == valstep[-1].
  • Let's call the new functiondef set_limits(valmin, valmax, valstep=None). The continuous caseset_limits(vmin, vmax) is the default and reads good. If we stretch the "limit" interpreation from boundary to "limit the accepted values", also the inclusion ofvalstep makes sense.

@melwyncarlo
Copy link
Author

Edit: Additional issue: we cannot useset_range(... valstep=None) in the meaning "keep the existing value" becausevalstep=None is used to indicate a continuous range. - Preliminary way out: do not support "keep the existing value".

vs.

Let's call the new functiondef set_limits(valmin, valmax, valstep=None)

I'm confused. Are we going withvalstep=None or just plainvalstep?
Also, why are the defaultNone values missing forvalmin andvalmax? Weren't they required to allow the user to set either one? (not everyone wants to set bothvalmin andvalmax simultaneously every time.

As an alternative, what are your thoughts on implementinggetter/setter properties instead?
Because even if we implement theset_limits() function,valmin,valmax, andvalstep are still accessible to be modified directly.


Whenvalstep is array-like and outside of thevalmin/valmax bounds, I cannot reproduce the slider vanishing. For example, forvalmin = 1 andvalmax = 10, I triedvalstep = [3, 5, 7] andvalstep = [0, 4, 8, 12]. The slider does not vanish.

But you're right that a check is required. About that,valmin != valstep[0] or valmax == valstep[-1] might not work, as thevalstep values can beunordered/non-sorted.
Even for unorderedvalstep, I see no issues when running it (I'm guessing this is intended behaviour?). But if we have to do the check, then maybe we should check againstsorted(valstep)?

Also, should there be a check forvalmin andvalmax too? Currently, even ifvalmin > valmax, the program runs, but the slider remains stuck. Is this intended?


Regarding the sentinel, some functions tend to use the'none' string to implyNone, leavingNone to be used as the sentinel itself, as intended. For example, theinterpolation parameter in theAxes.imshow function has 'none'(string) as one of its values, leaving the default toNone. (Reference)

Just a thought, maybe we could do the inverse and set 'none'(string) as the sentinel?
Or maybe set a global variable:SENTINEL = object() and use that instead?

@timhoffm
Copy link
Member

timhoffm commentedSep 26, 2025
edited
Loading

Let's call the new functiondef set_limits(valmin, valmax, valstep=None)

I'm confused. Are we going withvalstep=None or just plainvalstep? Also, why are the defaultNone values missing forvalmin andvalmax? Weren't they required to allow the user to set either one? (not everyone wants to set bothvalmin andvalmax simultaneously every time.

valstep=None with the meaning of "no step". This maps the behavior from__init__, i.e. always set everything. The default is there since many sliders are not step-limited, so typingset_limits(valmin, valmax, valstep) would be awkward.

As an alternative, what are your thoughts on implementinggetter/setter properties instead? Because even if we implement theset_limits() function,valmin,valmax, andvalstep are still accessible to be modified directly.

We should possibly make the attributes private. Individual setters are not a good option. They are more cumbersome to useset_valmin(a); set_valmin(b) and there might be surprising interference with valmin, valmax and step if applied sequentially.


I think the boundary conditions for explict step values are not well thought through and not handled consistently. But the problem is not getting worse if we limit ourselves for now to the "always set everything" approach. As it is as good or bad as setting on__init___. We can then handle this topic later.


Yes, a sentinel object, would be the way to go. We have one here

.
But as said, partial setting introduces additional complexity and the need for better validation. I propose to defer this we can later always move from

def set_limits(valmin, valmax, valstep=None)`

to

def set_limits(valmin=_Unset, valmax_Unset, valstep=_Unset)`

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@timhoffmtimhoffmtimhoffm left review comments

At least 1 approving review is required to merge this pull request.

Assignees
No one assigned
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

[ENH]: Update Slider Range (valmin and valmax)
2 participants
@melwyncarlo@timhoffm

[8]ページ先頭

©2009-2025 Movatter.jp