Stage is hidden when dialog is shown - javafx-2

I have this code which displays confirmation dialog to exit application.
public class DialogPanels
{
public void initClosemainAppDialog(final Stage primaryStage)
{
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
#Override
public void handle(WindowEvent event)
{
event.consume(); // Do nothing on close request
// Dialog Stage init
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
// Frage - Label
Label label = new Label("Exit from the program");
// Button "Yes"
Button okBtn = new Button("Yes");
okBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
//primaryStage.close();
//dialog.close();
//Platform.exit();
System.exit(0);
}
});
// Button "No"
Button cancelBtn = new Button("No");
cancelBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
primaryStage.show();
dialog.close();
}
});
// Layout for the Button
HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(okBtn);
hbox.getChildren().add(cancelBtn);
// Layout for the Label and hBox
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.getChildren().add(label);
vbox.getChildren().add(hbox);
// Stage
Scene scene = new Scene(vbox);
dialog.setScene(scene);
dialog.show();
}
});
}
}
The problem is that when close the main application the dialog box is displayed and the main stage is hidden. I want to display the dialog box in front of the main stage. Can you help me to correct this?
UPDATE
I tested this code, it's working but when the dialog is displayed the mainstage is not responsible(frozen). How I an make the mainstage responsible when I display dialog?

Consume the closing event and set the owner of the stage if you do not want to see another window when the windows are minimized:
#Override
public void handle(WindowEvent event)
{
event.consume(); // Do nothing on close request
// Dialog Stage init
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(primaryStage);
// other stuff
}
});

You need to set the proper relationships between primaryStage and dialog stage. Here's a hint to get you going:
...
dialog.initOwner(primaryStage);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.showAndWait();
You can find more information in Oracle's JavaFX 2 JavaDocs.
More example code (edit)
I'm using setOnHiding(..) instead of setOnCloseRequest(..):
stage.setOnHiding(new AskUserIfHeReallyWantsToQuitWindowHandler(stage));
I extracted your code into a seperate event handler class and fixed the issues I mentioned (sorry, I am little short on time right now):
public class AskUserIfHeReallyWantsToQuitWindowHandler implements EventHandler<WindowEvent> {
private final Stage primaryStage;
public AskUserIfHeReallyWantsToQuitWindowHandler(final Stage primaryStage) {
Objects.requireNonNull(primaryStage);
this.primaryStage = primaryStage;
}
#Override
public void handle(final WindowEvent event) {
event.consume();
final Stage dialog = new Stage();
final Button okBtn = new Button("Yes");
okBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(final ActionEvent event) {
dialog.close();
primaryStage.close();
}
});
// Button "No"
final Button cancelBtn = new Button("No");
cancelBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(final ActionEvent event) {
dialog.close();
Platform.runLater(new Runnable() {
#Override
public void run() {
primaryStage.show();
}
});
}
});
// Layout for the Button
final HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(okBtn);
hbox.getChildren().add(cancelBtn);
// Layout for the Label and hBox
final VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.getChildren().add(new Label("Do your really want to exit?"));
vbox.getChildren().add(hbox);
// Stage
final Scene scene = new Scene(vbox);
dialog.setScene(scene);
dialog.initOwner(primaryStage);
dialog.initModality(Modality.NONE);
dialog.showAndWait();
}
}

Related

JavaFX task not reruning once canceled or finishing once

