A "Segmented Button" Control?

Does anyone know if a control exists or can be adapted that would make
a type of "segmented button"? That is a button or tool that could be a
standalone button or tool placed into a toolbar where the user could
press different parts of the control and it act as a separate button?
For instance, a 32x32 button could be divided into two, three, four,
or even five segments (one in the center) where each acts as a
separate button yet in one control.

wx.SpinCtrl has a type of this with two buttons in one control.

This would be very handy, especially where space is limited in a
Toolbar, for opening certain windows, pages or similar.

···

I’m not familiar with anything that does this - I’ve had the same idea after seeing the controls available in Apple’s Interface Builder. It would not be terribly difficult (for someone experienced with wxPython) to create something similar with a custom-drawn control and/or combination of controls and panels. It’s also a non-trivial amount of coding, however.

-Nat

···

On Thu, Apr 8, 2010 at 10:43 AM, tsmorton tim@preservedwords.com wrote:

Does anyone know if a control exists or can be adapted that would make

a type of “segmented button”? That is a button or tool that could be a

standalone button or tool placed into a toolbar where the user could

press different parts of the control and it act as a separate button?

For instance, a 32x32 button could be divided into two, three, four,

or even five segments (one in the center) where each acts as a

separate button yet in one control.

Hello,

···

On Thu, Apr 8, 2010 at 12:43 PM, tsmorton <tim@preservedwords.com> wrote:

Does anyone know if a control exists or can be adapted that would make
a type of "segmented button"? That is a button or tool that could be a
standalone button or tool placed into a toolbar where the user could
press different parts of the control and it act as a separate button?
For instance, a 32x32 button could be divided into two, three, four,
or even five segments (one in the center) where each acts as a
separate button yet in one control.

wx.SpinCtrl has a type of this with two buttons in one control.

This would be very handy, especially where space is limited in a
Toolbar, for opening certain windows, pages or similar.

I have something that I made that sort of behaves this way in Editra,
its in the eclib folder and called SegmentBar. Its kind like a custom
drawn toolbar where only one button on it can be toggled down at a
time. screenshot near bottom of (editra.org).

Cody

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

I have something that I made that sort of behaves this way in Editra,
its in the eclib folder and called SegmentBar. Its kind like a custom
drawn toolbar where only one button on it can be toggled down at a
time. screenshot near bottom of (editra.org).

Thanks Cody,

This looks good and useful, but not really what I had in mind. If all
the page tools could be reduced to one tool/image that is a single
control, that would be much closer. Ideally, the segemented control
would be able to be used in a toolbar such as FlatMenu which will
allow the insertion of controls. Then one could access several related
items in a single, compact control.

The concept is fairly straightforward, I think (basically combine
custom buttons into one unit but with separate events and button
action), but I'm not sure how to implement it. It there a WxPython
version of wx.SpinCtrl or similiar available one could study how they
combined the buttons?

Tim

···

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

I have something that I made that sort of behaves this way in Editra,
its in the eclib folder and called SegmentBar. Its kind like a custom
drawn toolbar where only one button on it can be toggled down at a
time. screenshot near bottom of (editra.org).

Thanks Cody,

This looks good and useful, but not really what I had in mind. If all
the page tools could be reduced to one tool/image that is a single
control, that would be much closer. Ideally, the segemented control
would be able to be used in a toolbar such as FlatMenu which will
allow the insertion of controls. Then one could access several related
items in a single, compact control.

So, in other words, something like the back button in firefox that behaves differently if you click on the right side or the left side.

The concept is fairly straightforward, I think (basically combine
custom buttons into one unit but with separate events and button
action), but I'm not sure how to implement it. It there a WxPython
version of wx.SpinCtrl or similiar available one could study how they
combined the buttons?

You can look at wx.lib.buttons for an example of a generic custom button widget. To take it to the next step you would just need to behave differently if the mouse clicks happen in the different target zones that have been defined for the button. Perhaps it could just be some extra info added to the event object that specifies the target zone, and the event handler catching that event can deal with it appropriately.

···

On 4/8/10 4:26 PM, tsmorton wrote:

--
Robin Dunn
Software Craftsman

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

Thanks Robin,

So, in other words, something like the back button in firefox that
behaves differently if you click on the right side or the left side.

Yes, similar to Firefox's Back/Forw button.

You can look at wx.lib.buttons for an example of a generic custom button
widget. To take it to the next step you would just need to behave
differently if the mouse clicks happen in the different target zones
that have been defined for the button.

