8
$\begingroup$

There is probably either a Tutorial or a dupe I can read in order to figure this out, but I haven't been able to find one by searching on my own. So here is the problem:

I want to create a function checkboxToList[] that displays a grid of checkboxes like the following:

Column[Table[
  CheckboxBar[ConstantArray[0, alfa + 1], Range[-alfa, 3]]
  , {alfa, 5, 0, -1}
  ]
 , Alignment -> Right
 ]

enter image description here

Then I want the user to be able to make selections, like e.g.

enter image description here

Finally, by pressing a button or something similar, I want the function to return a list of pairs {{x1,y1},{x2,y2},...} where the x are the row numbers of the checked boxes counting from below, starting from 0, and the y are the checkbox labels. Thus, from the second image I would want to return {{0,0}, {0,1}, {2,-2}, {4,-4}, {4,-2}}. The order of the pairs in the returned list does not matter to me.

Any help much appreciated!

$\endgroup$
  • 1
    $\begingroup$ CheckboxBar[ConstantArray[0, alfa + 1], Range[-alfa, 3]] is effectively the same as CheckboxBar[{0}, Range[-alfa, 3]]. $\endgroup$ – Karsten 7. Sep 19 '16 at 17:10
5
$\begingroup$
checkboxToList[rows_] := DynamicModule[{cbb},
  cbb = ConstantArray[{0}, rows];
  Panel@Column[{
     Column[
      Table[
       With[{pos = alfa + 1}, 
        CheckboxBar[Dynamic[cbb[[pos]]], Range[-alfa, 3]]], {alfa, rows - 1, 
        0, -1}]
      , Alignment -> Right]
     ,
     Button["Checkboxes to List",
      CellPrint@ExpressionCell@Flatten[
         Transpose[{Range[0, Length@cbb - 1], 
            cbb}] /. {{a_, {b__}} :> ({a, #} & /@ {b}), {a_, {}} -> Nothing},
         1]]
     }]
  ]

checkboxToList[6]

OutGif


Edit 1:

SetAttributes[checkboxToList, HoldAll]

checkboxToList[rows_, out_] := 
 DynamicModule[{cbb}, cbb = ConstantArray[{0}, rows];
  Panel@Column[{Column[
      Table[With[{pos = alfa + 1}, 
        CheckboxBar[Dynamic[cbb[[pos]]], Range[-alfa, 3]]], {alfa, rows - 1, 
        0, -1}], Alignment -> Right], 
     Button["Checkboxes to List", 
      out = Flatten[
        Transpose[{Range[0, Length@cbb - 1], 
           cbb}] /. {{a_, {b__}} :> ({a, #} & /@ {b}), {a_, {}} -> Nothing}, 
        1]]}]]

checkboxToList[6, ans]

Edit 2:

checkboxToList[rows_] := DynamicModule[{cbb}, cbb = ConstantArray[{0}, rows];
  Panel@Column[{Column[
      Table[With[{pos = alfa + 1}, 
        CheckboxBar[Dynamic[cbb[[pos]]], Range[-alfa, 3]]], {alfa, rows - 1, 
        0, -1}], Alignment -> Right], Button["Checkboxes to List",
      MakeExpression[NotebookRead[PreviousCell[]], StandardForm] /. 
        HoldPattern[{__, out_ = checkboxToList[_]}] :> (out = 
           Flatten[Transpose[{Range[0, Length@cbb - 1], 
               cbb}] /. {{a_, {b__}} :> ({a, #} & /@ {b}), {a_, {}} -> 
               Nothing}, 1]) // ReleaseHold]}]]

ans = checkboxToList[6]
$\endgroup$
  • $\begingroup$ I interpreted "return a list of pairs" as printing it as an ExpressionCell, but one can change that to whatever is most appropriate in the context of that function. $\endgroup$ – Karsten 7. Sep 19 '16 at 17:28
  • $\begingroup$ How would you change the Button expression so that, if I input ans = checkboxToList[6] in the notebook, the variable ans would have the list of pairs stored after pressing the button? Is this possible to do? $\endgroup$ – Marius Ladegård Meyer Sep 19 '16 at 19:15
  • $\begingroup$ @MariusLadegårdMeyer Please see my edit. Does that work for you too? ans = checkboxToList[6] would be possible to, but not necessarily in a way as obvious. $\endgroup$ – Karsten 7. Sep 19 '16 at 19:32
  • $\begingroup$ @MariusLadegårdMeyer I addet a version that works with ans = checkboxToList[6], but it's kind of an odd way. I'd prefer the version used in Edit 1. $\endgroup$ – Karsten 7. Sep 19 '16 at 20:18
  • $\begingroup$ Karsten 7., @andre, thank you both for contributing. My final implementation uses a hybrid of both your answers, so it's hard to chooce what answer to accept. I will accept Karsten 7.'s answer because it also taught me how to use the button in different ways. $\endgroup$ – Marius Ladegård Meyer Sep 22 '16 at 11:33
6
$\begingroup$

Here is a solution that updates the list as soon as you check a box.

(* myCheckbox add or remove "elt" to/from the list "choice" *)
SetAttributes[myCheckbox, HoldFirst];
myCheckbox[choice_, elt_] := 
 Checkbox[Dynamic[MemberQ[choice, elt], 
   If[#, AppendTo[choice, elt], choice = DeleteCases[choice, elt]] &]]

choice = {};
Dynamic[choice]

Column[Table[
  Row[Row [{myCheckbox[choice, {alfa, #}], #}, " ", 
      Alignment -> Left] & /@ Range[-alfa, 3], "    "], {alfa, 5, 
   0, -1}], Alignment -> Right]

enter image description here

choice  

{{4, -4}, {4, -2}, {2, -2}, {0, 0}, {0, 1}}

Your approach with Column[Table[CheckboxBar ...]] has the drawback that if your checkbox labels have not the same size (vertically), your columns will be missaligned. This problem is solved if you use instead a Grid[] of the myCheckbox[] above. Example :

choice2 = {};
Dynamic[choice2]
Grid[{{Row[{myCheckbox[choice2, "A"], "A"}], 
   Row[{myCheckbox[choice2, "B"], "B"}]}, {, 
   Row[{myCheckbox[choice2, "C"], "CCCCC"}]}}, Alignment -> Left]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.