Checkbox events

Hello!

I want to create some checkboxes and if the user check one of them,
all the others should get disabled. This works for the first checkbox
but, somehow not for the others.

Here's a small example:
http://pastebin.com/NXybeFhi

Does someone knows what I'm doing wrong?

Kind regards
Stefanie

Hi,

Basically only the first two parts of your IF statement will run, whereas the other two parts never will. You have it set up to check if the first checkbox is checked in the first part and then you check if it’s not checked in the second part. Since those are the only two valid conditions for a checkbox, the other parts of your conditional will never be executed.

  • Mike

** GUI Police Note **: Are you sure you want to do that? The very
much standard GUI convention (across thousands of desktop apps and web
apps) is that multiple checkboxes allow as many to be checked as users
wishes to. Mutually exclusive selections are never represented with
checkboxes, but with *radio buttons*.

(Worse, if you really disable the other checkboxes, you would not
allow users to change their selection before committing)

···

On Mon, Aug 29, 2011 at 10:06 AM, Stefanie Lück <lueck@ipk-gatersleben.de> wrote:

Hello!

I want to create some checkboxes and if the user check one of them,
all the others should get disabled. This works for the first checkbox
but, somehow not for the others.

You're right, but I gave only a simple example. I have many choices in
3 groups. For some groups multiple choices are allowed, for others not
(inside and outside the group). Some choices depend on the choice of
the other groups, but I have to show that some combinations don't work
together. How to do this? To use Radiobutton and if the User chooses
a "not working" combination to give a message? Something like that? Or
I make even more groups and use a mixture of radio and checkboxes...

Another question, how I can check all the events without repeating
always one and the same conditional? Is there any "clever" way?

Thanks!
Stefanie

···

On Aug 29, 7:35 pm, C M <cmpyt...@gmail.com> wrote:

On Mon, Aug 29, 2011 at 10:06 AM, Stefanie Lück > > <lu...@ipk-gatersleben.de> wrote:
> Hello!

> I want to create some checkboxes and if the user check one of them,
> all the others should get disabled. This works for the first checkbox
> but, somehow not for the others.

** GUI Police Note **: Are you sure you want to do that? The very
much standard GUI convention (across thousands of desktop apps and web
apps) is that multiple checkboxes allow as many to be checked as users
wishes to. Mutually exclusive selections are never represented with
checkboxes, but with *radio buttons*.

(Worse, if you really disable the other checkboxes, you would not
allow users to change their selection before committing)

I came up with a rather hacky way to disable them (see attached), although as Che mentioned, radio buttons would be better here. I have seen some web forms that allow up 3-5 checkbox choices and then disables the rest. You could use my solution wrapped with some kind of counter to emulate that.

stef.py (1.85 KB)

···

Mike Driscoll

Blog: http://blog.pythonlibrary.org

You may also want to look at wx.EVT_UPDATE_UI events. They make it very easy to implement cases like this where the state of a widget depends on some other state in the application, like the checked/unchecked state of some other checkbox. And it helps you to break it down into easily digestible chunks. For example, if checkbox2 should be disabled when checkbox1 is checked, then you can just bind the following as checkbox2's wx.EVT_UPDATE_UI handler:

     def OnDependentCheckboxUpdateUI(self, evt):
         evt.Enable(not self.checkbox1.GetValue())

When the handler returns wx takes the value passed to evt.Enable and applies it to the widget that the event was for, checkbox2 in this example.

···

On 8/29/11 7:29 AM, Mike Driscoll wrote:

Hi,

Basically only the first two parts of your IF statement will run,
whereas the other two parts never will. You have it set up to check if
the first checkbox is checked in the first part and then you check if
it's not checked in the second part. Since those are the only two valid
conditions for a checkbox, the other parts of your conditional will
never be executed.

--
Robin Dunn
Software Craftsman

You're right, but I gave only a simple example. I have many choices in
3 groups. For some groups multiple choices are allowed, for others not
(inside and outside the group). Some choices depend on the choice of
the other groups, but I have to show that some combinations don't work
together. How to do this? To use Radiobutton and if the User chooses
a "not working" combination to give a message? Something like that? Or
I make even more groups and use a mixture of radio and checkboxes...

The first step is to do all you can to simplify things in terms of the
choices. If you can possibly consolidate choices or eliminate
choices, do so. If the choice rules are too complex, maybe you can
rethink your model to simplify them.

Then, see if there is any natural ordering that will simplify the GUI.
E.g., is there a natural hierarchy to the choices, in that some
choices are "foundational" to others? If so, you would want to put
those choices in the first position (left, up) in the array of choices
areas, or, better, force the user to interact with them first by using
a wxWizard or wxComboPopup or something like that. The answers they
choose can cause you to repopulate the next set of choices with only
compatible options.

I would say that in any case in which you have a box of
mutually-exclusive options, you should use either radio buttons or
maybe wxChoices.

Another question, how I can check all the events without repeating
always one and the same conditional? Is there any "clever" way?

Beyond what Mike and Robin wrote, If you use radio buttons, this is
automatic--within the group--and you don't have to do anything.