I thought also of some type of "image map" on the button defining
regions, and that would be ok (even though the whole button would
"depress" when any part was clicked, unlike the Firefox button), but a
single control with several independent regions would be ideal.

I'll look into it some more, but if some of the more experienced
controls makers in this group would like to tackle it, I'm sure it
would be used.

Tim

You can get this effect entirely by custom drawing in Python in response to every mouse event. Just check where the mouse was clicked and see if it corresponds to one of the segments, and if so take that into account in the next redraw. It gets a little complicated once you deal with tracking mouse focus and multiple positions, and you’d need to define a custom event with the segment ID embedded, but it’s still very doable, especially if you work off existing code like PlateButton (part of the standard distribution now). Drawing controls manually seems a little gross at first but you can make some very sophisticated widgets with this. (Andrea Gavana’s RibbonBar is probably the most extreme example that I’m aware of.)

If no one else gets around to this, I might make an attempt myself, if I can find the time. These controls are really what I miss the most in wxPython versus Cocoa.

···

On Thu, Apr 8, 2010 at 5:21 PM, tsmorton tim@preservedwords.com wrote:

I thought also of some type of “image map” on the button defining

regions, and that would be ok (even though the whole button would

“depress” when any part was clicked, unlike the Firefox button), but a

single control with several independent regions would be ideal.

So, was something like this what you wanted, or am I mixed up?

http://cci.lbl.gov/~nat/img/segment_ctrl.png

(It should work equally well with bitmaps - or bitmaps and labels - in theory.)

-Nat

···

On Thu, Apr 8, 2010 at 5:21 PM, tsmorton tim@preservedwords.com wrote:

Yes, similar to Firefox’s Back/Forw button.
. . .

I thought also of some type of “image map” on the button defining

regions, and that would be ok (even though the whole button would

“depress” when any part was clicked, unlike the Firefox button), but a

single control with several independent regions would be ideal.

Thanks Nat,

So, was something like this what you wanted, or am I mixed up?

Actually something like this quick and dirty image is what I had in
mind,

This is a 48x48 pixel button with a segment in each corner and an
optional segment in the center (black area). The button could have 2,
3, 4, or 5 segments. Probably more than 5 is not practical. 32 pixel
also, but segments would be smaller. Even 16 pixel could have 2
segments (like the two buttons on a SpinCtrl). The essential issue is
the group of buttons be considered one control so it could be placed
in toolbars and other places where controls must be inserted
individually and multiple controls cannot be placed above each other
or tight against each other.

Tim

Ah, I see. This probably isn’t very difficult, once you get familiar with the low-level drawing API. What I thought would be the hard part - getting different segments in a wx.PyControl to appear to be separate buttons - was actually much easier than I expected. The only catch is that you still only bind to a single button event, but wx.CommandEvent.SetClientData() is sufficient to distinguish between the segments in the control. If and when I finish what I wanted for my interfaces, it would not be difficult to adapt to the kind of layout you need. It is potentially much more work to actually make something “clean” and flexible enough for general use, however.

···

On Fri, Apr 9, 2010 at 7:32 PM, tsmorton tim@preservedwords.com wrote:

Actually something like this quick and dirty image is what I had in

mind,

http://www.bibleanalyzer.com/files/seg-button.png

This is a 48x48 pixel button with a segment in each corner and an

optional segment in the center (black area). The button could have 2,

3, 4, or 5 segments. Probably more than 5 is not practical. 32 pixel

also, but segments would be smaller. Even 16 pixel could have 2

segments (like the two buttons on a SpinCtrl). The essential issue is

the group of buttons be considered one control so it could be placed

in toolbars and other places where controls must be inserted

individually and multiple controls cannot be placed above each other

or tight against each other.

Hi All,

Actually something like this quick and dirty image is what I had in
mind,
Bible Analyzer Bible Software - Free Premium Bible Software For Windows, Macintosh, and Linux

This is a 48x48 pixel button with a segment in each corner and an
optional segment in the center (black area). The button could have 2,
3, 4, or 5 segments. Probably more than 5 is not practical. 32 pixel
also, but segments would be smaller. Even 16 pixel could have 2
segments (like the two buttons on a SpinCtrl). The essential issue is
the group of buttons be considered one control so it could be placed
in toolbars and other places where controls must be inserted
individually and multiple controls cannot be placed above each other
or tight against each other.

