An On/Off button alternative to CheckBox

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:

  • Maybe my obtuse moment has been extended but I see nothing random in the TAB traversal at all, either forwards or backwards. It moves from one control to the next.
    Does TAB traversal work in a completely different way on Windows?
    Or are you taking issue with the fact that I am allowing you to TAB between each individual control, within a buttonbox, rather than instantly moving on to the next buttonbox?

  • "I think in order to emulate a wx.RadioBox there should be some other controls within the box which are selected **before** the next control outside the box is tabbed to".
    If some other controls were within the box, it would not be an OnOffbuttonbox. It would be some wierd hybrid control.
    Clearly, I have not understood your point here.

start onoffbuttonbox.py, click B5-1, click B5-3, TAB forward and B5-2 is selected
start onoffbuttonbox.py, click B5-1, click B5-3, click B5-1, press ALT and B5-3 is selected
I don’t know the distribution, but somewhat random :rofl:

well, the gist of a radio button box is the one control character as far as TAB traversal is concerned because it is not on-off rather single choice of alternatives :stuck_out_tongue_winking_eye:

this is indeed taken wx further (demo RadioButton) and a nice demonstration of what a real radio button can do :joy:

Without a full keyboard, I can laugh at you. I am mobile. If call an action on an action, would you still be president…

Give me a few days and maybe I can make the “interpretation” clearer in code and words. I am not good with documentation or disputes…
Ok. Ok. Ok.

p.s. I will try to review all files as one… Don’t hold your breath. I won’t.

inhales

Rightly so dear sir or madam.
…So what is it lol…

well, Radio for check box lovers (based on RadioButton of Demo) :smiling_face_with_three_hearts:

import wx
import wx.lib.platebtn as pb

#----------------------------------------------------------------------