Che

···

On Mon, Aug 29, 2011 at 2:01 PM, Stefanie Lück <lueck@ipk-gatersleben.de> wrote:

Thanks for your great suggestions! I was thinking about a wizard but
it's becomes to confusing. I think it's better to have an overview
about what the user have chosen. As you all said, I'll try to keep it
as simple as possible and to reduce some choices.

···

On Aug 29, 8:50 pm, C M <cmpyt...@gmail.com> wrote:

On Mon, Aug 29, 2011 at 2:01 PM, Stefanie Lück <lu...@ipk-gatersleben.de> wrote:
> You're right, but I gave only a simple example. I have many choices in
> 3 groups. For some groups multiple choices are allowed, for others not
> (inside and outside the group). Some choices depend on the choice of
> the other groups, but I have to show that some combinations don't work
> together. How to do this? To use Radiobutton and if the User chooses
> a "not working" combination to give a message? Something like that? Or
> I make even more groups and use a mixture of radio and checkboxes...

The first step is to do all you can to simplify things in terms of the
choices. If you can possibly consolidate choices or eliminate
choices, do so. If the choice rules are too complex, maybe you can
rethink your model to simplify them.

Then, see if there is any natural ordering that will simplify the GUI.
E.g., is there a natural hierarchy to the choices, in that some
choices are "foundational" to others? If so, you would want to put
those choices in the first position (left, up) in the array of choices
areas, or, better, force the user to interact with them first by using
a wxWizard or wxComboPopup or something like that. The answers they
choose can cause you to repopulate the next set of choices with only
compatible options.

I would say that in any case in which you have a box of
mutually-exclusive options, you should use either radio buttons or
maybe wxChoices.

> Another question, how I can check all the events without repeating
> always one and the same conditional? Is there any "clever" way?

Beyond what Mike and Robin wrote, If you use radio buttons, this is
automatic--within the group--and you don't have to do anything.

Che

Try to draw out your options as one or more tables of choices and valid
other controls, this helps a lot in discussions with other people of
which controls should enable/disable each other, I usually find that it
also tends to naturally give me the grouping and ordering of the
controls, (if you can simplify your table by splitting out a given set
of options into a separate table then those options probably make a
separate group). Also it makes it easy to see exclusive choices, (radio
buttons/choices), and multiple options, (check box/multi-choice), to
pick the type of control.

Next I usually would have separate create and event handlers for each of
the groups identified. In the create functions I would build a table(s)
of the controls as I created them - this allows me to get all the
selected values/options without searching for the windows - I can then
create a tupple of the selected values that lets me look up which other
controls should be enables/disabled in a dictionary, (with a suitable
default set), and then run through the table(s) setting the
enable/disable values. This data driven way of working is more complex
than needed for simple items but for anything that is likely to grow or
is already complex it has the advantages of much lower complexity
increases each time a control is added, clearer code, etc., and fewer
lines of code. It also tends to allow better self documentation and
less maintenance problems.

Pseudo code:
Code driven (2 controls):
if control1 == valid:
   (dis)enable.control2
elif control2 == valid:
   (dis)enable.control1
else:
   (dis)enable.control1
   (dis)enable.control2

Code driven (3 controls):
if control1 == valid:
   (dis)enable.control2
    if control2 == valid:
       (dis)enable.control3
elif control2 == valid and control3 == valid:
   (dis)enable.control1
else:
   (dis)enable.control1
   (dis)enable.control2

As you can see this rapidly gets huge and messy.

Data Driven :
SelectionDict = { # for two controls
   # Values : Enables
   # (Ctrl1, Ctrl2):(Ctrl1, Ctrl2)
   (False,False):(True, True),
   (True, False): (True,False)
   (False, True): ( etc

OnSelect(self, evt):
  key = ()
  enableall = ()
  for Ctrl in ControlList:
    key += (Ctrl.GetValue(), )
    enableall += (True,)
  enables = SelectionDict.get(key, enableall)
  for n in range(0, len(enables)):
    ControlList[n].Enable(enables[n])

In the code driven method when you add a control you need to add a new
action in every branch of your if statements and add new if statements,
it is easy to miss one or more. In the data driven method adding a
control increases the size of the table, (all your changes are in one
place), and no new code it is easy to see which options you are adding.

You can use various methods for generating the key into your dictionary
and you can use dictionaries of dictionaries, etc.

Hope this gives you some ideas.

Gadget/Steve

···

On 29/08/2011 7:01 PM, Stefanie L�ck wrote:

You're right, but I gave only a simple example. I have many choices in
3 groups. For some groups multiple choices are allowed, for others not
(inside and outside the group). Some choices depend on the choice of
the other groups, but I have to show that some combinations don't work
together. How to do this? To use Radiobutton and if the User chooses
a "not working" combination to give a message? Something like that? Or
I make even more groups and use a mixture of radio and checkboxes...

Another question, how I can check all the events without repeating
always one and the same conditional? Is there any "clever" way?

Thanks!
Stefanie