javafx maximized window moves if dialog shows up - java

If I create a javafx dialog using the following method:
public static void showDialog(Event event) throws IOException {
dialogStage = new Stage();
GridPane grid = (GridPane) Start.createLoader().load(Start.class.getResource("file.fxml").openStream());
dialogStage.setScene(new Scene(grid));
dialogStage.setTitle("Title");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(((Node) event.getSource()).getScene().getWindow());
dialogStage.showAndWait();
}
the ower window moves in case it is maximized. This also happens if I use:
Modality.APPLICATION_MODAL
It works if I combine:
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage.getOwner());
but in this case the owner window is not blocked.
I want my dialog showing up on a maximized window without moving it. The maximized window should be blocked while the dialog is open. How can I do this?
Btw. I am using java 8 and javafx on linux.
Tanks!

Related

JavaFX 8 Create Undecorated TextInputDialog that behvaes as modal over full screen stage

I have a full screen main application stage and want to make a TextInputDialog appear on top, with a modal style (i.e. the dialog must be dismissed before giving other input to the stage).
If I set the owner to the stage, and the style to UTILITY, then it works.
But if I want to remove decoration (by setting the style to UNDECORATED) then the dialog doesn't appear at all! I can only get it to appear by not setting the parent.
If I don't set the parent, the dialog appears on top of the stage but if I click anywhere else on the application it disappears behind the full screen stage.
How do I create an undecorated dialog that has modal-like behaviour over a full-screen stage?
// This works, but is decorated
TextInputDialog dialog = new TextInputDialog();
dialog.initOwner(stage);
dialog.initStyle(StageStyle.UTILITY);
dialog.showAndWait();
// This doesn't show at all (probably appears underneath the stage?)
TextInputDialog dialog = new TextInputDialog();
dialog.initOwner(stage);
dialog.initStyle(StageStyle.UNDECORATED);
dialog.showAndWait();
// This still allows clicking in the stage while dialog shown. Also causes
// "exit" of fullscreen by showing task bar when dialog is shown
TextInputDialog dialog = new TextInputDialog();
dialog.initStyle(StageStyle.UNDECORATED);
dialog.showAndWait();
I've made a complete example, which appears to be something you've tried, but isn't working. In my case it works great though. The window shows full screen, and the dialog comes up in the center without window decorations.
public class DialogCheck extends Application{
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("text field");
BorderPane root = new BorderPane();
Button b = new Button("dialog");
root.setCenter(b);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.setFullScreen(true);
primaryStage.show();
b.setOnAction((evt)->{
TextInputDialog dialog = new TextInputDialog();
dialog.initOwner(primaryStage);
dialog.initStyle(StageStyle.UNDECORATED);
dialog.showAndWait();
});
}
}
Note that this is with java 11 & openjfx 11 on osx.
For some added debugging:
dialog.setOnShown( sevt ->{
System.out.println("showing: " + dialog.isShowing() + ", " + dialog.getX());
TextField field = dialog.getEditor();
field.requestFocus();
System.out.println(field.isFocused());
});
Also note the difference between using 'showAndWait' vs 'show'.
Dialog.showAndWait output:
showing: false, NaN.
false
Dialog.show output:
showing: true, 621.0
true

How to block a main window in JavaFX

There is a button in a scene of the main window. When it's clicked, the new window is created, according following code:
public static void create()
{
Stage stage = new Stage();
AnchorPane pane = new AnchorPane();
//Here i add some into pane
stage.setScene(new Scene(pane));
stage.setWidth(500);
stage.setHeight(600);
stage.show();
}
I'd like the main window will remain blocked (i.e. an user won't be able to click on buttons, type text, resize or interact with it with other ways) until the additional window is closed.
Here is a link that shows exactly what you're looking for: http://www.javafxtutorials.com/tutorials/creating-a-pop-up-window-in-javafx/
Here is the main part of the code you need to add:
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(btn1.getScene().getWindow());
stage.showAndWait(); // This forces the program to pay attention ONLY to this popup window until its closed
Hope this helps.

JavaFx stop new window stealing focus

