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$
  • $\begingroup$ @Kuba, I've checked the reference, this helps a ton! Please post an answer on this! $\endgroup$ – Wjx Jul 24 '16 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 Jul 25 '16 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 Jul 25 '16 at 9:46
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$
  • $\begingroup$ Also, it's hard to write out an function such like selfclose[content, closetime] using this method. $\endgroup$ – Wjx Jul 24 '16 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$ – Karsten 7. Jul 25 '16 at 11:41
  • $\begingroup$ Yes, this is better than mine~ $\endgroup$ – Wjx Jul 25 '16 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$ – Karsten 7. Jul 25 '16 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$
  • $\begingroup$ This is truely inspiring. I surely hope I can accept two answers at the same time! $\endgroup$ – Wjx Jul 25 '16 at 23:01

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.