An On/Off button alternative to CheckBox

Yes, pressing the “Minimum Mono” icon toggles the normal size mono on the left.
Tested with Windows 10.

@komto48g Sorry, but I’m not seeing it.
Unhelpfully, I labelled 4 of the demo buttons Minimum Mono, however each has its own name.

If you run this code from the command line, I print out the switch name and Id for identification purposes, just in case of this sort of issue.

Could you tell me which icon is being clicked and which is reacting, if possible by name or if not by position on the demo screen.
Also, just to be clear, is the clicked button reacting as well or is the clicked button doing nothing and the other button reacting instead?
Either I am blind or something queer is occurring.

Regards,
Rolf

The mini button does nothing and the other button reacts instead. Here is the snapshot:
AGDRec_20230222_013246.agm_clip.mp4

1 Like

@komoto48g I have finally worked out, that you are clicking on the overlapping multi-line label from the button on the left.
If you change self.onoff10 to be positioned further to the right e.g. (200,550)

self.onoff10 = OnOffButton(panel, -1, "Minimum Mono 4", pos=(200, 550),\
                                      initial=0, mono=True, circle=False, internal_style=2, name="10a")

That problem should stop happening.
To see the full extent of the label of self.onoff9 simply give it a background colour e.g.

self.onoff9.SetBackgroundColour("#bfefff") # lightblue

Let’s hope that is the answer or I’m flummoxed :grimacing:

perfect :smiling_face_with_three_hearts:

@da-dada Thanks! :grinning:

@rolfofsaxony pos=(250, 550) is better but slightly overlaps.

image

Just a layout issue, however, overlapping controls will cause z-order issues discussed here.
The problem is not the z-order itself but it is that gtk and win32 seem to behave differently.

The latest version 1.16.1 onoffbutton.py (33.3 KB)

1.16.1 Change Log

  • Alter demonstration to use sizers to avoid layout differences between gtk and other platforms
  • Minor change to alignment of icon and label for aesthetic reasons
  • Fix for Font change where self.GetFont was used instead of self.label.GetFont
    this could cause a truncated label
  • Font style flashes between Slant for Off and Normal for On

I’ve posted an updated version which uses sizers for the demonstration, to resolve OS layout differences

Yeah, using sizers could make the layout more platform-independent.
I like your idea of highlighting the on/off button by size, color, and direction because of its high visibility.

TBH, the last change seems unnecessary to me… :face_with_hand_over_mouth:

I agree! It was far too fussy.
The next release will lose it.

Hopefully the last version ( for a while :wink: )

OnOffButton Version 1.17.2 (thanks to ZigZag/Ecco for testing on Windows)

Change Log:
1.17.2 Add highlighting colour to Border, principally for darkgrounds
Add internal_style OOB_SOFTRECTANGLE (Value 4) A rectangle with slightly rounded corners
Suggestions from ZigZag/Ecco

1.17.1 Fix bug calculating inner and outer radius which resulted in a float instead of an integer
this could affect round radio buttons with a size parameter containing different width and height values
Attempt to shift focus to next or previous widget, if focused widget is disabled
Fix for wxpython < 4.1 Colour has no option GetLuminance()
Micro adjustments to positioning
Include style wx.TRANSPARENT

1.17.0 Track focus by way of underlining Label Text if the control has Focus
return to normal Label Text if focus is lost
Font style flashing between Slant for Off and Normal for On - Removed
as too fussy, especially as I’m now tracking focus with Underlined text

    Why Underline and not a dotted box?
    Under Gtk StaticText doesn't appear to receive Paint events but wx.lib.stattext, which does,
     doesn't allow mnemonics and I want the mnemonics.
    So stuck between the devil and the deep blue sea, I've run with Underline

1.16.3 Allow spacebar key to toggle the onoffbutton.
All colours in the demonstration to hex codes
Changed demonstration to use a FlexGridSizer to accomodate smaller screens.

1.16.2 Minor adjustment to set minimum size for alignment
also prevents fractional cropping of image aligned to the right

onoffbutton.py (38.5 KB)

Also

OnOffButtonBox Version 1.2.3 (again thanks to ZigZag/Ecco for testing on Windows)

Change Log:
1.2.3 OnOffButton’s from version 1.17.2 include a new option OOB_SOFTRECTANGLE
This is included in the demonstration.

1.2.2 Spacebar Key is now a legitimate onoffbutton selector
To accomodate tabbing between widgets, the helpcontext button has focus disabled from the keyboard
add the last legitimate onoffbutton with focus is logged for reinstatement of focus
OnOffButton’s from version 1.17.0 now track focus with Underlined text