Have an issue with JavaFX where whenI popup a new stage, that new window will take focus from any windows application with current focus
I want it to popup to the front, but not take focus, so if the user was typing elsewhere they can continue to type etc.
In Swing you could get around this by:
dialog.setFocusable(false);
dialog.setVisible(true);
dialog.setFocusable(true);
There seems to be no similar option in JavaFx.
Example below, when you click the button it will popup a new stage, taking focus (note I don't want to request focus back, as in the real application the user could be writing an email or on a web page when the popup happens, it needs to not take focus from these activities)
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class Main extends Application {
private Stage stage;
#Override public void start(Stage stage) {
this.stage = stage;
stage.setTitle("Main Stage");
stage.setWidth(500);
stage.setHeight(500);
Button btnPopupStage = new Button("Click");
btnPopupStage.setOnMouseClicked(event -> popupStage());
Scene scene = new Scene(btnPopupStage);
stage.setScene(scene);
stage.show();
}
private void popupStage(){
Stage subStage = new Stage();
subStage.setTitle("Sub Stage");
subStage.setWidth(250);
subStage.setHeight(250);
subStage.initOwner(stage);
subStage.show();
System.out.println("Does main stage have focus : "+stage.isFocused());
System.out.println("Does popup have focus : "+subStage.isFocused());
}
public static void main(String[] args) {
launch(args);
}
}
Any ideas for a stage to not take focus on a stage.show() ? Thanks
Just incase anyone is is searching, I couldn't find a solution, but I found someone with the same issue who raised a ticket for the openjdk
https://bugs.openjdk.java.net/browse/JDK-8090742
To get around it unfortunately I put the JavaFX pane inside a Swing JFrame and just called
dialog.setFocusableWindowState(false);
dialog.setVisible(true);
dialog.setFocusableWindowState(true);
Which has fixed the focus stealing issue, but not sure on the effects of having JFx in a Swing JFrame.
If anyone finds a non focus stealing way of a new Window in JFx let me know.
Thanks
to prevent what you are describing by assuming is the cause of your problem then you need to add subStage.initModality(Modality.NONE); . But that is not the problem, actually there is no problem here look here
stage.setWidth(500); // your stage is 500 wide
stage.setHeight(500); // & 500 long
Scene scene = new Scene(btnPopupStage);// your scene has a parent which is button
//by inheritance if i should say your button is 500 wide & long.
Have you seen the problem? your button will always respond to click events which in event will create a new Stage hence give focus to that Stage

JavaFX virtual keyboard overlaps nodes

i have a question about using virtual keyboard on touch supported pc with Windows 8.1. I have managed to show the virtual keyboard when textfield is focused with java switch:
-Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx
I found how to that on JavaFX Virtual Keyboard doesn't show1.
But when the keyboard show's up, it overlapps nodes below the keyboard.
According to what I read, http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/embed.htm, it should't be working like that.
Does anyone have any experience with that kind of problem?
When i run the test application it shows in full screen and embedded virtual keyboard is showing, becasue the textfield has focus. The textfield in this case is not visible until i "hide" the keyboard. I am not sure that this is the right approach so i need help please.
java -Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx application.TestVKB
public class TestVKB extends Application{
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) throws Exception {
TextField tfComment = new TextField();
tfComment.setPromptText("Enter comment");
BorderPane borderPane = new BorderPane();
borderPane.setBottom(tfComment);
Scene scene = new Scene(borderPane);
stage.setScene(scene);
stage.setMaximized(true);
stage.show();
}
}
After click in field username or password
I would be grateful for any advice. Thanks in advance.
As I've already pointed out in my first answer, the virtual keyboard is embedded in a PopupWindow, created in a different stage, and displayed on top of your current stage.
The option -Dcom.sun.javafx.vk.adjustwindow=true works, moving the main stage so the control is visible and there is no overlapping.
But when this input control is located at the bottom of the main stage, this is moved up to the center of the screen leaving a big empty gap that shows whatever is behind.
This second answer gives a solution to move the main stage just the required distance, without any gap, also taking into account the fade in/out animations of the virtual keyboard.
For starters, in our scene, we add a Button on the center, and the TextField on the bottom. With two controls we can change the focus easily and show/hide the keyboard.
To maximize the stage I'll use getVisualBounds(), so the taskbar can be visible.
private PopupWindow keyboard;
private final Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
private final Rectangle2D bounds = Screen.getPrimary().getBounds();
private final double taskbarHeight=bounds.getHeight()-visualBounds.getHeight();
#Override
public void start(Stage stage) {
TextField tfComment = new TextField();
tfComment.setPromptText("Enter comment");
BorderPane borderPane = new BorderPane(new Button("Click"));
borderPane.setBottom(tfComment);
Scene scene = new Scene(borderPane);
stage.setScene(scene);
stage.setX(visualBounds.getMinX());
stage.setY(visualBounds.getMinY());
stage.setWidth(visualBounds.getWidth());
stage.setHeight(visualBounds.getHeight());
stage.show();
}
We need to find the new stage when it's shown. In the same way as Scenic View, we'll use a deprecated method to get a valid window:
private PopupWindow getPopupWindow() {
#SuppressWarnings("deprecation")
final Iterator<Window> windows = Window.impl_getWindows();
while (windows.hasNext()) {
final Window window = windows.next();
if (window instanceof PopupWindow) {
if(window.getScene()!=null && window.getScene().getRoot()!=null){
Parent root = window.getScene().getRoot();
if(root.getChildrenUnmodifiable().size()>0){
Node popup = root.getChildrenUnmodifiable().get(0);
if(popup.lookup(".fxvk")!=null){
return (PopupWindow)window;
}
}
}
return null;
}
}
return null;
}
We'll call this method when the textfield gets the focus:
...
stage.show();
tfComment.focusedProperty().addListener((ob,b,b1)->{
if(keyboard==null){
keyboard=getPopupWindow();
}
});
}
Once we have the window, we can listen to changes in its position and move the main stage accordingly:
....
stage.show();
//findWindowExecutor.execute(new WindowTask());
tfComment.focusedProperty().addListener((ob,b,b1)->{
if(keyboard==null){
keyboard=getPopupWindow();
keyboard.yProperty().addListener(obs->{
System.out.println("wi "+keyboard.getY());
Platform.runLater(()->{
double y = bounds.getHeight()-taskbarHeight-keyboard.getY();
stage.setY(y>0?-y:0);
});
});
}
});
}
Note that instead of moving up the stage, another option will be resizing it (if there is enough space within the controls).
This will be the case where the textfield gets the focus and the virtual keyboard is fully shown:
Basically, the virtual keyboard is embedded in a PopupWindow, created in a different stage, and displayed on top of your current stage, at the bottom of the screen, no matter where the InputControl that triggers the keyboard is located.
You can see that on the FXVKSkin class:
winY.set(screenBounds.getHeight() - VK_HEIGHT);
But, just inmediately after that, you can find this:
if (vkAdjustWindow) {
adjustWindowPosition(attachedNode);
}
So, there's another command line option that you can use to move the stage so the node (the textfield in this case) will be on the center of the screen and you can type without overlapping it:
-Dcom.sun.javafx.vk.adjustwindow=true
Note that when the textfield loses the focus, the keyboard is hidden and the stage is moved again to its original position:
restoreWindowPosition(oldNode);
I've tested this option successfully, but when you have the textfield at the bottom of the screen, this will move your stage bottom to the center of the screen, leaving a big gap between both stages (you'll see whatever you have on the background).
I've managed to add a listener to the new stage and adjust the position just the necessary. If you are interested I could post it.
EDIT
Note this command line option won't work if the stage is maximized. A simple solution for this is:
Rectangle2D bounds = Screen.getPrimary().getBounds();
stage.setX(bounds.getMinX());
stage.setY(bounds.getMinY());
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.show();
I liked the solution, but in my case I prefer to move the keyboard using the showed method getPopupWindow i created a listener on textfield and changed the position of the keyboard directly.
textField.focusedProperty().addListener((ob, b, b1) -> {
if (keyboard == null) {
keyboard = getPopupWindow();
keyboard.setHideOnEscape(Boolean.TRUE);
keyboard.setAutoHide(Boolean.TRUE);
keyboard.centerOnScreen();
keyboard.requestFocus();
keyboard.sizeToScene();
}
Platform.runLater(() -> {
keyboard.setY(**NEW_POSITION_OF_KEYBOARD**);
});
});