I am working on a basic Java FX task exercise. It counts from 1 to 150 on a thread. The current value is presented on a label and updates a progress bar.
There is a button to start the task, to cancel it and to view canceled status of the task.
The thing that puzzles me is as to why I cannot re run the task after having canceled the thread once(same thing happens if I let the task finnish).
I want to be able to rerun the task . Then I need to make it so that it will resume(though that shouldn't be that hard after figuring out how to rerun the task)
Source ;
public class JavaFX_Task extends Application {
#Override
public void start(Stage primaryStage) {
final Task task;
task = new Task<Void>() {
#Override
protected Void call() throws Exception {
int max = 150;
for (int i = 1; i <= max; i++) {
if (isCancelled()) {
break;
}
updateProgress(i, max);
updateMessage(String.valueOf(i));
Thread.sleep(100);
}
return null;
}
};
ProgressBar progressBar = new ProgressBar();
progressBar.setProgress(0);
progressBar.progressProperty().bind(task.progressProperty());
Label labelCount = new Label();
labelCount.textProperty().bind(task.messageProperty());
final Label labelState = new Label();
Button btnStart = new Button("Start Task");
btnStart.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
new Thread(task).start();
}
});
Button btnCancel = new Button("Cancel Task");
btnCancel.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
task.cancel();
}
});
Button btnReadTaskState = new Button("Read Task State");
btnReadTaskState.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
labelState.setText(task.getState().toString());
}
});
VBox vBox = new VBox();
vBox.setPadding(new Insets(5, 5, 5, 5));
vBox.setSpacing(5);
vBox.getChildren().addAll(
progressBar,
labelCount,
btnStart,
btnCancel,
btnReadTaskState,
labelState);
StackPane root = new StackPane();
root.getChildren().add(vBox);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("java-buddy.blogspot.com");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The Task documentation is pretty clear on this.
As with FutureTask, a Task is a one-shot class and cannot be reused. See Service for a reusable Worker.
There is an example of restartable concurrent services in the Service documentation.

javafx background Task is not running more than once

The following is my Task initialization
final Task<Void> vt=voiceTask();
Button btn = new Button();
btn.setText("Say");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
new Thread(vt).start();
}
});
And here is the task coding
public Task<Void> voiceTask() {
return new Task<Void>(){
#Override
protected Void call() throws Exception {
HelloWorld hw=new HelloWorld();// HelloWorld is simple .java class getting voice through sphinx
updateMessage(hw.Hello());
return null;
}
};
}
Now on clicking the btn Button for the first time,the task functions normally, but on clicking for subsequent times the task is not called.
I want task to be called on every click.
Please advice me how to modify my code to do so...
See the JavaDocs.
As with FutureTask, a Task is a one-shot class and cannot be reused.
You need to create a new Task each time the button is pressed.
final Button btn = new Button();
btn.setText("Say");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
final Task<Void> vt=voiceTask();
vt.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
btn.setDisable(false);
}
});
btn.setDisable(true);
new Thread(vt).start();
}
});

How to create modal dialog with image

I have this very simple modal dialog:
public class DialogPanels
{
public void initClosemainAppDialog(final Stage primaryStage)
{
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
#Override
public void handle(WindowEvent event)
{
event.consume(); // Do nothing on close request
// Dialog Stage init
final Stage dialog = new Stage();
// If you want to freeze the background during dialog appearence set Modality.APPLICATION_MODAL
// or to allow clicking on the mainstage components set Modality.NONE
// and set dialog.showAndWait();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(primaryStage);
// Frage - Label
Label label = new Label("Exit from the program");
// Button "Yes"
Button okBtn = new Button("Yes");
okBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
//primaryStage.close();
//dialog.close();
//Platform.exit();
System.exit(0);
}
});
// Button "No"
Button cancelBtn = new Button("No");
cancelBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
primaryStage.show();
dialog.close();
}
});
// Layout for the Button
HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(okBtn);
hbox.getChildren().add(cancelBtn);
// Layout for the Label and hBox
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.getChildren().add(label);
vbox.getChildren().add(hbox);
// Stage
Scene scene = new Scene(vbox, 450, 150, Color.WHITESMOKE);
dialog.setScene(scene);
dialog.show();
}
});
}
}
I want to add image and to make it to look like this:
But I admin that it's too complex for my short knowledge to get the appropriate result. Can you show me how I can split the dialog, add second background and make my code to look the same as this example please?
Have a look at the ControlsFX project, they have some sophisticated dialogs and it's open source, so you can look up how it's done. For example, your dialog looks like this confirmation dialog of ControlsFX:
There is also support for custom dialogs.
€dit:
With the "show Masthead" option enabled it actually looks exactly like it:

