#Override
public void start(Stage primaryStage) {
playerIsSelected = false;
enemyIsSelected = false;
Blockquote Can be compiled, but when I click the EXIT button, it shows that the error as: Exception in thread "JavaFX Application Thread" java.lang.NullPointerException.And the Exit button click doesn't exit the window.
there is nowhere in your code that the identifier stage is defined. However, since your code is compiling I would assume this is defined outside of the method. Though, considering you've invoked primaryStage.show(); then eventually you might want to perform primaryStage.close();.
change this:
public void exit(){
stage.close(); //<-- cause of the NullPointerException
}
to this:
public void exit(){
primaryStage.close();
}
Related
I wrote the defaultCloseOperation function of the primaryStage, but I have an exit button too and I want to run that defaultCloseOperation.
I tried to call the close() and the hide() methods of the stage but it exit immediately without calling my defaultCloseOperation function, but I need to call it because I need to release all the resources from the server side when I close the client.
Do not do this on a closing operation of a Stage.
This is what the Application.stop method should be used for.
#Override
public void stop() throws Exception {
// TODO: release resources here
}
If there are resources used for one of multiple windows however, you should use an event handler for the onHidden event - no need to extend Stage:
stage.setOnHidden(event -> {
// TODO: release resources here
});
you can see it:
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override public void handle(WindowEvent t) {
System.out.println("CLOSING");
}
});
and here:
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
// take some action
...
// close the dialog.
Node source = (Node) actionEvent.getSource();
Stage stage = (Stage) source.getScene().getWindow();
stage.close();
}
}
more of explanation you can read here
Refer to the code snippet below:
public class Application extends javafx.application.Application implements ActionListener {
private java.awt.SystemTray tray;
private java.awt.TrayIcon trayIcon;
private java.awt.PopupMenu popupMenu = new PopupMenu();
private java.awt.MenuItem menuItem = new MenuItem("My Item");
#Override
public void start(Stage primaryStage) throws Exception {
if (!SystemTray.isSupported())
return;
menuItem.addActionListener(this);
popupMenu.add(menuItem);
trayIcon = new TrayIcon(image, "Title", popupMenu);
tray = SystemTray.getSystemTray();
tray.add(trayIcon);
}
#Override
public void actionPerformed(ActionEvent e){
Platform.runLater(() -> {
Optional<String> result = new TextInputDialog().showAndWait();
if(result.isPresent() && !result.get().isEmpty()){
...
}
})
}
}
What happens is the dialog will only show once. The second or more time actionPerformed() is triggered, it won't popup and doesn't throw any exception.
I've tried using Task, setOnSucceeded() on that Task, and start a Thread based on that Task. Even worse, the dialog won't show up at all, and again, no error produced.
You need to set the following:
Platform.setImplicitExit(false);
Otherwise the JavaFX runtime will shut down when you close your last window, hence why Platform.runLater() only works once for you
Snippet from Platform:
Sets the implicitExit attribute to the specified value. If this
attribute is true, the JavaFX runtime will implicitly shutdown when
the last window is closed; the JavaFX launcher will call the
Application.stop() method and terminate the JavaFX application thread.
If this attribute is false, the application will continue to run
normally even after the last window is closed, until the application
calls exit(). The default value is true.
In JavaFX, how can I get the event if a user clicks the Close Button(X) (right most top cross) a stage?
I want my application to print a debug message when the window is closed. (System.out.println("Application Close by click to Close Button(X)"))
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
// Any Event Handler
//{
System.out.println("Application(primaryStage) Closed by click to Close Button(X)");
//}
}
I got the answer for this question
stage.setOnHiding(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
Platform.runLater(new Runnable() {
#Override
public void run() {
System.out.println("Application Closed by click to Close Button(X)");
System.exit(0);
}
});
}
});
Another method for achieving the same effect, but remains more consistent with the way you start your application is to override stop();
According to the JavaFX documentation, the lifecycle of an instance of an Application is as follows:
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
As a result you simply override stop()
#Override
public void stop(){
System.out.println("Stage is closing");
}
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent we) {
System.out.println("Stage is closing");
}
});
I have to write a method that will do something when the user closes a window. So far I managed to write this code but it does not work (i placed it in my initialize method in my controller) :
Scene scene = myTable.getScene();
Window window = null;
if (scene != null)
{
window = scene.getWindow();
System.out.println("scene is not null");
window.addEventHandler(WindowEvent.WINDOW_HIDDEN, new EventHandler<WindowEvent>
()
{
#Override
public void handle(WindowEvent w)
{
System.out.println("do somethong here");
};
});
Unfortunately Even my message "scene is not null does not get displayed. Does anyone have a better idea on how to do it?
If you want to do something when the user closes the window you should use the setOnCloseRequest() method like this :
window.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
//do something
}
});
Now if scene is null then this code won't be executed and nothing will happen, maybe a little System.out.println(scene); before the test would help you debug this issue.
Add a change listener to the scene property of the table, and only add your event handler when the scene is changed to a non-null value.
As recommended by Marc, calling setOnCloseRequest or setOnHidden, is probably a better way to configure your EventHandler.
I currently have some code that makes a button in the primaryStage that spawns a new stage. My goal is to have the button close the stage it's on using the setOnMouseClicked method right after launching the new one. Here is how it's currently setup:
#Override
public void start(Stage primaryStage) {
setPlayBtn();
}
private void setPlayBtn() {
play = new ImageView(new Image(BugWars.class.getResourceAsStream("images/play-btn.png")));
play.setFitHeight(50);
play.setFitWidth(50);
play.setX(375);
play.setY(375);
play.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
setGame(); // This creates the new stage.
primaryStage.close();
}
});
Unfortunately this doesn't work. Netbeans complains that it can't find the symbol. It thinks it's a variable. I'm sure it's something stupid, but any help referencing the primaryStage would be appreciated. Thanks guys!
So I've worked around the problem by simply making the PlayBtn instatiate inside of the start() method that(I believe) creates primaryStage and then making primaryStage final. I don't know why this works, but it does.