How to create a popup window in javafx [duplicate]

This question already has an answer here:
JavaFX 2 custom popup pane
(1 answer)
Closed 7 years ago.
I want to create a popup window in a JavaFX application. Give me some ideas.
When I click on Check button it opens the popup window.
How to do it?
You can either create a new Stage, add your controls into it or if you require the POPUP as Dialog box, then you may consider using DialogsFX or ControlsFX(Requires JavaFX8)
For creating a new Stage, you can use the following snippet
#Override
public void start(final Stage primaryStage) {
Button btn = new Button();
btn.setText("Open Dialog");
btn.setOnAction(
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(primaryStage);
VBox dialogVbox = new VBox(20);
dialogVbox.getChildren().add(new Text("This is a Dialog"));
Scene dialogScene = new Scene(dialogVbox, 300, 200);
dialog.setScene(dialogScene);
dialog.show();
}
});
}
If you don't want it to be modal (block other windows), use:
dialog.initModality(Modality.NONE);
The Popup class might be better than the Stage class, depending on what you want. Stage is either modal (you can't click on anything else in your app) or it vanishes if you click elsewhere in your app (because it's a separate window). Popup stays on top but is not modal.
See this Popup Window example.
Take a look at jfxmessagebox (http://en.sourceforge.jp/projects/jfxmessagebox/) if you are looking for very simple dialog popups.
Have you looked into ControlsFx Popover control.
import org.controlsfx.control.PopOver;
import org.controlsfx.control.PopOver.ArrowLocation;
private PopOver item;
final Scene scene = addItemButton.getScene();
final Point2D windowCoord = new Point2D(scene.getWindow()
.getX(), scene.getWindow().getY());
final Point2D sceneCoord = new Point2D(scene.getX(), scene.
getY());
final Point2D nodeCoord = addItemButton.localToScene(0.0,
0.0);
final double clickX = Math.round(windowCoord.getX()
+ sceneCoord.getY() + nodeCoord.getX());
final double clickY = Math.round(windowCoord.getY()
+ sceneCoord.getY() + nodeCoord.getY());
item.setContentNode(addItemScreen);
item.setArrowLocation(ArrowLocation.BOTTOM_LEFT);
item.setCornerRadius(4);
item.setDetachedTitle("Add New Item");
item.show(addItemButton.getParent(), clickX, clickY);
This is only an example but a PopOver sounds like it could accomplish what you want. Check out the documentation for more info.
Important note: ControlsFX will only work on JavaFX 8.0 b118 or later.

Categories