I am writing a JavaFX app. I use a StackPane with two children. The topmost has a transparent background. I want the another pane to capture mouse events.
How can I do this?
I tried to make the top child mouse-transparent, but that makes its children transparent to mouse events.
// sample/Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
public static final String appName = "Application name";
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.initStyle(StageStyle.UNDECORATED);
root.getStylesheets().add("sample/sample.css");
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 400, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
// sample/Controller.java
package sample;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
public class Controller {
#FXML
private AnchorPane topbar;
#FXML
private Label lbAppName;
#FXML
private Button btnCloseApp;
#FXML
private Button button1;
#FXML
private Button button2;
#FXML
private void initialize() {
lbAppName.setText(Main.appName);
// this disables btnCloseApp
topbar.setMouseTransparent(true);
btnCloseApp.setOnAction(event -> {
Platform.exit();
});
button1.setOnAction(event -> {
System.out.println("Clicked button1");
});
button2.setOnAction(event -> {
System.out.println("Clicked button2");
});
}
}
<!-- sample/sample.fxml -->
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<StackPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml">
<HBox>
<VBox fx:id="sidebar">
<Button fx:id="button1" text="Button 1"/>
<Button fx:id="button2" text="Button 2"/>
</VBox>
<GridPane fx:id="form">
<Label text="Field 1" GridPane.rowIndex="0" GridPane.columnIndex="0"/>
<TextField fx:id="field1" GridPane.rowIndex="0" GridPane.columnIndex="1"/>
<Label text="Field 2" GridPane.rowIndex="1" GridPane.columnIndex="0"/>
<TextField fx:id="field2" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
</GridPane>
</HBox>
<AnchorPane fx:id="topbar">
<Label fx:id="lbAppName" AnchorPane.topAnchor="8" AnchorPane.leftAnchor="8"/>
<Button fx:id="btnCloseApp" text="Close" AnchorPane.topAnchor="8" AnchorPane.rightAnchor="8"/>
</AnchorPane>
</StackPane>
/* sample/sample.css*/
.root {
-fx-border-color: #a8c;
}
#sidebar {
-fx-padding: 40 8 8 8;
-fx-spacing: 8;
-fx-background-color: #caf;
-fx-pref-width: 150;
}
#form {
-fx-padding: 40 8 8 8;
-fx-hgap: 8;
-fx-vgap: 4;
}
Related
I try to place buttons and text evenly in the window. I use FXML for javafx project:
<VBox>
<HBox>
<TextField promptText="Text1" prefWidth="60" alignment="CENTER_LEFT">
<padding>
<Insets left="10" right="30"/>
</padding>
</TextField>
<Label text="Some text"/>
<TextField promptText="Text2" prefWidth="60" alignment="CENTER_RIGHT">
<padding>
<Insets left="30" right="10"/>
</padding>
</TextField>
</HBox>
</VBox>
I use padding, 'alignment' properties but nothing help, elements are offset:
How to correctly to place elements in window?
You need to:
Make sure the VBox is filling the width of the window
(your code snippet doesn’t indicate if it is in another container).
Make sure the HBox fills the width of the VBox
add fillWidth=“true” to the VBox element.
Let each component grow in the HBox
add HBox.hgrow = “ALWAYS” and maxWidth = “Infinity” to the text fields and label.
remove the padding and
insets, and existing preferred widths.
Here is an example:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.*?>
<VBox fillWidth="true" xmlns:fx="http://javafx.com/fxml">
<HBox>
<TextField promptText="Text1" maxWidth="Infinity" HBox.hgrow="ALWAYS"/>
<Label alignment="CENTER" text="Some text" maxWidth="Infinity" HBox.hgrow="ALWAYS"/>
<TextField promptText="Text2" maxWidth="Infinity" HBox.hgrow="ALWAYS"/>
</HBox>
</VBox>
and the application file:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 600, 400);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
I have a stack pane that when the mouse enters, I create a pane, stick some text in it, and display it near the mouse.
StatisticsController.java
stackPane.setOnMouseEntered(event -> {
Pane pane = new Pane();
Text text = new Text("Example Text");
//Add the text to the pane and set it near the mouse
pane.getChildren().add(text);
pane.setLayoutY(event.getSceneY() - 50);
pane.setLayoutX(event.getSceneX() - 100);
//add the style class to give it a blueBG background
pane.getStyleClass().add("blueBG");
// add it too our root
getRoot().getChildren().add(pane);
});
As you can see below when the Pane and text appear when I roll over the stackPane (the black circle and question mark in the image).
However it doesn't have the blue background I'm looking for.
What I find strange is if instead of adding it to the root and I add it to an existing Vbox, it styles correctly (Here I roll over the same stackPane):
So:
//Styles Correctly
getInfoBox().getChildren().add(pane);
// Adds but does not style
getRoot().getChildren().add(pane);
Some things that may be worth noting:
1)getInfoBox() is a static getter. I have multiple controllers which extend a MasterController which has static instance variables to things all controllers would want to be able to access - like the infoBox, to display information.
2)The root is a BorderPane made in the Main class:
Main.java
//Create the root
BorderPane root = new BorderPane();
// I've cut it out to save space but this repeats 4 times to set
//an .fxml file for the top, left, right and bottom of the borderPane ///
FXMLLoader headerLoader = new FXMLLoader(getClass().getResource("/view/header.fxml"));
Parent headerRoot = headerLoader.load();
root.setTop(headerRoot);
//------------------------------------------//
//Set the static reference in the MasterController
MasterController.setRoot(root);
Scene scene = new Scene(root,1366,768);
primaryStage.setScene(scene);
primaryStage.show();
3) The css files are all declared in the .fxml files using Scene Builder. The top, bottom, left, right .fxml files all have the same css (main.css). So does the statistic.fxml which is loaded on button click into the center (you can see in the image)
Suggestion: Could it be because the CSS is not defined for the Scene or BorderPane itself, it only applies to nodes added into the borderPane sections? If so how would I go about letting the enter Scene/Stage use the same css and would that negate adding in the css to each .fxml?
Edit:
When adding this code to the main to apply the CSS to the scene:
Scene scene = new Scene(root,1366,768);
scene.getStylesheets().add(getClass().getResource("/css/main.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
I get this:
So the CSS for the text is now working, but not for the Pane? I have no idea why this might happen.
// ---- REPRODUCTION -- //
Main.java
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane bp = new BorderPane();
MasterController.setRoot(bp);
Parent left = FXMLLoader.load(getClass().getResource("left.fxml"));
Parent right = FXMLLoader.load(getClass().getResource("right.fxml"));
bp.setLeft(left);
bp.setRight(right);
Scene scene = new Scene(bp, 600, 400);
scene.getStylesheets().add(getClass().getResource("main.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MasterController.java
package sample;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
public class MasterController {
private static VBox rightBox;
private static BorderPane root;
public static VBox getRightBox() {
return rightBox;
}
public static void setRightBox(VBox rightBox) {
MasterController.rightBox = rightBox;
}
public static BorderPane getRoot() {
return root;
}
public static void setRoot(BorderPane root) {
MasterController.root = root;
}
}
LeftController.java
package sample;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import java.io.IOException;
public class LeftController extends MasterController {
#FXML
public void loadCenter(ActionEvent event) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("center.fxml"));
Parent center = loader.load();
getRoot().setCenter(center);
} catch (IOException e){
e.printStackTrace();
}
}
}
CenterController.java
package sample;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
public class CenterController extends MasterController {
#FXML
private VBox center;
public void initialize() {
Platform.runLater(this::build);
}
public void build() {
center.getChildren().add(new Text("loaded"));
StackPane stackPane = new StackPane();
Text text = new Text("ROLL OVER");
stackPane.getChildren().add(text);
center.getChildren().add(stackPane);
stackPane.setOnMouseEntered(event -> {
getRightBox().getChildren().clear();
Pane pane1 = new Pane();
Text exampleText1 = new Text("Example Text");
pane1.getStyleClass().add("blueBG");
Pane pane2 = new Pane();
Text exampleText2 = new Text("Example Text");
pane2.getStyleClass().add("blueBG");
pane1.getChildren().add(exampleText1);
pane2.getChildren().add(exampleText2);
pane1.setLayoutY(event.getSceneY() + 40);
pane1.setLayoutX(event.getSceneX() - 40);
getRoot().getChildren().add(pane1);
getRightBox().getChildren().add(pane2);
});
}
}
RightController.java
package sample;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.layout.VBox;
public class RightController extends MasterController {
#FXML
private VBox rightBox;
public void initialize() {
setRightBox(rightBox);
}
}
left.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.LeftController">
<children>
<Button mnemonicParsing="false" onAction="#loadCenter" prefHeight="38.0" prefWidth="200.0" text="Click me to load center" />
</children>
</VBox>
center.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.layout.*?>
<VBox fx:id="center" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="200.0" stylesheets="#main.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.CenterController">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Center" />
</children>
</VBox>
right.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.layout.*?>
<VBox fx:id="rightBox" alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="200.0" stylesheets="#main.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.RightController">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Right Box" />
</children>
</VBox>
main.css
.blueBG {
-fx-background-color: aqua;
}
You should get the following result. You can see the pane is being styled correctly when added to the right, but not when added too the root.
BorderPane only applies layout to the center, left, right, top and bottom children. It's however the parent of a layout (or the scene in case of a root) that sets the size of a Region during a layout pass (or not, like in this case).
The result is that the style is applied to the Pane, but the size of the Pane remains 0. You can verify this by adding
pane1.resize(100, 100);
to the event handler to set the size of the pane.
You need to use a different kind of layout as parent for pane1's size to become non-empty or resize it yourself.
I have created a new JavaFx project.
In the project I have a Main class, a Controller class and a design file.
When I click on "New products" I want to load a new fxml file named new_product.fxml.
However I get a error when I click the "New product" button:
Caused by: java.lang.NullPointerException
at sample.Main.changeScene(Main.java:33)
at sample.Controller.buttonNewProductOnMouseClicked(Controller.java:21)
In Main.java line 33 is the primaryStage. Looks like my controller can't access it?
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception{
this.primaryStage = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
Scene primaryScene = new Scene(root, 300, 275);
primaryStage.setScene(primaryScene);
primaryStage.show();
}
public void changeScene(String fxml){
Parent pane = null;
try {
pane = FXMLLoader.load(getClass().getResource(fxml));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene( pane );
primaryStage.setScene(scene);
}
public static void main(String[] args) {
launch(args);
}
}
My design file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<BorderPane xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<top>
<HBox prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<Button fx:id="buttonProducts" mnemonicParsing="false" onMouseClicked="#buttonProductsOnMouseClicked" text="Products" />
<Button fx:id="buttonNewProduct" mnemonicParsing="false" onMouseClicked="#buttonNewProductOnMouseClicked" text="New products">
<HBox.margin>
<Insets left="5.0" />
</HBox.margin></Button>
</children>
</HBox>
</top>
<center>
<Label text="Label" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
The Controller class for the design file
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
public class Controller {
#FXML
private Button buttonProducts;
#FXML
private Button buttonNewProduct;
public void buttonProductsOnMouseClicked(javafx.scene.input.MouseEvent mouseEvent) {
buttonProducts.setText("You have clicked on me!");
}
public void buttonNewProductOnMouseClicked(javafx.scene.input.MouseEvent mouseEvent) {
buttonNewProduct.setText("You have clicked on me!");
Main mainclass = new Main();
mainclass.changeScene("new_product/new_product.fxml");
}
}
Here i want, if i wrote something on textarea and then click on button then the label will change as what i typed. But i can't handle the code properly.
Here is my source code---
ClickDemo.java-
package Application;
import java.io.FileInputStream;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class ClickDemo extends Application{
#Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader();
// Path to the FXML File
String fxmlDocPath = "src/View/sample1.fxml";
FileInputStream fxmlStream = new FileInputStream(fxmlDocPath);
// Create the Pane and all Details
AnchorPane root = (AnchorPane) loader.load(fxmlStream);
// Create the Scene
Scene scene = new Scene(root);
// Set the Scene to the Stage
stage.setScene(scene);
// Set the Title to the Stage
stage.setTitle("A SceneBuilder Example");
// Display the Stage
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Sample1Controller.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Controllers;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseEvent;
/**
* FXML Controller class
*
* #author Dell
*/
public class Sample1Controller {
/**
* Initializes the controller class.
*/
#FXML
private Button btn;
#FXML
private Label label;
#FXML
private TextArea textarea;
#FXML
void btn1handle(ActionEvent event) {
// label.setText("Hello world");
textarea.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
//System.out.println(newValue);
label.setText(newValue);
}
});
}
#FXML
void textareaHandle(MouseEvent event) {
}
}
Sample1.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="Controllers.Sample1Controller">
<children>
<Button fx:id="btn" layoutX="274.0" layoutY="230.0" mnemonicParsing="false" onAction="#btn1handle" text="Button" />
<Label fx:id="label" layoutX="210.0" layoutY="58.0" prefHeight="42.0" prefWidth="233.0" text="This is Text 1">
<font>
<Font size="31.0" />
</font>
</Label>
<TextArea fx:id="textarea" layoutX="101.0" layoutY="121.0" onDragDetected="#textareaHandle" prefHeight="79.0" prefWidth="399.0" />
</children>
</AnchorPane>
The issue is that you have the wrong implementation of the method called btn1handle. You are adding the new listener to the textarea instead of setting textarea's text into the label. The implementation of the method btn1handle could be very simple:
#FXML
void btn1handle(ActionEvent event) {
label.setText(textarea.getText());
}
I've asked this question before but I couldn't offer a preferably a Minimal, Complete, and Verifiable example. So I made another sample which is correctly working and completely minimal. By the way, I want to change the color of a menu box which I click one of those, and it would be remain persistent whenever I click another item such as a button. Here's a sample below and please help me..again..
FXMLDocumentController.java
package javafxapplication1;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
/**
*
* #author James
*/
public class FXMLDocumentController implements Initializable {
#FXML
private VBox menuVBox1 = new VBox();
#FXML
private VBox menuVBox2 = new VBox();
#FXML
private VBox menuVBox3 = new VBox();
#FXML
private VBox parentMenuVBox = new VBox(menuVBox1, menuVBox2, menuVBox3);
private final Background focusBackground = new Background(new BackgroundFill(Color.web("#000000"), CornerRadii.EMPTY, Insets.EMPTY));
private final Background unfocusBackground = new Background(new BackgroundFill(Color.web("#F4F4F4"), CornerRadii.EMPTY, Insets.EMPTY));
private void setMenuBoxColor (VBox menu) {
VBox menuVBox = menu;
menuVBox.requestFocus();
for (Node child : parentMenuVBox.getChildren()) {
VBox vb = (VBox) child;
vb.backgroundProperty().bind(Bindings
.when(vb.focusedProperty())
.then(focusBackground)
.otherwise(unfocusBackground)
);
}
}
#FXML
private void handleSelectMenus(MouseEvent event) {
//Change the color of clicked VBox
setMenuBoxColor((VBox)event.getSource());
System.out.println("Menu clicked");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="132.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication1.FXMLDocumentController">
<left>
<VBox fx:id="parentMenuVBox" prefHeight="200.0" prefWidth="100.0" spacing="10.0" BorderPane.alignment="CENTER">
<children>
<VBox fx:id="menuVBox1" onMouseClicked="#handleSelectMenus" prefHeight="200.0" prefWidth="100.0" style="-fx-border-color: #000000;">
<children>
<Label text="MENU1" />
</children>
</VBox>
<VBox fx:id="menuVBox2" layoutX="10.0" layoutY="10.0" onMouseClicked="#handleSelectMenus" prefHeight="200.0" prefWidth="100.0" style="-fx-border-color: #000000;">
<children>
<Label text="MENU2" />
</children>
</VBox>
<VBox fx:id="menuVBox3" layoutX="10.0" layoutY="160.0" onMouseClicked="#handleSelectMenus" prefHeight="200.0" prefWidth="100.0" style="-fx-border-color: #000000;">
<children>
<Label text="MENU3" />
</children>
</VBox>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
</left>
<bottom>
<HBox prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
<Button mnemonicParsing="false" text="Next" />
</children>
</HBox>
</bottom>
</BorderPane>
javaFXApplication1.java
package javafxapplication1;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author James
*/
public class JavaFXApplication1 extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
First set the unfocusBackground for all child vboxes, and then set focusBackground for only selected one.
public class FXMLDocumentController implements Initializable
{
#FXML
private VBox parentMenuVBox;
private final Background focusBackground = new Background( new BackgroundFill( Color.web( "#000000" ), CornerRadii.EMPTY, Insets.EMPTY ) );
private final Background unfocusBackground = new Background( new BackgroundFill( Color.web( "#F4F4F4" ), CornerRadii.EMPTY, Insets.EMPTY ) );
#FXML
private void handleSelectMenus( MouseEvent event )
{
// Set unfocusBackground for all child vboxes
for ( Node child : parentMenuVBox.getChildren() )
{
VBox vb = ( VBox ) child;
vb.setBackground( unfocusBackground );
}
// and set focusBackground for only selected one
VBox selected = ( VBox ) event.getSource();
selected.setBackground( focusBackground );
System.out.println( "Menu clicked" );
}
#Override
public void initialize( URL url, ResourceBundle rb )
{
}
}
I changed only the fxml controller from the code in the question.