我想通过普通的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 & 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类中设置标签文本? 我需要以哪种方式修改我的代码?
答案 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();
...