1.2.2 GridSizer replaced with FlexGridSizer, as the GridSizer compressed its contents
when the window was resized.
Amended for Windows OS layout differences
extended gap between widgets
added extra space around box
Added sizer flag wx.RESERVE_SPACE_EVEN_IF_HIDDEN

onoffbuttonbox.py (29.8 KB)

It’s the end of the month, so despite my hopes for onoffbutton changes being ended, here is the latest version.

Change Log:
1.18.0  Tracking focus, changes from underlining text to a rounded rectangle perimeter
         Achieved by adding focus bitmaps and expanding the bitmaps stated size, to cater for a Focus indicator area
        Pressing Alt Key on its own, identifies which widget has Focus
        Alt Key plus mnemonic continues to function as normal
        The default grey background has changed from #787878 (grey47) to #bfbfbf (grey75)
         for better contrast
        Minimum height has changed from 16 to 17 for better centring of the indicator.
        If the On or Off foreground colours are adjusted, the edge pen colour is adjusted for contrast
        Function SetOnOffColours added, which combines 4 colour functions, updating the images only once
        Internal style Arrow calculations change from using bitmap size, to use SetImageSize values for consistency
        Added functions:
            GetFocusStyle() and SetFocusStyle(style)

The big change is Focus tracking moving from underscored text to a visual perimeter for the control.
Focus has style, wx.PENSTYLE_SOLID is the default, wx.PENSTYLE_DOT is another good option and wx.PENSTYLE_TRANSPARENT should be used if you do not require a Focus indicator.

onoffbuttonbox.py (30.8 KB) onoffbutton.py (43.0 KB)

Oh Dear, just a month later and it’s time to issue Version 2.1.0

Principally, I’ve added
new button types
new alignment styles
and the ability to add your own images to be used as On/Off buttons.

the full changelog is below.

This zip file contains:
onoffbutton.py
onoffbuttonbox.py (used to select one of a number of mutually exclusive choices.)
onoffbuttonlist.py (used to select zero or more choices from a range of choices.)
The images used by the demonstration

onoff.zip (235.3 KB)

Regards,
Rolf

examples of the buttons available in the demonstrations:
onoffbutton

onoffbuttonbox

onoffbuttonlist

Change Log:
2.1.0 wx.StaticText has resizing issues on font change
https://github.com/wxWidgets/Phoenix/issues/1228
https://github.com/wxWidgets/wxWidgets/issues/16088
Whilst wx.lib.stattext.GenStaticText avoids these issues it does not appear to handle mnemonics
The problem has been resolved by using GetTextExtent and DoGetBestSize

    Added user supplied On and Off images with optional supplied focus images
    If focus images are supplied, supplied images do not require offsetting to allow for focus indicators
    If images are supplied, the ratio for rescaling is taken from the width/height ratio of the On image supplied.
     This is applied if no size or a partial size is given.

2.0.0 Depending on wxPython values for alignment of the control, proved somewhat confusing, so all alignment
values have become internal:
aligning to the left (default) is now controlled by OOB_LEFT
right by OOB_RIGHT
top by OOB_TOP
and bottom by OOB_BOTTOM
The alignment style changes, from being in the standard style parameter, to the internal_style parameter

    All of the above occurs as 2 new alignment styles are added.
    In addition to aligning the control to the Left or Right of the text, you may now align the control
    above (OOB_TOP) or below (OOB_BOTTOM) the text.

    When aligning a control Top or Bottom, this can be combined with Left or Right, so the control and text
    are aligned Left or Right, above one another. The default is Centred, one above the other.

    rotate is a new parameter, which will rotate the control image through 90° giving a vertical control, like
    a lightswitch.
    default is 0 - None | > 0 = 90° clockwise (On at the bottom) | < 0 = 90° anti-clockwise (On at the top)

    Additional micro alignment adjustments have been made

    Default OOB_CIRCLE given a fractional overlap for aesthetic reasons

    Changed the base Bitmap to depth=32, to ensure that a transparent bitmap can be created.
    This allows a transparent brush to be used if no background colour is specfied.
    This also caters to controls that are placed on a gradient coloured background.
    The downside is that you have to remember to include wx.TRANSPARENT_WINDOW if you override style.

    Set foreground colour based on background colour for visibility of control's simple border,
     if set, in dark mode.

    Adds internal_style OOB_GRADIENT a rectangular button using a gradient between colour On and colour Off
    Adds internal_style OOB_RADIOCHECK a radio button containing a Check mark when on
    Remove spacing function as a step too far.
    Demonstration now set in a scrolled panel for ease of use and includes extra option examples

