This is the Scenario.
I have Code which intiates a Alram when an error is encountered.
AudioAlarm t = new AudioAlarm(song);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Awake");
t.start();
setRunnung(true);
JOptionPane.showMessageDialog(null, "Alarm ...", "Alarm", JOptionPane.OK_OPTION);
AudioAlarm.setLoop(false);
System.out.println("Alarm Acknowledged ...");
I would like to re-design this logic in this manner,
If the Alarm is unacknowledged by the user over a period of time say 2 min, it turn off and message msg dialog should disappear.
How can I Obtain this?
I am able to Stop the Alram, but unable to dispose the dialog without the user pressing "OK"
To do what you want, you should:
Create a JOptionPane instance using one of its constructors
Call createDialog on this option pane to get a dialog containing this option pane
Use a javax.swing.Timer instance in order to fire an action event after 2 minutes
add an action listener to this timer which would close the dialog containing the option pane
show the dialog containing the option pane.
I do not know if what you are after can be done, but can't you instead replicate the JOptionPane as a JFrame and dispose of that one? You can find how to close a JFrame on this Previous SO Post:
If you want the GUI to behave as if
you clicked the "X" then you need to
dispatch a windowClosing Event to the
Window. The "ExitAction" from Closing
An Application allows you to add this
functionality to a menu item or any
component that uses Actions easily.
Related
I'm currently creating a dialog using JavaFX. The Dialog it self works very well but now I'm trying to add an input validation which warns the user when he forgets to fill out a text field.
And here comes my question: Is it possible to prevent the dialog from closing inside the Result Converter? Like this:
ButtonType buttonTypeOk = new ButtonType("Okay", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().add(buttonTypeOk);
dialog.setResultConverter((ButtonType param) -> {
if (valid()) {
return ...
} else {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setHeaderText("Pleas fill all fields!");
alert.showAndWait();
//prevent dialog from closing
}
});
I noticed that the dialog dosn't close if an error was thrown inside the resault converter but this doesn't seems to be a good way to solve this problem.
If it isn't possible to solve the problem this way I could disable the button as described in this post. But I would prefer to keep the button enabled and display a message.
Thank you in advance !
How you are supposed to manage data validation in a dialog is actually explained in the Javadoc, I quote:
Dialog Validation / Intercepting Button Actions
In some circumstances it is desirable to prevent a dialog from closing
until some aspect of the dialog becomes internally consistent (e.g. a
form inside the dialog has all fields in a valid state). To do this,
users of the dialogs API should become familiar with the
DialogPane.lookupButton(ButtonType) method. By passing in a ButtonType
(that has already been set in the button types list), users will be
returned a Node that is typically of type Button (but this depends on
if the DialogPane.createButton(ButtonType) method has been
overridden). With this button, users may add an event filter that is
called before the button does its usual event handling, and as such
users may prevent the event handling by consuming the event. Here's a
simplified example:
final Button btOk = (Button) dlg.getDialogPane().lookupButton(ButtonType.OK);
btOk.addEventFilter(
ActionEvent.ACTION,
event -> {
// Check whether some conditions are fulfilled
if (!validateAndStore()) {
// The conditions are not fulfilled so we consume the event
// to prevent the dialog to close
event.consume();
}
}
);
In other words, you are supposed to add an event filter to your button to consume the event in case the requirements are not fulfilled which will prevent the dialog to be closed.
More details here
One other way to solve this is by using setOnCloseRequest if you don't want to relay only on the user clicking the "Okay" button. The event handler will be called when there is an external request to close the Dialog. Then the event handler can prevent dialog closing by consuming the received event.
setOnCloseRequest(e ->{
if(!valid()) {
e.consume();
}
});
I want to save a file before closing my JavaFX application.
This is how I'm setting up the handler in Main::start:
primaryStage.setOnCloseRequest(event -> {
System.out.println("Stage is closing");
// Save file
});
And the controller calling Stage::close when a button is pressed:
#FXML
public void exitApplication(ActionEvent event) {
((Stage)rootPane.getScene().getWindow()).close();
}
If I close the window clicking the red X on the window border (the normal way) then I get the output message "Stage is closing", which is the desired behavior.
However, when calling Controller::exitApplication the application closes without invoking the handler (there's no output).
How can I make the controller use the handler I've added to primaryStage?
If you have a look at the life-cycle of the Application class:
The JavaFX runtime does the following, in order, whenever an
application is launched:
Constructs an instance of the specified Application class
Calls the init() method
Calls the start(javafx.stage.Stage) method
Waits for the application to finish, which happens when either of the following occur:
the application calls Platform.exit()
the last window has been closed and the implicitExit attribute on Platform is true
Calls the stop() method
This means you can call Platform.exit() on your controller:
#FXML
public void exitApplication(ActionEvent event) {
Platform.exit();
}
as long as you override the stop() method on the main class to save the file.
#Override
public void stop(){
System.out.println("Stage is closing");
// Save file
}
As you can see, by using stop() you don't need to listen to close requests to save the file anymore (though you can do it if you want to prevent window closing).
Suppose you want to ask the user if he want to exit the application without saving the work. If the user choose no, you cannot avoid the application to close within the stop method. In this case you should add an EventFilter to your window for an WINDOW_CLOSE_REQUEST event.
In your start method add this code to detect the event:
(Note that calling Platform.exit(); doesn't fire the WindowEvent.WINDOW_CLOSE_REQUEST event, see below to know how to fire the event manually from a custom button)
// *** Only for Java >= 8 ****
// ==== This code detects when an user want to close the application either with
// ==== the default OS close button or with a custom close button ====
primaryStage.getScene().getWindow().addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST, this::closeWindowEvent);
Then add your custom logic. In my example i use an Alert popup to ask the user if he/she want to close the application without saving.
private void closeWindowEvent(WindowEvent event) {
System.out.println("Window close request ...");
if(storageModel.dataSetChanged()) { // if the dataset has changed, alert the user with a popup
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.getButtonTypes().remove(ButtonType.OK);
alert.getButtonTypes().add(ButtonType.CANCEL);
alert.getButtonTypes().add(ButtonType.YES);
alert.setTitle("Quit application");
alert.setContentText(String.format("Close without saving?"));
alert.initOwner(primaryStage.getOwner());
Optional<ButtonType> res = alert.showAndWait();
if(res.isPresent()) {
if(res.get().equals(ButtonType.CANCEL))
event.consume();
}
}
}
The event.consume() method prevents the application from closing. Obviously you should add at least a button that permit the user to close the application to avoid the force close application by the user, that in some cases can corrupt data.
Lastly, if you have to fire the event from a custom close button, you can use this :
Window window = Main.getPrimaryStage() // Get the primary stage from your Application class
.getScene()
.getWindow();
window.fireEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSE_REQUEST));
Ahh this is a known bug in JavaFX where the Stage will not close if a modal dialog is present at the time of closing. I will link you to the bug report which I just saw today. I think it is fixed in the latest release.
Here you go:
https://bugs.openjdk.java.net/browse/JDK-8093147?jql=text%20~%20%22javafx%20re-entrant%22
resolved in 8.4 it says. I think this what you are describing.
public Stage getParentStage() {
return (Stage) getFxmlNode().getScene().getWindow();
}
btnCancel.setOnAction(e -> {
getParentStage().close();
});
I am trying to catch SWT events, like SWT.activate, SWT.deactivate and SWT.dispose in Eclipse. So, I can see which dialog was opened or activated, which was closed and which was deactivated. If the event was caught, I extract the Shell object and extracts its title with shell.getText(). To listen to events, I used an untyped listener (edited):
PlatformUI.getWorkbench().getDisplay().addFilter(SWT.Activate, shellListener);
Listener shellListener = new Listener(){
#Override public void handleEvent(Event e) {
if (event.widget.getClass() == org.eclipse.swt.widgets.Shell.class){
Shell shell = (Shell) e.widget;
String shellTitle = shell.getText();
if (event.type == Activate) {
String message = "The following dialog was activated: " + shellTitle;
// do other stuff with 'message'
}
}
}
};
If in Eclipse I open 'New' and the listener above correctly displays 'New' as activated dialog. But if I select 'Java Interface' within the 'New' dialog, then I am landing in a dialog, called 'New Java Interface'. But my handleEvent method is not fired and therefore I cannot extract the new dialog title. My question is: What kind of event is called or what happens, when I am in an Eclipse dialog and clicking on something in it which leads me to another dialog (with a new title)?
I think the problem here comes from the fact that the New 'dialog' in Eclipse is actually a Wizard. When you select 'Java Interface' (in the 'New' dialog) you are actually then landing not in another dialog but on a page within the same wizard. Every page in this wizard can have it's own title but behind the scene it is the same underlying shell object, that is why you don't receive further events.
By the way: when working with the SWT.Activate, SWT.Deactivate and other similar shell events, it might be helpflul / easier to the a ShellAdapter
Good day every one, i have such situation :
SomeDocument doc = DocumentsContainner.getDocument(doc);
try {
DocumentUtitlites.parseDocument(doc);
} catch (DocumentParseException e) {
ManualParsingFrame frame = new ManualParsingFrame(doc);
frame.show();
}
NextStageOfUsingDoc(doc);
ManualParsingFrame is frame where user can see doc text and parsing in manually by selecting text .It's appear as u can see only when parseDocument(SomeDocument doc) throw exception. When user ends manually parsing text he click ok button wich is on frame.
And start NextStageOfUsingDoc - some other staff that can be processed only if doc was parse by parseDocument or by user ManualParsingFrame. The question is How to make invoke NextStageOfUsingDoc when user click ok button. Now if i have exception i see frame, but process is continue execution and in result i have visible frame and NextStageOfUsingDoc invoked with non parsed doc object. Thank u for your time.
Don't use a JFrame for this. Show your manual parsing info in a modal JDialog. This will stop program flow in the calling program until the modal dialog has been dealt with.
I'm working on Java and I'm trying to display a confirmation message to the user when he wants to exit but I didn't know where I have to put it exactly. may you help me?
You can stop frame from closing by default by using WindowConstants.DO_NOTHING_ON_CLOSE as peram to below API
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
/* (non-Javadoc)
* #see java.awt.event.WindowAdapter#windowClosing(java.awt.event.WindowEvent)
*/
#Override
public void windowClosing(WindowEvent e) {
//Use JOptionPane. If everything goes fine
//then do frame.dispose();
}
});
If your exit is being done by pressing the x button on the window then you need to handle the windows events.
To get the confirmation message you need to pop up a JOptionPane.
There is a discussion of a number of ways to handle the window closing here:
How can a Swing WindowListener veto JFrame closing
Documentation on JOptionPane is here:
http://docs.oracle.com/javase/7/docs/api/javax/swing/JOptionPane.html
Add a WindowListner to your JFrame and override windowClosing method and do a pop-up with JOptionPane warning user.