Why cursor resets to default after scene switch in JavaFX? - javafx

I know that I can set cursor type for the entire scene using Scene.setCursor method. But if I swap the scene with another one, cursor always resets to default - disregarding the cursor set on new scene. Here's the test case, tested in XFCE and XMonad:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HideCursor extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
root.setStyle("-fx-background-color: green");
Scene scene = new Scene(root, 600, 600);
scene.setCursor(Cursor.MOVE);
StackPane root2 = new StackPane();
root2.setStyle("-fx-background-color: blue");
Scene scene2 = new Scene(root2, 600, 600);
scene2.setCursor(Cursor.MOVE);
primaryStage.setScene(scene);
Button switchScene = new Button("switch");
root.getChildren().add(switchScene);
switchScene.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
primaryStage.setScene(scene2);
}
});
primaryStage.show();
}
}
Interestingly, in Windows 7 it works as expected. What am I doing wrong?

Related

How to set popup scene mouse transparent in javafx

How to do that in JavaFX?
The popup shows up when the mouse enters a node. When the mouse enters the showing popup, the popup obscures the mouse from the node. Then the node fire exit event. How to make the popup ignore the mouse events?
code
package sample;
import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
primaryStage.setScene(new Scene(root, 300, 275));
Label labelNode = new Label("Label Node");
labelNode.setPrefHeight(200);
labelNode.styleProperty().set("-fx-background-color: orange");
Popup popup = new Popup();
popup.getScene().getRoot().setMouseTransparent(true);
AnchorPane popContent =new AnchorPane();
popContent.styleProperty().set("-fx-background-color: red");
popContent.setPrefHeight(100);
popContent.getChildren().add(new Label("Popup content"));
popup.getContent().add(popContent);
labelNode.setOnMouseEntered(event->{
Point3D point3D = labelNode.localToScene(event.getX(), event.getY(), 0);
popup.show(primaryStage, point3D.getX()-5, point3D.getY()-5);
});
labelNode.setOnMouseExited(event->{
popup.hide();
});
root.getChildren().add(labelNode);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Please try moving the cursor in to "yellow" several times.
Solution:
Keep two boolean nodeExited and popupExited statuses. Hide popup when both are true.
package sample;
import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class Main extends Application {
boolean nodeExited = false;
boolean popupExited = false;
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
primaryStage.setScene(new Scene(root, 300, 275));
Label labelNode = new Label("Label Node");
labelNode.setPrefHeight(200);
labelNode.styleProperty().set("-fx-background-color: orange");
Popup popup = new Popup();
popup.getScene().getRoot().setMouseTransparent(true);
AnchorPane popContent = new AnchorPane();
popContent.styleProperty().set("-fx-background-color: red");
popContent.setPrefHeight(100);
popContent.getChildren().add(new Label("Popup content"));
popup.getContent().add(popContent);
popup.getScene().setOnMouseEntered(event -> {
popupExited = false;
});
popup.getScene().setOnMouseExited(event -> {
popupExited = true;
if (nodeExited)
popup.hide();
});
labelNode.setOnMouseEntered(event -> {
nodeExited = false;
Point3D point3D = labelNode.localToScene(event.getX(), event.getY(), 0);
popup.show(primaryStage, point3D.getX() - 5, point3D.getY() - 5);
});
labelNode.setOnMouseExited(event -> {
nodeExited = true;
if (popupExited)
popup.hide();
});
root.getChildren().add(labelNode);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFx add Window-Control-Buttons to Menubar (IntelliJ like)

Since IntelliJ version 2019.2 Jetbrains removed the titlebar from the IDE and put the minimize, maximize and close button of the window into the menubar. So far, I have not found out how to do so using javafx. Is there a way to instanciate a "WindowControlButtons"-Class, so I can easily add them to the menubar or do I have to add a buttongroup and style the buttons for each platform myself?
Example how it shall look like on Windows:
As suggested by #mr mcwolf You can try below solution.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class JavaFXApplication1 extends Application {
#Override
public void start(Stage primaryStage) {
Button closeButton = new Button();
closeButton.setText("X");
closeButton.setOnAction((ActionEvent event) -> {
javafx.application.Platform.exit();
});
Button hideButton = new Button();
hideButton.setText("-");
hideButton.setOnAction((ActionEvent event) -> {
primaryStage.setIconified(true);
});
Menu menu = new Menu("Menu");
MenuItem menuItem1 = new MenuItem("item 1");
MenuItem menuItem2 = new MenuItem("item 2");
menu.getItems().add(menuItem1);
menu.getItems().add(menuItem2);
MenuBar menuBar = new MenuBar();
menuBar.getMenus().add(menu);
HBox hBox = new HBox(menuBar, hideButton, closeButton);
HBox.setHgrow(menuBar, Priority.ALWAYS);
HBox.setHgrow(hideButton, Priority.NEVER);
HBox.setHgrow(closeButton, Priority.NEVER);
BorderPane root = new BorderPane();
root.setTop(hBox);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Output on Windows looks like this.

How to make mouse transparent stage in JavaFX 8?

I know how to make mouse transparent Node. But I want to make transparent window in color and mouse events, so that cursor could pass through this window and click on the app which below it.
Here is a minimal code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class MouseTransparentWindow extends Application {
#Override
public void start(Stage primaryStage) {
StackPane stackPane = new StackPane();
stackPane.setStyle("-fx-background-color: rgba(192,192,192,0.2);" +
"-fx-border-width: 1px;-fx-border-color: #1d1d1d");
stackPane.setMouseTransparent(true);
Scene scene = new Scene(stackPane, 400, 250, Color.TRANSPARENT);
scene.setFill(null);
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.TRANSPARENT);
primaryStage.show();
}
}
It seems it works on Windows, but I need that my code work on all Operating Systems.

JavaFX Resizing TextField with Window

In JavaFX, how do I create a textfield inside an hbox (BorderPane layout) resize in width/length as the user resizes the window?
You can set the HGROW for the textfield as Priority.ALWAYS.
This will enable the TextField to shrink/grow whenever the HBox changes its width.
MCVE :
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField();
HBox container = new HBox(textField);
container.setAlignment(Pos.CENTER);
container.setPadding(new Insets(10));
// Set Hgrow for TextField
HBox.setHgrow(textField, Priority.ALWAYS);
BorderPane pane = new BorderPane();
pane.setCenter(container);
Scene scene = new Scene(pane, 150, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Output :

JavaFX How to 'hide' TitledPane back after expanding

I have TitledPane, which i want to hide back (after expanding - un-expand it) after pressing a button. Is there any way to do it? I didn't find any way :( Thanks!
Just do
titledPane.setExpanded(false);
Complete example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TitledPaneExample extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Some content");
Button button = new Button("OK");
VBox content = new VBox(10, label, button);
TitledPane titledPane = new TitledPane("Titled Pane", content);
button.setOnAction(e -> titledPane.setExpanded(false));
VBox root = new VBox(titledPane);
Scene scene = new Scene(root, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Resources