6
$\begingroup$

When I code in Mathematica, I often find myself having to repeat large chunks of code for a function to work. The latest example of this is a color changing button that prints when clicked, code shown below.

Mouseover[
 Style[
  Button[
   Pane["Print", FrameMargins -> {{4, 4}, {4, 4}}, 
    ImageSize -> {34, 24}],
   Print["Print"],
   Appearance -> None
   ], Background -> Red
  ],
 Style[
  Button[
   Pane["Print", FrameMargins -> {{4, 4}, {4, 4}}, 
    ImageSize -> {34, 24}],
   Print["Print"],
   Appearance -> None
   ], Background -> Green
  ]
 ]

The only thing that is changing on the mouse over is the button color, but for this to work I need to repeat a whole chunk of code.

A simpler way of doing this is to define a button color function, and then use that in the Mouseover function, code shown below.

ButtonColor[color_] :=
 Style[
  Button[
   Pane["Print", FrameMargins -> {{4, 4}, {4, 4}}, 
    ImageSize -> {34, 24}],
   Print["Print"],
   Appearance -> None
   ], Background -> color
  ]

Mouseover[
 ButtonColor[Red],
 ButtonColor[Green]
 ]

This is better, but what if i only have to refer to the button color changing function for one mouse over button? Should I really have to define a function to use it for one instance?

I think the ideal way to code this would be to use Table or something similar, code shown below.

Mouseover[
 Table[
  Style[
   Button[
    Pane["Print", FrameMargins -> {{4, 4}, {4, 4}}, 
     ImageSize -> {34, 24}],
    Print["Print"],
    Appearance -> None
    ], Background -> color
   ],
  {color, {Red, Green}}
  ]
 ]

The only problem, Table doesn't work because it creates EXTRA BRACES!

Is there a better way of coding this color changing button?

$\endgroup$

3 Answers 3

6
$\begingroup$

You don't have repeat yourself. You can map a pure function defining the button over a list of the background colors and then apply Mouseover Like so:

Mouseover @@ 
  (Button[Panel["Print", FrameMargins -> {{4, 4}, {4, 4}}, 
     Background -> #], Print["Print"], Appearance -> None] & /@ {Red, Green})

button

$\endgroup$
1
  • $\begingroup$ Oohh, this is exactly what I was after, I think. Thanks for the quick reply ^_^ $\endgroup$
    – user12572
    May 18, 2014 at 2:31
9
$\begingroup$

An alternative approach using CurrentValue["MouseOver"]:

Button[Panel["Print", FrameMargins -> {{4, 4}, {4, 4}}, 
             Background -> Dynamic@If[CurrentValue["MouseOver"], Green, Red]], 
       Print["Print"], Appearance -> None]

or, without the Panel,

Button["Print", Print["Print"], 
       Background -> Dynamic@If[CurrentValue["MouseOver"], Green, Red]]

enter image description here enter image description here

$\endgroup$
1
  • 2
    $\begingroup$ Best answer so far, IMO. +1 $\endgroup$
    – Mr.Wizard
    Aug 17, 2014 at 0:24
7
$\begingroup$

Another method which doesn't really use Mouseover but the EventHandler:

DynamicModule[{col = Red},
              EventHandler[
                           Button[
                                  Panel["Print", FrameMargins -> {{4, 4}, {4, 4}}, 
                                                 Background   -> Dynamic[col]], 
                                  Print["Print"],
                                  Appearance -> None],
                           "MouseEntered" :> (col = Green),
                           "MouseExited"  :> (col = Red  )
                          ]
             ]

The Button isn't repeated in the output too, so might make the result a little slimmer.

$\endgroup$

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.