Can I interrupt a closing of a sketch to save data?

Hello all,

Can I interrupt a closing of a sketch to save data?

When Alt-F4 is pressed or the cross in the window is clicked (OS = Windows), the program closes.

I would like to interrupt this, to save a file that the user changed.
I this possible?

Thanks!

Regards, Chrisir

P.S.

This belongs to the project: Can I make a small windows app for taking time and log production times?

1 Like

You can do this by registering a method like this :

void setup() {
registerMethod("dispose", this);
}

void dispose() {
//your Code Here
}

Apparently you can also do this :

void exit() {
   //your Code Here. 
   super.exit();
}

I havenā€˜t Tested both, so no idea if they really work like that.

2 Likes

They work with ESC but not with Alt-F4 / cross

  • they can execute println (ā€œClosingā€); in both cases [ESC AND Alt-F4 / cross ]
  • but they donā€™t leave the function exit and go back to draw with Alt-F4 / cross [with ESC it works]
1 Like

Take a look at :

((java.awt.Window) ((processing.awt.PSurfaceAWT.SmoothCanvas)getSurface().getNative()).getFrame()).getWindowListeners();

One of those should handle the Alt-F4 Event, but i donā€˜t know how to get the precise one. Iā€˜ll look into it a bit more and tell you when i find something :wink:

Ugh, ok i tried to find something, but apparently the only way to remove one is to have the specific Event as a WindowListener already, but i donā€˜t know how to identify the right one. So you might want to just override the existing one by adding a new one with the addWindowListener() function, but iā€˜m not sure if thatā€˜s goodā€¦

1 Like

Chris,
I have these links for reference:

I hope this code below helps.

Cheers,
Kf

void setup(){
  size(400,600);
  fill(255);
  prepareExitHandler();
}


void draw(){background(0);ellipse(mouseX,mouseY,50,70);}

void keyPressed(){
 if(key==' ') exit(); 
}

private void prepareExitHandler () {

  Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

    public void run () {

      System.out.println("SHUTDOWN HOOK");

      // application exit code here
    }
  }
  ));
}
1 Like

I will look into this later.

My plan was to interrupt ESC / Alt-F4 / cross and go to a state to ask the User save changes / discard changes / abort (stay in the program).

Then depending on the answer action is taken. (When we say exit(); the same exit function would be run again but I imagined with a flag we could:

  • in the 1st run: leave function with return before it gets to its end, hence not leave the sketch

  • in the 2nd run skip return (due to the flag), let it run to its end and thus leave the sketch

)

1 Like

Yeah, I am not sure if this will help you in your case.
An idea would be to separate your program from the sketch and keep track of your programā€™s state. The main P3 sketch could be run as an invisible sketch which launches a second sketch and it is there where you manage your program. If the user exits and the prompt declines the exit step, you could close the second ā€œchildā€ sketch and open a new one loading the current state of your program.

I hope there is a better way to do this though. That is my suggestion and probably not applicable if you are not managing states.

You will also need to keep in mind that if the OS kills your program, you might not have an option but to exit without this flow. Just thinking out loudā€¦

Kf

1 Like

What happens when you press Alt-F4 is that your application is asked to close, but itā€˜s not forces. Only the WindowListeners Closing event is called.

What exactly happens is left to you, but that ā€žyouā€œ in this case is the way that processing handles this case, so overriding it might not be a good ideaā€¦ on the other Hand, you can probably see how probably handles this and if it only calls dispose() or so, then that would be perfect, but i donā€˜t know thatā€¦

Found it! This is what Processing does internally :

//sketch is a field of PSurfaceNone of class PApplet
//frame is a Java.awt.Frame field in PSurfaceAWT

frame.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent e) {
        sketch.exit();  // don't quit, need to just shut everything down (0133)
      }
    });

So you can just use this :

PSurfaceAWT frame = (processing.awt.PSurfaceAWT.SmoothCanvas)getSurface().getNative()).getFrame();

PApplet sketch = this;

void setup() {

   frame.addWindowListener(
      new WindowAdapter() {
         @Override
         public void windowClosing(WindowEvent e) {
            //put your Code here
            if (readyToClose())
               sketch.exit();
         }
      }

}

boolean readyToClose() {
   if (allSaved) {
      return true;
   } else {
      return false;
   }
}
4 Likes