1.19.0 Adds an internal call to Layout for those using direct positioning not sizers.
Adds internal_style OOB_BULLET

Thank you for your work, tho there is at least 1 bug haha.

Its not really mouse based…

onoffbuttonbox.py on MSW 7 does a double click/two note type of thing. on=on or off=off etc …

… otherwise … it looks like the rest of the work i was going to put into ShapedBitmapButton

It appears that it needs a bit of testing and then optimization. :slight_smile:

I see that you have put in the time to deserve a “Thank you”
Thank you.

Sorry Metallicow, I am not sure what you are describing, when you say:

does a double click/two note type of thing. on=on or off=off etc

Could you be more specific?

I’ll look at it, to see if it’s a coding error but I don’t have access to a windows machine to test it, if it is a platform issue.

Regards,
Rolf

I’ve briefly looked over the file(s)…

On interaction of the click on some of the “WIDGETS” in MSW(os) if the radio(groups…)(well call it a button…) is already clicked or prominent or high-lighted as THE choice… It doesn’t matter if it is flipped 90degrees… If it is already ON, then consider all options and optimize the answer to be OFF and execute that event only once. There is absolutely no reason to fire the event twice in most all instances. A subclass of the class could take care of any “ummmmm, idunno instances”

NOW… this would be very important if you was already “on the ground” and a step ahead if the (interpreted object) might be a breaker box… followed by a bunch of switches…
NOTE: There is no magical way to transport yourself from bed at 4:01 AM in the morning to just go magically flip a switch twice HAHA. … see what I mean…

… so besides that there are some optimizations I recognized just skimming though the files.
I noticed a few places where you could kill dots…
for example:

self.circonpos = circonpos
...
circonpos

...
or
[circonpos for widget in widgetList]

if it is used more than 2-3 times… take it out of a loop or if group. You used it 6 or more times… small things like this will be very important if you use if/else type of NO ‘for loop’ types of style of writing…

The long drawn out answer is… if the switch is already ON, and I click it… It should switch OFF with 1 event, NOT On-Off->On. This logic contains no points in reality like Blender’s format.

Thank you, I hope you understand. I cannot do core testing for you due to the scope of the widget.

… also WHY did you write a widget in wxpython and not give it a wxwidget license… it will never get accepted into the main c++ library otherwise… plus you screw a few folks downstream when you do that…

… anyhow Thanks for the widget. If you have more questions, feel free to ask…

Take a look at my ShapedBitmapButton if you are a bit confused with how the “proper ways” to write them are. The only difference is if you want someone to PORT your work back upstream easily… If your framework follows the same workflow, x100 will the compiled c/c++ version if they ever get to it haha.

Thankee Sai

well, not only the box behaviour is peculiar on Windows :roll_eyes:

@Metallicow and @da-dada
I appreciate you both chipping in to make the onoffbuttonbox better than it currently is.

It is based on a button that is either On or Off. Like a radio button.
This onoffbuttonbox configuration, was added in an attempt to emulate the radiobox of WxPython, the fact that you clicked on a button, means that you either turned it off or on
In a buttonbox, irrespective of its current value, it will swap to the opposite one, thus if it was already the selected item in the buttonbox, it has to be turned back on for the buttonbox to maintain its integrity.
Sadly, I see no logical way of predetermining that it’s value should not be swapped when clicked.
I don’t know how the radiobox deals with this but I suspect it does the same thing.
I’m happy to be proven wrong and if so, I’m equally happy to change the code.

Currently, I see no way around it.

Regards,
Rolf.

p.s.

I noticed a few places where you could kill dots…

I genuinely have no idea, what you are referring to with this statement

well, not only the box behaviour is peculiar on Windows

If there is something else you have taken issue with, please say what it is.
Cryptic messages issued whilst rolling your eyes, performs no function whatsoever. :no_mouth:

Regards the license, I tend to throw a GPL license in there just for form, rather than any real desire to stamp a copyright all over the place. In essence, if I publish the code, anyone can pinch bits or the whole thing, just so long as they don’t subsequently apply their own copyright to it.
In that regard, any license which achieves the same thing could be applied, I have simply never bothered to look into it.

places where you could kill dots…

Ok, got it, I was having an obtuse moment.
You are referring to local variables versus instance variables.

well, besides the somewhat random behaviour of the TAB traversal amongst the boxes (use of ALT in between) I think in order to emulate a wx.RadioBox there should be some other controls within the box (see example demo with text field) which are selected before the next control outside the box is tabbed to :disappointed_relieved: