0

I am teaching my self java(fx) in order to create some applications for my small business.

However I am stuck with the problem below. The actual program is much larger and complicated so I created a new, smaller and easier on the eye class to get some help for something that has me stumped for more than a week

The code below creates 3 instances of a label with different ids (in case it can help). Is there any way to change the text of (let's say) Label 2 to something else by pressing the button?

This is really my last hope to find a solution.

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Test extends Application {

@Override
public void start(Stage primaryStage) {

    Button btn = new Button();
    btn.setText("Change Label 2 text to something else");
    btn.setLayoutX(220);
    btn.setLayoutY(250);

    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            //????????????????????????????????????
        }
    });

    Pane root = new Pane();
    root.getChildren().add(btn);

    for(int i=1; i<=3; i++){
        Label label = new Label("Label "+i);
        label.setId(String.valueOf(i));
        label.setLayoutX(i*60);
        label.setLayoutY(i*60);
        root.getChildren().add(label);
    }

    Scene scene = new Scene(root, 600, 500);

    primaryStage.setTitle("Instances");
    primaryStage.setScene(scene);
    primaryStage.show();
}

public static void main(String[] args) {
    launch(args);
}

}

RAG7
  • 13
  • 7

3 Answers3

2

Create a reference to the component at class level. For example you could create an array of label components

private Label[] labels;

and initialize

labels = new Label[3];
for (int i = 0; i < labels.length; i++) {
    labels[i] = new Label("Label " + (i + 1));
    ...
}

and the handler then simply contains

labels[1].setText("New Text");
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • Thank you for the input and help. I will try to see what I can do by using arrays (or arraylists?) and will check if I can create arrays for groups (since the larger program uses groups with shapes and labels that you can move around using the mouse. – RAG7 Aug 16 '14 at 22:17
2

You are creating one same instance of Label three times. Instead, create array of Labels Something like this:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Test extends Application {

    @Override
    public void start(Stage primaryStage) {
        Label[] labels = new Label[3];

        Button btn = new Button();
        btn.setText("Change Label 2 text to something else");
        btn.setLayoutX(220);
        btn.setLayoutY(250);

        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                labels[1].setText("Text changed");
            }
        });

        Pane root = new Pane();
        root.getChildren().add(btn);

        for (int i = 0; i < 3; i++) {

            labels[i] = new Label("Label " + i);
            labels[i].setId(String.valueOf(i));
            labels[i].setLayoutX(i * 60);
            labels[i].setLayoutY(i * 60);
            root.getChildren().add(labels[i]);
        }

        Scene scene = new Scene(root, 600, 500);

        primaryStage.setTitle("Instances");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Other side notes: Don't position your components like this:

label.setLayoutX(i*60);
label.setLayoutY(i*60);

Use proper pane for layout.

Branislav Lazic
  • 14,388
  • 8
  • 60
  • 85
  • Thank you for the time you took to revise the code and give me advice. I think you pointed me to the right direction. Unfortunately as a new member I cannot upvote yet. – RAG7 Aug 16 '14 at 22:21
  • @RAG7 I'll upvote on your behalf – Santhosh Nov 06 '21 at 05:56
1

The answers of Reimeus and Branislav (store explicit references to the labels you want to manipulate in Java), are the preferred solution.

This answer is just offered as alternate counterpoint info.

Using CSS ids and lookups

You can use css ids and lookup functions to get a reference to a node.

Example

For example, you are creating your labels like this:

for(int i=1; i<=3; i++){
    Label label = new Label("Label "+i);
    label.setId(String.valueOf(i));
    . . .
    root.getChildren().add(label);
}

You can turn your second label into a mutant ninja turtle like this:

btn.setOnAction(event -> {
    Label label = (Label) btn.getScene().lookup("#2");
    label.setText("Turtle Power");
    label.setGraphic(
        new ImageView(
            new Image(
                "http://www.cavemag.com/wp-content/uploads/2011/12/teenage-mutant-ninja-turle-toys.jpg",
                64, 0, true, true 
           )
        )
    );
});

After pressing the button to manipulate the label:

turtle power

Advantages and Disadvantages

Advantages are:

  1. You don't need explicit Java references in your application to scene nodes you want to manipulate, which can be useful if you have a loosely coupled logic design in your code.
  2. Lookups can use powerful CSS selectors to return one or multiple nodes.

Disadvantages are:

  1. You lose type safety.
  2. You don't have compiler checks and IDE assistance to ensure that the lookup ID actually matches a CSS ID.
  3. Lookups are time sensitive and must be performed after a CSS layout pass has executed.

Usually the disadvantages will outweigh the advantages of using lookups.

The lookup approach works well with dynamic languages like JavaScript executing over complex unstructured html documents, (where things like jQuery are used). But isn't as desirable with JavaFX because Java is statically typed, which benefits type resolution and also because the scene graph setups are generally more structured than your typical HTML app.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • Till yesterday I didn't know how to handle it. Today I have 2 valid ways to proceed. Thank you – RAG7 Aug 17 '14 at 15:56