Reputation: 6352
I want to create a Singleton main class in JavaFX but I am having difficulties because the main class must extend Application, so the constructor can't be private.
I want the main class to be a Singleton because I want to access a couple of instance methods from any class.
In my current code I am using the main class as a fake Singleton because I do not provide any guarantee that the class will not be instantiated again in some part of the code.
I would like to know if there is a decent way to create a Singleton when you can't use private constructors.
Here is the code of my main class:
public final class MainClass extends Application {
private static MainClass instance;
private Stage primaryStage, optionsStage;
@Override
public void start(final Stage primaryStage) {
instance = this;
try {
// Main scene.
{
Parent page = (Parent) FXMLLoader.load(
MainWindowController.class.getResource("main.fxml"));
Scene mainScene = new Scene(page);
primaryStage.setScene(mainScene);
primaryStage.show();
}
// Options scene.
{
optionsStage = new Stage();
optionsStage.setTitle("Options");
optionsStage.setResizable(false);
optionsStage.initModality(Modality.APPLICATION_MODAL);
optionsStage.initOwner(primaryStage);
Parent page = (Parent) FXMLLoader.load(
OptionsWindowController.class.getResource("options.fxml"));
Scene scene = new Scene(page);
optionsStage.setScene(scene);
}
} catch (Exception ex) {
Constants.LOGGER.log(Level.SEVERE, ex.toString());
}
}
/**
* Returns the instance of this class.
* @return
*/
public static MainClass getInstance() {
return instance;
}
public Stage getPrimaryStage() {
return primaryStage;
}
/**
* Returns the options stage.
* @return
*/
public Stage getOptionsStage() {
return optionsStage;
}
/**
* The main() method is ignored in correctly deployed JavaFX
* application. main() serves only as fallback in case the
* application can not be launched through deployment artifacts,
* e.g., in IDEs with limited FX support. NetBeans ignores main().
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 1
Views: 4788
Reputation: 4569
I'd think that adding a public constructor like the following and removing the instance = this;
assignment in your start
method would do the trick, although I am not well-versed in JavaFX. I don't think it would ever try to instantiate your main class more than once, but if the API makes no such guarantee, you might find yourself in trouble later on down the road.
In any case... you'd find out pretty darn quickly if you did something like the following:
public MainClass(){
super();
synchronized(MainClass.class){
if(instance != null) throw new UnsupportedOperationException(
getClass()+" is singleton but constructor called more than once");
instance = this;
}
}
NetBeans' compiler (if you're using it) will whine about a "leaking this
", but this will guarantee that you don't run the constructor to completion more than once.
Upvotes: 4