Java FX - Removing a node if the user unchecks a checkbox - java

I am making a GUI using JavaFx, I want a name field to appear if the check box is checked and disappear if it is not checked.
Here is the code I wrote
test1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Boolean b = test1.isSelected();
log(b);
Label label1 = new Label("Name:");
TextField textField = new TextField();
HBox hb = new HBox();
if (test1.isSelected()) {
hb.getChildren().addAll(label1, textField);
hb.setSpacing(10);
grid.add(hb, 3, 3);
} else {
**hb.getChildren().removeAll(label1 , textField);** <---look at this!
}
}
});
I am removing the node if it is unchecked but it doesn't execute it accordingly. What am I doing wrong?
Incase it is required, here is how I execute my scene.
Scene scene = new Scene(grid, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();

Related

How can a class like BorderPane display the change when it is later being coded and not when initialised?

I was working on JavaFX, and I realised something which kept me thinking. So, there's a scene in my constructor which adds the variable root of the type BorderPane. In the main class, this class' constructor is called first, thereby initialising the BorderPane in the Scene. However, the BorderPane is being modified and edited in a method called build. I am confused how the BorderPane is still being able to display its updated version from the build() since in the constructor it has already been commanded to display.
Here's my code:
public class SnacksOrDrinks
{
private BorderPane root;
private Stage primaryStage;
private Scene scene;
private Cart crt;
public SnacksOrDrinks(Stage primaryStage, Cart crt)
{
// BorderPane is being initialised and is being put inside the scene:
BorderPane root1 = new BorderPane();
this.scene = new Scene(root1, 800, 475);
this.crt = crt;
ImageView imgview = new ImageView("./application/MountainPainting.jpg");
imgview.fitWidthProperty().bind(primaryStage.widthProperty());
imgview.fitHeightProperty().bind(primaryStage.heightProperty());
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
this.primaryStage = primaryStage;
this.root = root1;
root.setStyle("-fx-background-color: blue");
root.getChildren().add(imgview);
}
public void build(Dispenser dis)
{
// ItemsPaneProp extends GridPane and stores the common properties shared in other classes.
ItemsPaneProp pane = new ItemsPaneProp();
// Header Created:
CommHeaderProp header = new CommHeaderProp("Lopes Vending Machine");
// However, BorderPane is being modified here, and the constructor has already been called.
BorderPane.setAlignment(header, Pos.CENTER);
root.setTop(header);
// Create a Line:
Line line = new Line(100, 10, 300, 10);
line.setFill(Color.GOLDENROD);
line.setStrokeWidth(2);
line.setSmooth(true);
pane.add(line, 0, 0);
// Create all the Scene's Components and setup the Event Handlers
ImageView img = new ImageView("./application/softdrink.jpg");
img.setFitWidth(75);
img.setFitHeight(75);
Button btn1 = new Button("Select to get Drinks", img);
btn1.setStyle("-fx-background-color: white");
btn1.setFont(Font.font("Times New Roman", FontWeight.BOLD, FontPosture.REGULAR, 12));
btn1.setContentDisplay(ContentDisplay.TOP);
pane.add(btn1, 0, 1);
ImageView img1 = new ImageView("./application/potato-chips.png");
img1.setFitWidth(75);
img1.setFitHeight(75);
Button btn2 = new Button("Select to get Snacks", img1);
btn2.setStyle("-fx-background-color: white");
btn2.setFont(Font.font("Times New Roman", FontWeight.BOLD, FontPosture.REGULAR, 12));
btn2.setContentDisplay(ContentDisplay.TOP);`enter code here`
pane.add(btn2, 1, 1);
root.setCenter(pane); // The BorderPane is being modified here too, but the constructor isn't updating the scene. Then, how does it still work?
btn1.setOnMouseClicked(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
// Create, build, and show Scene 2
DrinksList scene = new DrinksList(primaryStage, crt);
scene.build(dis);
scene.show();
}
});
btn2.setOnMouseClicked(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent e)
{
// Create, build, and show Scene 2
SnacksList scene = new SnacksList(primaryStage, crt);
scene.build(dis);
scene.show();
}
});
}
public void show()
{// setting scene:
primaryStage.setScene(scene);
}
}
Take a look at https://docs.oracle.com/javase/8/javafx/scene-graph-tutorial/scenegraph.htm#JFXSG107
The JavaFX scene graph is a retained mode API, meaning that it maintains an internal model of all graphical objects in your application. At any given time, it knows what objects to display, what areas of the screen need repainting, and how to render it all in the most efficient manner.
Your borderPane - part of SceneGraph, so JavaFX knows, when you change anything in your borderPane, and automatically invoking redraw method for it.

How to change position of button JavaFX

