When a parent component has transparent mouse enabled all child controls are no longer able to receive mouse events. Is it possible exclude a child from this rule.
public class TransparentMouseTest extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
#Override
public void start(Stage stage)
{
Pane root = new StackPane();
root.getChildren().add(new TextField());
Pane p = new StackPane();
p.setMouseTransparent(true);
p.setStyle("-fx-background-color:#F001;");
p.getChildren().add(new Button("Button should be able \nto receive mouse events."));
root.getChildren().add(p);
Scene scene = new Scene(root, 400, 300);
stage.setScene(scene);
stage.show();
}
}
Related
I'am new to JavaFX, so my coding is not the best. My programme has one Stage with 2 different Scenes. For a better overview I have created a new class for the second Scene. From this second Scene I want to go back to first one, using a button. The method: primaryStage.setScene(scene) is not working and I dont know why. Can someone please help me? :)
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
GridPane primarygridpane = new GridPane();
Scene scene = new Scene(primarygridpane,400,400);
...
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
public class Harnwegsinfektion {
public static void create (Stage primaryStage){
GridPane secondarygridpane = new GridPane();
Scene scene2 = new Scene(secondarygridpane,400,400);
buttonBack.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(scene);
}
});
primaryStage.setScene(scene2);
primaryStage.show();
}
}
The problem is that your scene variable is named scene2 and you are calling setScene() with scene.
I don't really know when and where create() is called, but if you want to go back to the first scene from the button, you have to save the original one before switching :
public static void create (Stage primaryStage){
GridPane secondarygridpane = new GridPane();
Scene scene2 = new Scene(secondarygridpane,400,400);
Scene originalScene=primaryStage.getScene(); //save the previous scene
buttonBack.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(originalScene); //go back to the previous scene
}
});
primaryStage.setScene(scene2);
primaryStage.show();
}
I need a help with JavaFX. I have a program that draws lines with the mouse in the scene. When I press clear button, whole scene needs to be cleared. But only last drawn line is being cleared with this program.
When clear button is pushed, all drawn lines should be cleared. Now, only the last drawn line is being cleared.
public class Test extends Application {
private Line currentLine;
private Group root;
private ColorPicker colorPicker;
private Button clearButton;
private HBox buttons;
private Scene scene;
public void start(Stage primaryStage) {
root = new Group();
colorPicker = new ColorPicker(Color.WHITE);
clearButton = new Button("Clear");
clearButton.setOnAction(this::processActionButton);
buttons = new HBox(colorPicker, clearButton);
buttons.setSpacing(15);
root.getChildren().addAll(buttons);
scene = new Scene(root, 500, 300, Color.BLACK);
scene.setOnMousePressed(this::processMousePress);
scene.setOnMouseDragged(this::processMouseDrag);
primaryStage.setTitle("Color Lines");
primaryStage.setScene(scene);
primaryStage.show();
}
public void processMousePress(MouseEvent event) {
currentLine = new Line(event.getX(), event.getY(), event.getX(),
event.getY());
currentLine.setStroke(colorPicker.getValue());
currentLine.setStrokeWidth(3);
root.getChildren().add(currentLine);
}
public void processMouseDrag(MouseEvent event) {
currentLine.setEndX(event.getX());
currentLine.setEndY(event.getY());
}
public void processActionButton(ActionEvent event) {
root.getChildren().removeAll(currentLine);
}
public static void main(String[] args) {
launch(args);
}
}
You can have a special group for lines only:
Group groupLines = new Group();
...
root.getChildren().add(groupLines);
Add new lines into this group:
public void processMousePress(MouseEvent event) {
...
groupLines.getChildren().add(currentLine);
}
And clean only this group:
groupLines.getChildren().clear();
Please refer to the JavaFX SSCCE below. The print statement appears when closing the primary stage from the window's default titlebar "X" button. The print statement does NOT appear when clicking the "Close" button. Why isn't my onCloseHandler being called when I call close() on the stage? Is my expectation somehow unreasonable or is this (yet another) bug in JavaFX? Thanks!
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button closeButton = new Button("Close");
closeButton.setOnAction(e -> {
primaryStage.close();
});
primaryStage.setOnCloseRequest(e -> {
System.out.println("onCloseRequest handler called!");
});
StackPane rootPane = new StackPane();
rootPane.getChildren().add(closeButton);
primaryStage.setScene(new Scene(rootPane, 300, 250));
primaryStage.show();
}
}
As described by the Javadoc, this is only fired on external requests:
Called when there is an external request to close this Window.
Maybe setOnHidden would work for you, it is called in both cases.
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Button closeButton = new Button("Close");
closeButton.setOnAction(e -> {
primaryStage.close();
});
primaryStage.setOnHidden(e -> {
System.out.println("stage hidden");
});
StackPane rootPane = new StackPane();
rootPane.getChildren().add(closeButton);
primaryStage.setScene(new Scene(rootPane, 300, 250));
primaryStage.show();
}
}
So, I'm trying to switch scenes in JavaFX but I can't seem to get it to work when I hard coded it I was able to get it working by using lambda expressions.
public class Main extends Application {
Stage window;
Scene scene1;
Scene scene2;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
Label label = new Label("Welcome to the first scene");
Button bttn1 = new Button("Go to second scene");
bttn1.setOnAction(e -> window.setScene(scene2));
//Scene 1
VBox layout1 = new VBox(20);
layout1.getChildren().addAll(label, bttn1);
scene1 = new Scene(layout1, 400, 400);
//Scene 2
Button bttn2 = new Button("Go to first scene");
bttn2.setOnAction(e -> window.setScene(scene1));
StackPane layout2 = new StackPane();
layout2.getChildren().add(bttn2);
scene2 = new Scene(layout2, 400, 500);
window.setScene(scene1);
window.setTitle("Test");
window.show();
}
However the project involves a few different GUIs and I would prefer to design the GUI's in FXML Scene Builder than to hardcode them the FX way. However when I have tried to do the FXML way it hasn't worked an error is always appearing when I press the button.
Error message
This is the document controller code.
public class FXMLDocumentController implements Initializable {
#FXML
private Button button1;
#FXML
private Button button2;
#FXML
private void handleButtonAction(ActionEvent event) throws IOException {
Stage stage;
Parent root;
if(event.getSource() == button1){
stage=(Stage)button1.getScene().getWindow();
root = FXMLLoader.load(getClass().getResource("FXML2.fxml"));
}
else{
stage=(Stage)button2.getScene().getWindow();
root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
The error you posted says the code is trying to load a button as an anchor pane. Check too see if you have an anchorpane with the fx:I'd of button1.
Here is my code, I'm trying to load a splash screen image with transparent background before my main stage starts. They come almost at the same time, but the big problem is I get a grey rectangle before anything else: .
Here is the code:
public class Menu extends Application {
private Pane splashLayout;
private Stage mainStage;
private ImageView splash;
// Creating a static root to pass to ScreenControl
private static BorderPane root = new BorderPane();
public void start(Stage splashStage) throws IOException {
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.splash = new ImageView(new Image(getClass().getResource("/splash.png").toString()));
splashStage.initStyle(StageStyle.TRANSPARENT);
showSplash(splashStage, screenSize);
// Constructing our scene using the static root
root.setCenter(new ScrollPane);
Scene scene = new Scene(root, screenSize.getWidth(), screenSize.getHeight());
showMainStage(scene);
if (splashStage.isShowing()) {
mainStage.setIconified(false);
splashStage.toFront();
FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.5), splashLayout);
fadeSplash.setDelay(Duration.seconds(3.5));
fadeSplash.setFromValue(1.0);
fadeSplash.setToValue(0.0);
fadeSplash.setOnFinished(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
splashStage.hide();
}
});
fadeSplash.play();
}
}
private void showMainStage(Scene scene) {
mainStage = new Stage(StageStyle.DECORATED);
mainStage.setTitle("book-depot");
mainStage.getIcons().add(new Image(getClass().getResourceAsStream("/icon.png")));
mainStage.setScene(scene);
mainStage.show();
}
private void showSplash(Stage splashStage, Dimension screenSize) {
splashLayout = new StackPane();
splashLayout.setStyle("-fx-background-color: transparent;");
splashLayout.getChildren().add(splash);
Scene splashScene = new Scene(splashLayout, 690, 590);
splashScene.setFill(Color.TRANSPARENT);
splashStage.setScene(splashScene);
splashStage.show();
}
public void mainGui(String[] args) {
launch(args);
}
}
Am I doing something wrong or I really can't get a transparent background?
This is what it looks like when also the other stage loads up, but I'd like it to work like that even before the main stage loads, or at least I'd want to remove the grey rectangle you can see in the other screenshot
The grey background is your "mainStage" since you are showing splash and main stages at the same time. At the beginning while showing the splash stage you can just init (not show) the main stage and show it later when the animation finishes:
public class ModifiedMenu extends Application
{
private Pane splashLayout;
private Stage mainStage;
private ImageView splash;
// Creating a static root to pass to ScreenControl
private static BorderPane root = new BorderPane();
public void start(Stage splashStage) throws IOException {
final Dimension2D screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.splash = new ImageView(new Image(getClass().getResource("/splash.png").toString()));
splashStage.initStyle(StageStyle.TRANSPARENT);
showSplash(splashStage, screenSize);
// Constructing our scene using the static root
root.setCenter(new ScrollPane());
Scene scene = new Scene(root, screenSize.getWidth(), screenSize.getHeight());
initMainStage(scene);
if (splashStage.isShowing()) {
splashStage.toFront();
FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.5), splashLayout);
fadeSplash.setDelay(Duration.seconds(3.5));
fadeSplash.setFromValue(1.0);
fadeSplash.setToValue(0.0);
fadeSplash.setOnFinished(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
splashStage.hide();
mainStage.show();
}
});
fadeSplash.play();
}
}
private void initMainStage(Scene scene) {
mainStage = new Stage(StageStyle.DECORATED);
mainStage.setTitle("book-depot");
mainStage.getIcons().add(new Image(getClass().getResourceAsStream("/icon.png")));
mainStage.setScene(scene);
}
private void showSplash(Stage splashStage, Dimension2D screenSize) {
splashLayout = new StackPane();
splashLayout.setStyle("-fx-background-color: transparent;");
splashLayout.getChildren().add(splash);
Scene splashScene = new Scene(splashLayout, 690, 590);
splashScene.setFill(Color.TRANSPARENT);
splashStage.setScene(splashScene);
splashStage.show();
}
public void mainGui(String[] args) {
launch(args);
}
}