6
$\begingroup$

I'm currently making an interface in Mathematica and I'll need to bump a window out and then let it close itself in a certain amount of time.

Here's an short example to illustrate the effect:

new = CreateDialog[Plot[x^2, {x, 0, 1}]];
Pause@3;
NotebookClose[new]

However, I may need the window to keep opening for minutes before it close itself and at the same time, there'll be a lot of processes and calculations running:

t=Now;
new = CreateDialog[Plot[x^2, {x, 0, 1}]];
Pause@3;
NotebookClose[new]
Prime /@ Range@1000000;
Now-t
(*A long time......consumed 3s unnecessary time*)

This will not be acceptable.

So, my problem is, how to solve this problem?

$\endgroup$
3
  • $\begingroup$ @Kuba, I've checked the reference, this helps a ton! Please post an answer on this! $\endgroup$
    – Wjx
    Commented Jul 24, 2016 at 23:29
  • $\begingroup$ Sorry for the confusion...... I want to open a dialog which will close itself in, for example, 10 seconds. This action should not take much calculation time. Then, after the creation of this dialog, run the code after this piece of code. Is this clear this time? $\endgroup$
    – Wjx
    Commented Jul 25, 2016 at 9:30
  • $\begingroup$ it's set when the dialog is created, then it will be the dialog itself's job to close it in 10 seconds. $\endgroup$
    – Wjx
    Commented Jul 25, 2016 at 9:46

3 Answers 3

3
$\begingroup$

This is what I understood OP needs:

SetAttributes[foo, HoldFirst];

foo[proc_] := Module[{dialog},
  dialog = MessageDialog["whatever"];
  RunScheduledTask[NotebookClose @ dialog, {3}];
  proc]

a more advanced example can be found in

Palette button with progress bar

$\endgroup$
2
$\begingroup$

Oh, sorry everyone. I've got an answer here right after I posted my answer......

But I think this solution may be helpful for other users annoyed with Pause:

new = CreateDialog[Plot[x^2, {x, 0, 1}]];
PrintTemporary@DynamicModule[{t = Now, check = True},
   Dynamic[
    If[check && Now - t >= Quantity[3, "Seconds"], NotebookClose[new];
      check = False], UpdateInterval -> .2]];
Print@1
Prime /@ Range@1000000;

Much smoother.

The key of this answer is to use dynamic link between Kernel and FrontEnd instead of the normal link used for calculations. In this way, the dynamic will keep running while normal evaluations running too!

But there still is a problem: Here I used PrintTemporary and Print to deal with the Dynamic to make it disappear and stop wasting energy after it finished its duty. How to solve this problem better? This method is so rude and not that elegant......

$\endgroup$
4
  • $\begingroup$ Also, it's hard to write out an function such like selfclose[content, closetime] using this method. $\endgroup$
    – Wjx
    Commented Jul 24, 2016 at 14:54
  • 1
    $\begingroup$ selfclose[content_, closetime_] := Module[{new = CreateDialog[content]}, Dynamic[ If[Clock[closetime, closetime, 1] == closetime, NotebookClose[new]; NotebookDelete[EvaluationCell[]], ""], UpdateInterval -> closetime]] and then selfclose[Plot[x^2, {x, 0, 1}], 3] $\endgroup$
    – Karsten7
    Commented Jul 25, 2016 at 11:41
  • $\begingroup$ Yes, this is better than mine~ $\endgroup$
    – Wjx
    Commented Jul 25, 2016 at 12:55
  • $\begingroup$ I added an answer where the Dynamic stuff is all part of the dialog and therefore will disappear with it. $\endgroup$
    – Karsten7
    Commented Jul 25, 2016 at 22:36
2
$\begingroup$

A self-closing dialog window using NotebookDynamicExpression

selfclose1[content_, closetime_] := CreateDialog[
  Column[{
    content,
    CancelButton[ImageSize -> Full]}],
  NotebookDynamicExpression -> 
   Dynamic[Refresh[
     If[Clock[closetime, closetime, 1] == closetime, NotebookClose[]],
      UpdateInterval -> closetime, TrackedSymbols :> {}], None, 
    UpdateInterval -> Infinity, TrackedSymbols :> {}]]

or a DynamicWrapper

selfclose2[content_, closetime_] := CreateDialog[
  Column[{
    DynamicWrapper[
     content,
     Refresh[
      If[Clock[closetime, closetime, 1] == closetime, 
       NotebookClose[]], UpdateInterval -> closetime, 
      TrackedSymbols :> {}], UpdateInterval -> Infinity, 
     TrackedSymbols :> {}, Evaluator -> None],
    CancelButton[ImageSize -> Full]}]]

Test 1:

selfclose2[Plot[x^2, {x, 0, 1}], 3]

Test 2:

AbsoluteTiming[
 First@AbsoluteTiming[
    With[{t = 3}, 
     selfclose1[ProgressIndicator[Dynamic[Clock[t, t, 1]], {0, t}], t]]; 
    Prime /@ Range@500000] - 
  First@AbsoluteTiming[Prime /@ Range@500000]
 ]

GIF


Instead of a Clock, one could also use

AbsoluteTime[TimeZone -> 0] - ("MemoryModificationTime" /. NotebookInformation[])

or increment a local variable.

$\endgroup$
1
  • $\begingroup$ This is truely inspiring. I surely hope I can accept two answers at the same time! $\endgroup$
    – Wjx
    Commented Jul 25, 2016 at 23:01

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.