class Frame( wx.Frame):
    def __init__( self, parent):

        super().__init__(
            parent, title='Radio for checkbox lovers', size=(330, 300))
        pnl = wx.Panel( self)

        # Layout controls on panel:
        vbox = wx.BoxSizer( wx.VERTICAL )

        box1_title = wx.StaticBox( pnl, -1, "Group 1" )
        box1 = wx.StaticBoxSizer( box1_title, wx.VERTICAL )
        grid1 = wx.FlexGridSizer( cols=2 )

        # 1st group of controls:
        self.group1_ctrls = []
        radio1 = wx.RadioButton( pnl, -1, " Radio1", style = wx.RB_GROUP )
        radio2 = wx.RadioButton( pnl, -1, " Radio2" )
        radio3 = wx.RadioButton( pnl, -1, " Radio3" )
        self.group1_ctrls.append((radio1, pb.PlateButton(pnl)))
        self.group1_ctrls.append((radio2, pb.PlateButton(pnl)))
        self.group1_ctrls.append((radio3, pb.PlateButton(pnl)))

        for radio, text in self.group1_ctrls:
            grid1.Add( radio, 0, wx.ALIGN_CENTRE|wx.LEFT|wx.RIGHT|wx.TOP, 5 )
            grid1.Add( text, 0, wx.ALIGN_CENTRE|wx.LEFT|wx.RIGHT|wx.TOP, 5 )

        box1.Add( grid1, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
        vbox.Add( box1, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )

        box2_title = wx.StaticBox( pnl, -1, "Group 2" )
        box2 = wx.StaticBoxSizer( box2_title, wx.VERTICAL )
        grid2 = wx.FlexGridSizer( cols=2 )

        # 2nd group of controls:
        self.group2_ctrls = []
        radio4 = wx.RadioButton( pnl, -1, " Radio1", style = wx.RB_GROUP )
        radio5 = wx.RadioButton( pnl, -1, " Radio2" )
        radio6 = wx.RadioButton( pnl, -1, " Radio3" )
        self.group2_ctrls.append((radio4, pb.PlateButton(pnl)))
        self.group2_ctrls.append((radio5, pb.PlateButton(pnl)))
        self.group2_ctrls.append((radio6, pb.PlateButton(pnl)))

        for radio, text in self.group2_ctrls:
            grid2.Add( radio, 0, wx.ALIGN_CENTRE|wx.LEFT|wx.RIGHT|wx.TOP, 5 )
            grid2.Add( text, 0, wx.ALIGN_CENTRE|wx.LEFT|wx.RIGHT|wx.TOP, 5 )

        box2.Add( grid2, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
        vbox.Add( box2, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )
        self.icon = wx.ArtProvider.GetBitmap(wx.ART_TICK_MARK)
        self.bbmp = wx.Bitmap(1,1)
        self.bbmp.SetMaskColour('black')

        pnl.SetSizer( vbox )
        self.Show()

        # Setup event handling and initial state for controls:
        for radio, text in self.group1_ctrls:
            self.Bind(wx.EVT_RADIOBUTTON, self.OnGroup1Select, radio )

        for radio, text in self.group2_ctrls:
            self.Bind(wx.EVT_RADIOBUTTON, self.OnGroup2Select, radio )

        for radio, text in self.group1_ctrls + self.group2_ctrls:
            radio.SetValue(0)
            text.Enable(False)

    def OnGroup1Select( self, event ):
        radio_selected = event.GetEventObject()
        print('Group1 %s selected\n' % radio_selected.GetLabel() )

        for radio, text in self.group1_ctrls:
            if radio is radio_selected:
                text.SetBitmap(self.icon)
            else:
                text.SetBitmap(self.bbmp)
            text.Refresh()

    def OnGroup2Select( self, event ):
        radio_selected = event.GetEventObject()
        print('Group2 %s selected\n' % radio_selected.GetLabel())

        for radio, text in self.group2_ctrls:
            if radio is radio_selected:
                text.SetBitmap(self.icon)
            else:
                text.SetBitmap(self.bbmp)
            text.Refresh()

app = wx.App()
Frame(None)
app.MainLoop()

@Metallicow @da-dada
Before this gets out of hand :slight_smile: I’m working on it.

I’ve resolved the don’t double flip the control, if it is already on and I currently working through adding the concept of RB_GROUP functionality to onoffbuttons, which should make them behave more like radio buttons if placed in a group, which placing them in an onoffbuttonbox, would automatically do.

Bear with me !
(I’ve got hundreds of ancient olive trees to prune at the same time)

Regards,
Rolf

Yea there seems to be a misunderstanding of buttonbox and radiobox lol…

A ButtonBox should operate like a ‘breakerbox’… If you flip a switch it turns off… other switches can still be on.

A RadioBox is a grouping of buttons where only one option(or button) can be on at any givin time. On some operating systems upon startup if a option is not specified in code as a default, then the first optionRadio becomes the On(or default) as if it was being lazily initialized.

I looked more at your files and seen it isn’t as complex as I thought it would be. It isn’t classed out to really be ready to be straight ported into wxWidgets like ShapedBitmapButton is, tho it should be(that was one of the things I had on a TODO when I ported CheckBox to pure python).

Also the brightness/luminance stuff isn’t really gpl-able. its basically public information about a curve(I put links in attached file with pure python code)

I have attached a link to a modified file for OnOffButtonBoxMCOW.py It fixes the goofy behaviour with essentially a one-liner of logic.

If you want to make it operate like a RadioBox, then I suggest to subclass the class and overwrite that one event function so that you check all widgets if are on before turning all/some off, and then switching the one widget clicked on on in one swoop event.

… Maybe at some point I’ll get around to properly creating this all as a pure python ButtonBox/RadioBox as was on my TODO list to be included in the standard wxPy lib… but this works for now as a quick drag and drop file for most folks. Thanks again :slight_smile:

onoffbuttonboxMCOW.py (39.8 KB)

Yea I recall Cody had made some widgets for his code editor. I recall making some fixes to them so that they would run on Phoenix. Not sure if those widgets was ever on a TODO list to be ported into the main wxPy lib but I recall there was a bit more work to be done to be considered properly done…

well, I’ve to admit I like workables rather than (foggy) TODOs: his platebtn seems to work on Windows & has a touch of Google (using style=pb.PB_STYLE_NOBG) :joy:

Find attached Version 3.0.0 of OnOffButton
onoff-3.0.0.zip (526.9 KB)

@da-dada I have added some hybrid demonstrations, based on the wx.RadioButton demo, although I still have my doiubts about whether the tabbing will behave itself on Windows, as it does on Linux. My gut feel, is that it is something to do with Focus.

Hybrid_Onoff_demo

The changelog:

3.0.0   Added initial parameter oob_group_id to enable onoffbutton groups, similar to wx.RadioButton groups.

        Override the AcceptsFocusFromKeyboard function which controls the focus of items in the same group.
        This should resolve previous tabbing issues, when used in an onoffbuttonbox.

        Added keys wx.WXK_UP and wx.WXK_DOWN to the available navigation keys.
         wx.WXK_UP acts the same as wx.WXK_LEFT
         wx.WXK_DOWN acts the same as wx.WXK_RIGHT

        Added function GetGroupId()
        Added function GetGroupmembers()

        Change to check if the onoffbutton is in an onoffbutton group
         if it is and it is already the selected item in that group, do not process the selection by click or keyboard.
         This causes unnecessary events.

        Added test in OnFocus to check if Mnemonic key is currently depressed in a group item and if so Select button.
        This is required because normally a group can only have 1 item selected and rejects attempts to focus any
         other item. This bypasses that restriction, allowing mnemonics to function in an onoffradiobox.

        Added new demonstration program hybriddemo.py, which illustrates using onoffbuttons in groups,
         not in an onoffbuttonbox, emulating the wxPython demo of ../wxPython-demo-4.2.1/demo/RadioButton.py

        Added new demonstration program hybriddemo2.py, which illustrates using onoffbuttons in groups,
         not in an onoffbuttonbox, with a sub group of an OnOffButtonList with mnemonics

        Added new demonstration program hybriddemo3.py, which illustrates using onoffbuttons in groups,
         not in an onoffbuttonbox, with a sub group of an OnOffButtonBox with mnemonics

@Metallicow

there seems to be a misunderstanding of buttonbox and radiobox lol…

Yes indeed.

  • The onoffbutton attempts to offer an alternative to both a checkbox and a radiobutton.

  • In addition it offers a list facility (multiple choice from many) and a box facility (one from a number of mutually exclusive choices)

In essence it is neither but tries hard to operate as either.

I suspect that Version 3.0.0 is still a work in progress, until someone on a Windows platform can isolate an issues with the Focus/Tabbing that has been reported.

As usual, bugs, comments and insults, on a postcard please.
Regards,
Rolf

@rolfofsaxony well done :joy:

the only wee difference to the wxPython versions I have noticed is at the start where the first TAB jumps to

I tested your onoff-3.0.0 o MSW7-10 and the button/radiobox doesn’t resemble a buttonbox as per description. Maybe you should re-look over my one-liner.
It is a event based command I make. A one liner. If widget is checked, then do NOT send EVENT, as widget is already checked, no need to do it twice.

As far as the focus bugs, that has to deal with the platform and your version… ???
Are you using just linux or linux and windows… Apple is just a $20 version of linux that cannot seem to figure out what a jumper is lol…

… anyhow … until next time …