Ah, I see. This probably isn't very difficult, once you get familiar with
the low-level drawing API. What I thought would be the hard part - getting
different segments in a wx.PyControl to appear to be separate buttons - was
actually much easier than I expected. The only catch is that you still only
bind to a single button event, but wx.CommandEvent.SetClientData() is
sufficient to distinguish between the segments in the control. If and when
I finish what I wanted for my interfaces, it would not be difficult to adapt
to the kind of layout you need. It is potentially much more work to
actually make something "clean" and flexible enough for general use,
however.

I am probably being naive here, but looking at the picture Tim posted
and noting that "The essential issue is the group of buttons be
considered one control so it could be placed in toolbars", why don't
you use a wx.PyPanel and wx.BoxSizer/wx.GridSizer and place your small
buttons in the sizer as children of the wx.PyPanel? You will still
have to handle the fact that when you click on one button the whole
panel should look "pressed" or when you hover on it the whole panel
should look hovered, but that's not that hard considering that you're
using generic controls (wx.PyPanel and hand-drawn buttons) and you're
going to draw things yourself. Just an idea.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

==> Never *EVER* use RemovalGroup for your house removal. You'll
regret it forever.
The Doomed City: Removal Group: the nightmare <==

···

On 10 April 2010 04:16, Nathaniel Echols wrote:

On Fri, Apr 9, 2010 at 7:32 PM, tsmorton <tim@preservedwords.com> wrote:

Thanks Nat and Andrea,

Andrea, if a PyPanel with buttons is used as you suggested, could it
be inserted in FlatMenu as a control and that would allow each button
to have its own normal button action look when pressed? I realize if
the PyPanel is inserted as a Tool the whole tool will look "pressed"
and "hovered" when any part is acted upon.

Tim

···

On Apr 10, 6:23 am, Andrea Gavana <andrea.gav...@gmail.com> wrote:

Hi All,

On 10 April 2010 04:16, Nathaniel Echols wrote:

> On Fri, Apr 9, 2010 at 7:32 PM, tsmorton <t...@preservedwords.com> wrote:

>> Actually something like this quick and dirty image is what I had in
>> mind,
>>Bible Analyzer Bible Software - Free Premium Bible Software For Windows, Macintosh, and Linux

>> This is a 48x48 pixel button with a segment in each corner and an
>> optional segment in the center (black area). The button could have 2,
>> 3, 4, or 5 segments. Probably more than 5 is not practical. 32 pixel
>> also, but segments would be smaller. Even 16 pixel could have 2
>> segments (like the two buttons on a SpinCtrl). The essential issue is
>> the group of buttons be considered one control so it could be placed
>> in toolbars and other places where controls must be inserted
>> individually and multiple controls cannot be placed above each other
>> or tight against each other.

> Ah, I see. This probably isn't very difficult, once you get familiar with
> the low-level drawing API. What I thought would be the hard part - getting
> different segments in a wx.PyControl to appear to be separate buttons - was
> actually much easier than I expected. The only catch is that you still only
> bind to a single button event, but wx.CommandEvent.SetClientData() is
> sufficient to distinguish between the segments in the control. If and when
> I finish what I wanted for my interfaces, it would not be difficult to adapt
> to the kind of layout you need. It is potentially much more work to
> actually make something "clean" and flexible enough for general use,
> however.

I am probably being naive here, but looking at the picture Tim posted
and noting that "The essential issue is the group of buttons be
considered one control so it could be placed in toolbars", why don't
you use a wx.PyPanel and wx.BoxSizer/wx.GridSizer and place your small
buttons in the sizer as children of the wx.PyPanel? You will still
have to handle the fact that when you click on one button the whole
panel should look "pressed" or when you hover on it the whole panel
should look hovered, but that's not that hard considering that you're
using generic controls (wx.PyPanel and hand-drawn buttons) and you're
going to draw things yourself. Just an idea.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."http://xoomer.alice.it/infinity77/

==> Never *EVER* use RemovalGroup for your house removal. You'll
regret it forever.http://thedoomedcity.blogspot.com/2010/03/removal-group-nightmare.html&lt;==

I like the look of that a lot, and am looking forward to seeing the code.

···

On 4/9/10 4:54 PM, Nathaniel Echols wrote:

On Thu, Apr 8, 2010 at 5:21 PM, tsmorton <tim@preservedwords.com > <mailto:tim@preservedwords.com>> wrote:

    Yes, similar to Firefox's Back/Forw button.
    . . .
    I thought also of some type of "image map" on the button defining
    regions, and that would be ok (even though the whole button would
    "depress" when any part was clicked, unlike the Firefox button), but a
    single control with several independent regions would be ideal.

So, was something like this what you wanted, or am I mixed up?

http://cci.lbl.gov/~nat/img/segment_ctrl.png