Make menubar call method when it is clicked?

I am wanting to add an empty javafx.scene.control.Menu to a MenuBar and have it call a method when it is clicked.
I have tried using menu.setOnShowing(new EventHandler<Event>(){}); with no luck.
Here is what I am currently working with:
public MenuBar createMenuBar() {
MenuBar menuBar = new MenuBar();
Menu file = new Menu("File");
Menu addAccountTab = new Menu("Add Tab");
addAccountTab.setOnShowing(new EventHandler<Event>() {
public void handle(Event e) {
System.out.println("addAccountTab Menu clicked.");
}
});
menuBar.getMenus().add(addAccount);
return menuBar;
}
However, clicking the Menu does not call the onShowing event.
Your Menu needs to contain at least one MenuItem for the event to fire.
public class MenuApplication extends Application {
#Override
public void start(Stage primaryStage) {
MenuBar menuBar = new MenuBar();
Menu file = new Menu("File");
Menu addAccountTab = new Menu("Add Tab");
addAccountTab.setOnShowing(new EventHandler<Event>() {
#Override
public void handle(Event e) {
System.out.println("addAccountTab Menu clicked.");
}
});
MenuItem NewMenuItem = new MenuItem("New");
addAccountTab.getItems().add(NewMenuItem);
menuBar.getMenus().addAll(file, addAccountTab);
StackPane root = new StackPane();
root.getChildren().add(menuBar);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The output I get is shown below:
Although the API suggests otherwise, the onShowing event doesn't get called when there are no MenuItems in the Menu or when they are all hidden.
I was able to solve the issue by using Menu's hide() method inside of the onShown event like this.
public MenuBar createMenuBar() {
MenuBar menuBar = new MenuBar();
Menu addAccount = MenuBuilder.create()
.onShown(new EventHandler<Event>() {
public void handle(Event e) {
((Menu)e.getSource()).hide();
System.out.println("addAccount Clicked");
}
}).items(new MenuItem())
.text("Add Account").build();
menuBar.getMenus().addAll(addAccount);
return menuBar;
}

How to make drag and drop action in JavaFX 2.2 with Swing?

I have a problem with drag and drop event on JFXPanel that on located JPanel. When i push drag message to DragBoard, javaFX part of application doesnt work anymore. I think its about swing event mechanizm but i am not sure. There is no problem with other events. It made me confused. Is there any solution to this problem? Thanks in advance.
public class MyScene extends Scene {
public MyScene(VBox vBoxMainLayout) {
super(vBoxMainLayout);
HBox hBox = new HBox();
hBox.setPrefSize(10000, 10000);
hBox.setSpacing(40);
Button buttonSource = new Button("Source");
buttonSource.setMinSize(60, 30);
buttonSource.setOnDragDetected(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
Dragboard db = startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
String message = "Drag operatation is done";
content.putString(message);
db.setContent(content);
event.consume();
}
});
buttonSource.setOnDragDone(new EventHandler<DragEvent>() {
public void handle(DragEvent event) {
event.consume();
}
});
TextArea textAreaTarget = new TextArea();
textAreaTarget.setMinSize(200, 500);
hBox.getChildren().add(buttonSource);
hBox.getChildren().add(textAreaTarget);
vBoxMainLayout.getChildren().add(hBox);
}
}
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
VBox vBoxMainLayout = new VBox();
MyScene myScene = new MyScene(vBoxMainLayout);
JFrame frame = new JFrame();
JFXPanel arg0 = new JFXPanel();
arg0.setScene(myScene);
frame.getContentPane().add(arg0);
frame.setVisible(true);
}
}
It was a known deadlock in JavaFX 2.1 and pushed to 2.2 (thats what i learned from oracle ) but i guess it stil not solved.

Resources