Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Button[] beguiles me. A simple example follows:

b1 = Button["Evaluate", Cos[Pi/6], Method -> "Queued"]
b2 = Button["Evaluate", Print[Cos[Pi/6]], Method -> "Queued"]

Both of the above statements produce buttons. When one clicks on b1, it appears to evaluate something, but does not output or display anything. Clicking on b2 displays the expected output.

But clicking a second time on b2 prints the expected result a second time. Continuing to click on b2 just increases the list of printed results. This uselessly clutters the notebook I want to distribute.

I want a Button[] to execute a function and simply display its results as near as possible to what pressing Shift + Return in an input cell would do.

I further want it to overwrite previous output.

Ideally I would place the Button[] expression in a hidden initialization cell so only the actual button appears in the deployed notebook.

Does anyway exist to get a Button to do what I've described? How?

share|improve this question
    
Good question. In normal evaluation CellPrint overwrites the previous output but it does not work from within Button, at least as I tried it. – Mr.Wizard Jan 25 '13 at 23:37
    
@Mr.Wizard -- Any thoughts on why the difference? – Jagra Jan 26 '13 at 2:49
up vote 7 down vote accepted

You could try something like:

y = 0; 
b1 = Button["Evaluate", y = Cos[Pi/6] (++y), Method -> "Queued"]
Dynamic@y

Mathematica graphics

share|improve this answer
    
I must not have made described what I need to do clearly. When I click the Button a 2nd or 3rd time I need it to completely overwrite the output, neither adding to a list of printed results nor nesting the evaluation as you show above. In use I'll have some input variables that may get changed between the times someone clicks the button. I want a Button that will simply evaluate an expression and give me the same output I'd get from evaluating an input cell. Still, I wonder if you've pointed me in a productive direction. I'll try some things. Thx. – Jagra Jan 25 '13 at 19:01
1  
@Jagra My evaluation is recursive just because I wanted it.You may evaluate whatever you want – Dr. belisarius Jan 25 '13 at 19:04
    
Got it working. Many thanks. – Jagra Jan 25 '13 at 19:32

Sometimes Dynamic is not really needed. In Version 9 you can use the nice new Cells[] construct. So the button could look like

CellPrint@ExpressionCell[Button["Evaluate",
   NotebookDelete[Cells[CellTags -> "calculationbutton"]];
   CellPrint@ExpressionCell[Cos[Pi/6],
     "Output", CellTags -> "calculationbutton"], Method -> "Queued"], 
  "Text"]

And I would also just close the instruction cell to hide it, e.g.:

Cell[CellGroupData[{Cell[BoxData[
 RowBox[{"CellPrint", "@", 
  RowBox[{"ExpressionCell", "[", 
   RowBox[{
    RowBox[{"Button", "[", 
     RowBox[{"\"\<Evaluate\>\"", ",", "\[IndentingNewLine]", 
      RowBox[{
       RowBox[{"NotebookDelete", "[", 
        RowBox[{"Cells", "[", 
         RowBox[{"CellTags", "->", "\"\<calculationbutton\>\""}], 
         "]"}], "]"}], ";", "\[IndentingNewLine]", 
       RowBox[{"CellPrint", "@", 
        RowBox[{"ExpressionCell", "[", 
         RowBox[{
          RowBox[{"Cos", "[", 
           RowBox[{"Pi", "/", "6"}], "]"}], ",", 
          "\[IndentingNewLine]", "\"\<Output\>\"", ",", 
          RowBox[{
          "CellTags", "\[Rule]", "\"\<calculationbutton\>\""}]}], 
         "]"}]}]}], ",", 
      RowBox[{"Method", "\[Rule]", "\"\<Queued\>\""}]}], "]"}], ",", 
    "\"\<Text\>\""}], "]"}]}]], "Input",
 CellGroupingRules->{GroupTogetherGrouping, 10000.}],

Cell[BoxData[
 ButtonBox["\<\"Evaluate\"\>",
  Appearance->Automatic,
  ButtonFunction:>(NotebookDelete[
     Cells[CellTags -> "calculationbutton"]]; CellPrint[
     ExpressionCell[
      Cos[Pi/6], "Output", CellTags -> "calculationbutton"]]),
  Evaluator->Automatic,
  Method->"Queued"]], "Text",
 CellGroupingRules->{GroupTogetherGrouping, 10000.},
 GeneratedCell->True,
 CellAutoOverwrite->True]
}, {2}]]
share|improve this answer

Another approach is to make the button disable itself.

DynamicModule[{enabled = True}, 
  Dynamic@Button["Evaluate", enabled = False; Print[Cos[Pi/6]], 
  Method -> "Queued", Enabled -> enabled]]

Before clicking on the button

before-clicking

After clicking

after-clicking

share|improve this answer

I realise this question is old, but in my quest to find a solution to a similar problem to OP I have come up with a solution using CellTags and FrontEndExecute (like Rolf M). I try to avoid Dynamic.

Create a cell tag for the cell you want to evaluate with a button. This approach will Evaluate all cells with the same CellTag and depending on the scenario this could be advantageous.

In my example I used the CellTag "cellToEvaluate". (Select CellTag from front-end Cell menu to add cell tags.)

Create a Button that finds and evaluates cells with that CellTag.

Button["Evaluate",FrontEndExecute[FrontEndToken[NotebookLocate["cellToEvaluate"],"Evaluate"]]]

example

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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