(It should work equally well with bitmaps - or bitmaps and labels - in
theory.)

--
Robin Dunn
Software Craftsman

Here is a very basic SegmentedButton Class that one can pass size and
segment arguments. It will return the buttons (2, 3, or 4) on a
PyPanel that can be inserted into an AUI Toolbar as a control. It uses
the Generic Buttons. It does not yet deal with events or labels. This
is just a "proof of concept" thing.

I am not very swift on making hand drawn buttons that could appear to
overlap (the 5th button in the center). That would be very nice and
somewhat unique. There are many possibilities with button arrangements
such as this. I know some of you guys (and gals) could make some very
compact, functional, and attractive controls (hint, hint).

Tim

ps. If the code below is wrapped, here it is as well,
http://www.BibleAnalyzer.com/files/segTest.py

···

-------------------------------

import wx
import wx.lib.buttons as buttons

class SegmentButton(wx.PyPanel):
    def __init__(self, parent, id=wx.ID_ANY, size = (32, 32), segments
= 4):
        wx.PyPanel.__init__(self, parent, id)

        segSize = (size[0] /2, size[0] /2) # 4 segments
        if segments == 3:
            segSize = (size[0], size[0] /3.33)
        if segments == 2:
            segSize = (size[0], size[0] /2)

        segList = []

        for seg, num in enumerate(range(segments)):
            b = buttons.GenButton(self, -1, str(num), size =
(segSize[0], segSize[1]))
            segList.append(b)

        gsRows = (2, 2) # 4 segments
        if segments == 3:
            gsRows = (3, 1)
        elif segments == 2:
            gsRows = (2, 1)

        gs = wx.GridSizer(gsRows[0], gsRows[1])
        for b in segList:
            gs.Add(b, 0, wx.EXPAND)

        self.SetSizer(gs)

class TestFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, style =
wx.DEFAULT_FRAME_STYLE)
        panel = wx.Panel(self, -1)

        segButton = SegmentButton(panel, size = (48, 48), segments =
4)

        self.SetTitle('Segment Button Demo')

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(segButton, 0, wx.ALL, 30)
        panel.SetSizer(sizer)
        self.Layout()

class MyApp(wx.App):
    def OnInit(self):
        Demo = TestFrame(None)
        Demo.Show()
        return 1

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

I’ve attached what I have so far, minus the icons needed to see the bitmap versions. There are still a few clumsy things (why does it end up with size (0,0) when I place it in the toolbar?), but this does what I wanted it for. I haven’t tried it on Linux yet, however.

-Nat

segmentedctrl.py (14 KB)

···

On Sat, Apr 10, 2010 at 12:51 PM, Robin Dunn robin@alldunn.com wrote:

On 4/9/10 4:54 PM, Nathaniel Echols wrote:

So, was something like this what you wanted, or am I mixed up?

http://cci.lbl.gov/~nat/img/segment_ctrl.png

(It should work equally well with bitmaps - or bitmaps and labels - in

theory.)

I like the look of that a lot, and am looking forward to seeing the code.

        So, was something like this what you wanted, or am I mixed up?

        http://cci.lbl.gov/~nat/img/segment_ctrl.png

        (It should work equally well with bitmaps - or bitmaps and
        labels - in
        theory.)

    I like the look of that a lot, and am looking forward to seeing the
    code.

I've attached what I have so far, minus the icons needed to see the
bitmap versions. There are still a few clumsy things (why does it end
up with size (0,0) when I place it in the toolbar?),

Toolbars don't check best size. If you call self.SetInitialSize(size) in the __init__ then it will merge the best size with the size passed to the __init__ (if any) and will then set the widget to that size. Then it will be the proper size after creation and will look correct in situations where there is no sizer.

but this does what
I wanted it for. I haven't tried it on Linux yet, however.

It has some problems on Windows. Since you are using a buffered DC on windows you should clear it to the background colour first, which will help take care of the rounded corners. Also it looks like some measurments are off, not only the buttons that are too large, but the hit testing can sometimes activate the wrong segment. (I clicked on "Selection" in the screenshot.) The toolbar issue in the screenshot is probably just due to not calling SetToolBitmapSize.

···

On 4/10/10 7:35 PM, Nathaniel Echols wrote:

On Sat, Apr 10, 2010 at 12:51 PM, Robin Dunn <robin@alldunn.com > <mailto:robin@alldunn.com>> wrote:
    On 4/9/10 4:54 PM, Nathaniel Echols wrote:

--
Robin Dunn
Software Craftsman