简体   繁体   中英

How to change label text of .fxml file from another java class(means out side the controller)?

I want to change the label data dynamically through normal java class how can i do it.

below is my .fxml file :

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="1311.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafx_lsdu.LsduFrameController">
<children>
  <GridPane layoutX="14.0" layoutY="14.0" prefHeight="30.0" prefWidth="1286.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0">
    <columnConstraints>
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
    </columnConstraints>
    <rowConstraints>
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    </rowConstraints>
     <children>
        <Label id="PlazaName" fx:id="PlazaName" alignment="CENTER_RIGHT" prefHeight="33.0" prefWidth="257.0" text="PLAZA NAME :" />
        <Label id="PlazaNameData" fx:id="PlazaNameData" prefHeight="33.0" prefWidth="257.0" GridPane.columnIndex="1" />
        <Label id="LaneStatus" fx:id="LaneStatus" alignment="CENTER" prefHeight="32.0" prefWidth="257.0" text="LANE STATUS" GridPane.columnIndex="2" />
        <Label id="DateTime" fx:id="DateTime" alignment="CENTER_RIGHT" prefHeight="35.0" prefWidth="256.0" text="DATE &amp; TIME :" GridPane.columnIndex="3" />
     </children>
  </GridPane>
  </children>
</AnchorPane>

below is my controller class:

public class LsduFrameController implements Initializable {
@FXML
public static Label PlazaNameData;
/**
 * Initializes the controller class.
 * @param url
 * @param rb
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
   new Thread(new DisplayPlazaNameLocation()).start();
   // here i am calling DisplayPlazaNameLocation.java class and creating new thread
   }        
}

in below code I try to set the label text :-

public class DisplayPlazaNameLocation implements Runnable{
    static String plazaNameLocation;
    static Connection con;
    @Override
    public void run() {
        inRun();
    }
    public void inRun(){
        try {
            Class.forName(DB_DRIVER_CLASS);
            con= DriverManager.getConnection(DB_URL[0],DB_USERNAME,DB_PASSWORD);
            if(con != null){
                this.getPlazaNameLocation();
            }
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } 
           catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public  void getPlazaNameLocation(){
        try {
            PreparedStatement pst=con.prepareStatement("SELECT DISTINCT Plaza_Loc FROM lsdu_live");
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                plazaNameLocation = rs.getString("Plaza_Loc");
            }
            //jLabel199.setText(plazaNameLocation);
            String ar[] = plazaNameLocation.split(",");
            //jLabel199.setText("<html>"+ar[0]+"<br>"+ar[1]+"</html>");
            System.out.println("plazaNameLocation");
    //===================================================================
            LsduFrameController.PlazaNameData.setText(plazaNameLocation);//here i am trying to set the label text.
    //=======================================================================
            rs.close();
            pst.close();
            con.close();
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}

I am getting below exception:

Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at inf_main_code.DisplayPlazaNameLocation.getPlazaNameLocation(DisplayPlazaNameLocation.java:57)
at inf_main_code.DisplayPlazaNameLocation.inRun(DisplayPlazaNameLocation.java:36)
at inf_main_code.DisplayPlazaNameLocation.run(DisplayPlazaNameLocation.java:29)
at java.lang.Thread.run(Thread.java:745)

at this line

LsduFrameController.PlazaNameData.setText(plazaNameLocation);

How can I set label text from another normal java class?
In which way I need to modify my code ?

FXMLLoader doesn't inject to static fields.

Keeping it static (dirty fix)

You could make PlazaNameData a instance field and copy it to a static field in the initialize method

public class LsduFrameController implements Initializable {

    @FXML
    public Label PlazaNameData;

    public static Label PlazaNameDataStatic;

    /**
     * Initializes the controller class.
     * @param url
     * @param rb
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        PlazaNameDataStatic = PlazaNameData;
        ...
    }

    ...

Prefered approach

Using static is often bad design. In most cases there are better ways to pass the data.

In this case you could simply pass a reference to LsduFrameController to the DisplayPlazaNameLocation , eg in a constructor, and access the relevant instance members of the controller via that reference.

public class LsduFrameController implements Initializable {

    @FXML
    public Label PlazaNameData;

    ...

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        new Thread(new DisplayPlazaNameLocation(this)).start();
    }
    ...
}
public class DisplayPlazaNameLocation implements Runnable {
    private final LsduFrameController lsduController;

    public DisplayPlazaNameLocation(LsduFrameController lsduController) {
         this.lsduController = lsduController;
    }

    ...

        javafx.application.Platform.runLater( new Runnable() {
            @Override
            public void run() {
                lsduController.PlazaNameData.setText(plazaNameLocation);
            }
        });
    ...
}

Furthermore updates from different threads than the javafx application thread should be done using Platform.runLater .

You can't change something in FX Thread from other Thread . Change this:

    ...
    System.out.println("plazaNameLocation");
//===================================================================
    LsduFrameController.PlazaNameData.setText(plazaNameLocation);//here i am trying to set the label text.
//=======================================================================
    rs.close();
    ...

to:

Java 8:

    ...
    System.out.println("plazaNameLocation");
    javafx.application.Platform.runLater( () ->
        LsduFrameController.PlazaNameData.setText(plazaNameLocation);
    );
    rs.close();
    ...

Java 7:

    ...
    System.out.println("plazaNameLocation");
    javafx.application.Platform.runLater( new Runnable() {
        @Override
        public void run() {
            LsduFrameController.PlazaNameData.setText(plazaNameLocation);
        }
    });
    rs.close();
    ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM