2
$\begingroup$

I am trying to make a simple hundred chart with squares that will toggle on and off when clicked. I have a start, I can click to fill a square, but have no idea how to click on a filled square and "un-fill" it. I would appreciate any help or advice on how to proceed.

list = {};

ClickPane[
 Dynamic[
  Graphics[{
    GrayLevel[0.8], Line /@ Table[{{i, 0}, {i, 10}}, {i, 0, 10}],
    Line /@ Table[{{0, i}, {10, i}}, {i, 0, 10}],
    Rectangle[#, # + {1, 1}] & /@ list}]], AppendTo[list, Floor[#]] &]

Comment...

I just saw FlipView and here is a very crude way to answer my question, not elegant, but it works. Would still value input...

lines = { GrayLevel[0.8], Line /@ Table[{{i, 0}, {i, 10}}, {i, 0, 10}],
  Line /@ Table[{{0, i}, {10, i}}, {i, 0, 10}]}

rectangles = Flatten[Table[
    FlipView[{{White, Rectangle[{i, j}, {i, j} + {1, 1}]},
      {GrayLevel[0.9], Rectangle[{i, j}, {i, j} + {1, 1}]}}], {i, 0, 
     9, 1}, {j, 0, 9, 1}]];

Graphics[{
  rectangles,
  lines}]
$\endgroup$
1
  • 1
    $\begingroup$ The lines are not necessary if you include EdgeForm, i.e., Graphics[{EdgeForm[GrayLevel[0.8]], rectangles}] $\endgroup$
    – Bob Hanlon
    Feb 8, 2022 at 4:13

5 Answers 5

5
$\begingroup$

Is the ClickPane an inescapable requirement? Would something like the following help at all?

rec = 
  FlipView[{
    Graphics@ {FaceForm[LightGray],   Rectangle[]},
    Graphics@ {FaceForm[Darker@Gray], Rectangle[]}
  }];

Grid[
  ConstantArray[rec, {3, 3}],
  Frame -> All, Spacings -> {0, 0}
]

a grid with some clicked rectangles

$\endgroup$
3
$\begingroup$

Create a single Rectangle and Translate it:

rectangle = FlipView @ 
    Thread[{EdgeForm[Black], FaceForm /@ {LightGray, Darker @ Gray}, Rectangle[]}];

n = 4;

coords = Tuples[Range @ n, 2];

Graphics[Translate[rectangle, #] & /@ coords]

enter image description here

$\endgroup$
2
$\begingroup$

There is no out of the box function. However, you can achieve this with a dynamic button:

n = 5;
Grid[Table[
  DynamicModule[{x = White}, 
   Button[StringForm["``,``", i, j], x = If[x === White, Red, White], 
    Background -> Dynamic[x]]], {i, n}, {j, n}]]

enter image description here

$\endgroup$
2
$\begingroup$
ClearAll[labeledRectangles]
labeledRectangles[o : OptionsPattern[]][n_, faceStyles_: {LightGray, Darker @ Gray}, 
    edgeStyle_: Black] := Module[{range = Range @ n}, 
  Graphics[Translate[FlipView @ Thread[
   {EdgeForm[edgeStyle], FaceForm /@ faceStyles,  Rectangle[], 
   {Text[Style[Row[{n + 1 - Last@#, First@#}, "×"], 
      Last@faceStyles, FontSize -> Scaled[.02], Opacity[1]], {.5, .5}, Center], 
    Text[Style[Times[First@#, n + 1 - Last@#], 
      First@faceStyles, FontSize -> Scaled[.04], Opacity[1]], {.5, .5}, Center]}}],
    #] & /@ Tuples[range, 2], 
   o, Frame -> True, 
   FrameTicks -> {{#, #} &[{# + .5, n + 1 - #} & /@ range], 
      {#, #} &[{# + .5, #} & /@ range]}]]

Examples:

labeledRectangles[ImageSize -> Large][10]

enter image description here

labeledRectangles[ImageSize -> Large][10, {Black, White}, Directive[Gray, Thick]]

enter image description here

$\endgroup$
3
  • $\begingroup$ Thanks for this, looks amazing. When I copy and paste and evaluate I am getting an error... Range::range: Range specification in Range[n] does not have appropriate bounds. Not sure what I might be doing wrong there...? $\endgroup$ Feb 11, 2022 at 15:31
  • $\begingroup$ @TomDeVries, I copy/pasted the wrong code block. Fixed now. $\endgroup$
    – kglr
    Feb 11, 2022 at 15:41
  • $\begingroup$ Fantastic, definitely a great application of a hundred chart, lots for me to learn here! $\endgroup$ Feb 11, 2022 at 16:31
2
$\begingroup$

Using a labeled MatrixPlot with EventHandler to modify labels on left-mouse click and to Speak the cell contents on right-mouse click:

ClearAll[labeledMat, multiplicationTable]

infoButton = Inset[Tooltip[Graphics[{Blue, Disk[], 
    Text[Style["i", 14, Italic, Bold, White, FontFamily -> "Times"], {0, 0}]}, 
   PlotRange -> 1.2, ImageSize -> 24],
 "left click to" <> ToString[Style[" see ", Italic], StandardForm] <> 
 "the result\nright click to" <> ToString[Style[" hear ", Italic], StandardForm]], 
   Scaled@{0, 1}, {-1., -2}];

labeledMat[mat_] := MapIndexed[
  Text[Style[# /. {1 -> ((Length @ mat + 1 - #2[[2]]) #2[[1]]), 
       0 -> Row[{Length @ mat + 1 - #2[[2]], #2[[1]]}, "×"]}, # /.
    {0 -> FontSize -> Scaled[.025], 1 -> FontSize -> Scaled[.05]}], #2 - .5] &, mat, {2}]

multiplicationTable[n_: 10, o : OptionsPattern[]] := 
 DynamicModule[{m = ConstantArray[0, {n, n}]}, Dynamic @ Panel @
  EventHandler[
     MatrixPlot[Reverse @ Transpose @ m, o, 
      ColorRules -> {0 -> LightGray, 1 -> Gray}, 
      Mesh -> All, 
      ImageSize -> 1 -> 50,
      ImagePadding -> {{Automatic, Automatic}, {Automatic, 36}}, 
      Epilog -> {infoButton, labeledMat[m]}], 
   {{"MouseClicked", 1} :>
     With[{p = Clip[Ceiling @ MousePosition["Graphics"], {1, n}, {None, None}]},
        If[FreeQ[None]@p, m[[## & @@ p]] = 1 - m[[## & @@ p]]]], 
    {"MouseClicked", 2} :>
     With[{p = Clip[Ceiling @ MousePosition["Graphics"], {1, n}, {None, None}]},
        If[FreeQ[None]@p, 
          With[{a = p[[1]], b = n + 1 - p[[2]]},             
           If[m[[## & @@ p]] > 0, Speak[StringJoin[ToString[b] <> " times ", 
             ToString @ a, " equals ", ToString[a b]]]
           Speak[HoldForm[b a]]]]]]}]]

Examples:

multiplicationTable[10, ColorRules -> {0 -> Yellow, 1 -> Red}]

enter image description here

$\endgroup$
1
  • $\begingroup$ Another great example with lots of good examples of programming methods and applications! $\endgroup$ Feb 13, 2022 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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