如何从另一个java类更改.fxml文件的标签文本(意味着控制器外)?

时间:2016-07-26 08:56:18

标签: java multithreading javafx javafx-8

我想通过普通的java类动态更改标签数据,我该怎么做。

下面是我的.fxml文件:

<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>

下面是我的控制器类:

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
   }        
}

在下面的代码中我尝试设置标签文本: -

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();
        }
    }
}

我得到以下异常:

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)

在这一行

LsduFrameController.PlazaNameData.setText(plazaNameLocation);

如何从另一个普通的java类中设置标签文本? 我需要以哪种方式修改我的代码?

2 个答案:

答案 0 :(得分:2)

FXMLLoader没有注入static字段。

保持静止(脏修复)

您可以将PlazaNameData设为实例字段并将其复制到static方法中的initialize字段

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;
        ...
    }

    ...

首选方法

使用static通常是糟糕的设计。在大多数情况下,有更好的方法来传递数据。

在这种情况下,您只需将LsduFrameController的引用传递给DisplayPlazaNameLocation,例如在构造函数中,并通过该引用访问控制器的相关实例成员。

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);
            }
        });
    ...
}

此外,应使用Platform.runLater完成来自javafx应用程序线程的不同线程的更新。

答案 1 :(得分:1)

您无法在FX Thread中更改其他Thread内容。改变这个:

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

为:

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();
    ...