As you can see I have two buttons right now (button and button2) The problem is that they are in the center of JavaFX window (in the same place). So I don't see one of them because 2nd is covering 1st. What is wrong? The main objective of this simple app is to have two buttons on main screen. And after clicking into one of buttons, I expect to open new window with some other content.
public class Run extends Application {
#Override
public void start(final Stage primaryStage) {
Button button = new Button();
button.setText("Navigation");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Label secondLabel = new Label("Select from list");
StackPane secondaryLayout = new StackPane();
secondaryLayout.getChildren().add(secondLabel);
Scene secondScene = new Scene(secondaryLayout, 500, 400);
// New window (Stage)
Stage newWindow = new Stage();
newWindow.setTitle("Adding products");
newWindow.setScene(secondScene);
// Specifies the modality for new window.
newWindow.initModality(Modality.WINDOW_MODAL);
// Specifies the owner Window (parent) for new window
newWindow.initOwner(primaryStage);
// Set position of second window, related to primary window.
newWindow.setX(primaryStage.getX() + 200);
newWindow.setY(primaryStage.getY() + 100);
newWindow.show();
}
});
Button button2 = new Button();
button2.setText("X");
button2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Label secondLabel = new Label("Select from list");
StackPane secondaryLayout = new StackPane();
secondaryLayout.getChildren().add(secondLabel);
Scene secondScene = new Scene(secondaryLayout, 500, 400);
// New window (Stage)
Stage newWindow = new Stage();
newWindow.setTitle("Adding products");
newWindow.setScene(secondScene);
// Specifies the modality for new window.
newWindow.initModality(Modality.WINDOW_MODAL);
// Specifies the owner Window (parent) for new window
newWindow.initOwner(primaryStage);
// Set position of second window, related to primary window.
newWindow.setX(primaryStage.getX() + 200);
newWindow.setY(primaryStage.getY() + 100);
newWindow.show();
}
});
StackPane root = new StackPane();
root.getChildren().add(button);
root.getChildren().add(button2);
Scene scene = new Scene(root, 650, 450);
primaryStage.setTitle("Shopping Buddy");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

JavaFX ScrollPane setVvalue() not working properly

I am testing the JavaFX ScrollPane class and realized that it is not working as I expect, I don't know why. I have the following code:
public class Client3 extends Application {
int indexMsg = 0;
Button send;
GridPane root;
ScrollPane msgPane;
GridPane msgPaneContent;
FlowPane writePane;
TextField writeMsg;
Scene scene;
#Override
public void start(Stage primaryStage) {
root = new GridPane();
root.setAlignment(Pos.CENTER);
root.setVgap(10);
root.setPadding(new Insets(10, 10, 10, 10));
msgPane = new ScrollPane();
msgPane.setPrefSize(280, 280);
msgPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
msgPaneContent = new GridPane();
msgPaneContent.setPrefWidth(270);
msgPaneContent.setVgap(10);
writePane = new FlowPane(10, 10);
writePane.setAlignment(Pos.CENTER);
writePane.setPrefWidth(280);
writeMsg = new TextField();
writeMsg.setPrefWidth(150);
writeMsg.setPromptText("Write your message");
writePane.getChildren().add(writeMsg);
GridPane.setConstraints(msgPane, 0, 0);
GridPane.setConstraints(writePane, 0, 1);
msgPane.setContent(msgPaneContent);
root.getChildren().addAll(msgPane, writePane);
writeMsg.setOnAction((ev) -> {
if (!writeMsg.getText().isEmpty()) {
TextArea msg = new TextArea(writeMsg.getText());
msg.setMaxWidth(135);
msg.setPrefRowCount(msg.getLength() / 21 + 1);
msg.setWrapText(true);
GridPane.setConstraints(msg, 0, indexMsg);
indexMsg++;
writeMsg.deleteText(0, writeMsg.getText().length());
msgPaneContent.getChildren().add(msg);
msgPane.setVvalue(1.0);
}
});
scene = new Scene(root, 300, 300);
primaryStage.setTitle("Chat App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Basically, I have a GridPane as the root with a ScrollPane and a GridPane as its children. The ScrollPane has a children GridPane. There is a TextField with an EventHandler which generates a TextArea inside the GridPane (the ScrollPane's children). Each TextArea object is created in the vertical direction, downwards. I want to set the scrollbar always at its maximum value (setVvalue(1.0)) each time a new TextArea is added. The thing is that it doesn't seem to work as it should because the vertical value is never set to the maximum after handling the event, but it seems to be set to the maximum value that it had before handling it (the bottom of the previous TextArea added).
Any solution for this? Thanks in advance.

How to call a method when a button is clicked in JavaFX?

I'm having a problem with creating a method and calling it when a button is clicked.
What I want to do is when a button is clicked the scene changes to a new one. I have already achieved this but I came across a problem when I need to create more of such actions.
Here is my code:
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
BorderPane borderPane = new BorderPane();
Button dugmeStart = new Button("Start");
dugmeStart.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
BorderPane borderPane2 = new BorderPane();
Label prvo_pritanje = new Label("Prvo pitanje: Kada je poceo Prvi svetski rat?");
prvo_pritanje.setStyle("-fx-font-weight: bold;");
Button dalje1 = new Button("Dalje");
//Navigacija
HBox navigacija_goranj = new HBox();
navigacija_goranj.getChildren().add(prvo_pritanje);
navigacija_goranj.setAlignment(Pos.CENTER);
navigacija_goranj.setPadding(new Insets(15,12, 15, 12));
HBox navigacija_donja = new HBox();
navigacija_donja.getChildren().add(dalje1);
navigacija_donja.setPadding(new Insets(15,12, 15, 12));
navigacija_donja.setAlignment(Pos.CENTER);
//Odgovori
HBox odgovori = new HBox();
ToggleGroup pitanja1 = new ToggleGroup();
RadioButton prvo_pitanje = new RadioButton("1914");
prvo_pitanje.setToggleGroup(pitanja1);
RadioButton drugo_pitanje = new RadioButton("1918");
drugo_pitanje.setToggleGroup(pitanja1);
RadioButton trece_pitanje = new RadioButton("1910");
trece_pitanje.setToggleGroup(pitanja1);
odgovori.getChildren().addAll(prvo_pitanje, drugo_pitanje, trece_pitanje);
odgovori.setSpacing(15);
odgovori.setAlignment(Pos.CENTER);
//Dodavanje u BorderPane
borderPane2.setBottom(navigacija_donja);
borderPane2.setTop(navigacija_goranj);
borderPane2.setCenter(odgovori);
Scene scena2 = new Scene(borderPane2, 300, 300);
primaryStage.setScene(scena2);
}
});
Label dobrodoslica = new Label("Pocetak kviza");
dobrodoslica.setStyle("-fx-font-weight: bold;");
//Definisanje Hbox-a sa dugmetom "Start"
HBox navigacija1 = new HBox();
navigacija1.setPadding(new Insets(15, 12, 15, 12));
navigacija1.getChildren().add(dugmeStart);
navigacija1.setAlignment(Pos.CENTER);
borderPane.setBottom(navigacija1);
borderPane.setCenter(dobrodoslica);
Scene scene = new Scene(borderPane,300,300);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("Domaci: Kviz");
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
You can see that when a button is clicked it creates a whole new scene and BorderPane, and populates it with content. I figured that it would be best to create a method with each scene and then call each method when a button is clicked. The problem is I cant figure out how to do this.
Any help is appreciated. Thanks in advance.

JavaFX: Node doesn't recognize when mouse is being dragged over it

I'm attempting to have a node recognize when a drag gesture is performed from one node to another.
I've tried to set a MouseDragEvent through node#setOnMouseDragOver but it doesn't ever get invoked.
This is my implementation:
nfaNode.setOnMouseDragOver(event1 -> {
System.out.println("over " + nfaNode.getText().getText());
});
I want it to know that Q_1 is being dragged over so that I am able to tell that Q_0 is being dragged to Q_1.
During a dragging gesture events are only delivered to the node where the gesture started by default. To change this, you need to call startFullDrag in the onDragDetected handler. Also if you move the node around, setting mousetransparent to true may be necessary for the mouse events not to be delivered just to the dragged node.
Example
#Override
public void start(Stage primaryStage) {
Rectangle rect1 = new Rectangle(100, 100, Color.BLUE);
Rectangle rect2 = new Rectangle(200, 200, 100, 100);
rect2.setFill(Color.RED);
rect1.setOnDragDetected(evt -> {
rect1.startFullDrag();
});
rect2.setOnMouseDragOver(evt -> {
System.out.println("over");
});
Pane root = new Pane(rect1, rect2);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
Comment out rect1.startFullDrag(); and you'll not see any output in the console.
Update
You can retrieve the gestureSource from a MouseDragEvent to get the node where you started the drag gesture and use getSource to retrieve the node where the event handler was added. Example:
#Override
public void start(Stage primaryStage) {
TextField text1 = new TextField();
TextField text2 = new TextField();
EventHandler<MouseEvent> dragDetected = evt -> ((Node) evt.getSource()).startFullDrag();
EventHandler<MouseDragEvent> dragOver = evt -> {
System.out.println("over " + ((TextField) evt.getGestureSource()).getText());
};
EventHandler<MouseDragEvent> dragReleased = evt -> {
TextField target = (TextField) evt.getSource();
TextField source = (TextField) evt.getGestureSource();
if (source != target) {
target.setText(source.getText());
source.clear();
}
};
for (TextField tf : Arrays.asList(text1, text2)) {
tf.setOnDragDetected(dragDetected);
tf.setOnMouseDragOver(dragOver);
tf.setOnMouseDragReleased(dragReleased);
}
VBox root = new VBox(text1, text2);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}

Categories