在模拟程序中更改不同对象时如何更新 Scene Builder GUI?
How to update SceneBuilder GUI when change different object in simulaton program?
我正在 Java 中编写模拟器应用程序。有 3 种不同的 classes。 classes 中的某些更改必须更改 GUI 中的 TextField(SceneBuilder 制作)。在 gui 中单击按钮,必须在 classes 中更改对象。我用 SceneBuilder
制作了 GUI,我知道如何使用控制器 class。
有什么方法可以使用控制器 class for FXML
in object class 来更改 TextField 中的文本吗?像这样:
@Override
public void run() {
while (0 != 1) {
if (!stack.isEmpty())
controls.settfAI("INFECTED"); //controls is FXML controller // settfAI is id of text field
try {
sleep(3000);
} catch (InterruptedException e) {
CCLogger.cclogger(Watchman.class.getName(), Level.INFO, e);
}
}
}
第二个问题,当我点击按钮时,我可以编程改变控件中的对象class吗?像这样:
@FXML
Button btnOne; //btnOne is id in SceneBuilder file
//...
// AmbulanceCar ambulanceCar=new AmbulanceCar();
public void clicked() {
ambulanceCar.go(); // send ambulance car in some location
}
我的程序有很多按钮和 3 个必须更改模拟器状态的 TextField。
更新:
我有城市和移动的人。当人被感染时,Watchman 必须在 TextField 中看到人的位置。我有带有按钮和文本字段的 fxml。我知道 Watchman class 必须有来自 fxml 的 Controler。我得到控制器
Parent watchBtns = FXMLLoader.load(getClass().getResource("ControlGUI.fxml"));
URL contronLinkUrl=Paths.get("/ControlGUI.fxml").toUri().toURL();
FXMLLoader loader=FXMLLoader.load(contronLinkUrl);
之后,我用
将Controler发送给Watchmanclass
city.getWatchman().setControler(loader.getController());
在 Watchman class 中,我尝试使用以下代码编辑 TextField:
public void setControler(ControlerControlGUI controlGUI)
{
controlerControlGUI=controlGUI;
System.out.println("Controler set!");
}
@Override
public void run()
{
System.out.println("Watchman started!");
while(0!=1)
{
try {
if(!stack.isEmpty())
{
controlerControlGUI.settfAI("INFECTED");
}
sleep(3000);
} catch (InterruptedException e) {
CCLogger.cclogger(Watchman.class.getName(), Level.INFO, e);
}
}
}
现在我得到了错误
Caused by: java.lang.ClassCastException: class javafx.scene.layout.AnchorPane cannot be cast to class javafx.fxml.FXMLLoader (javafx.scene.layout.AnchorPane is in module javafx.graphics of loader 'app'; javafx.fxml.FXMLLoader is in module javafx.fxml of loader 'app')
更新,如果下面的答案对你来说很复杂...
在控制器 class 中,您可以放置您要控制的对象。在我的例子中是这样的:
Person infectedPerson;
Ambulance ambulance;
//call in main function
public void setInfectedInfo(Person person,Ambulance amb)
{
infectedPerson=person;
ambulance=amb;
}
在其他 class 中,我将此代码用于为 fxml 和 class 设置相同的控制器,这将同时使用它们
Stack<Alarm> stack= new Stack<>();
Vector<Ambulance> ambulances=new Vector<>();
ControlerControlGUI controlerControlGUI;
public void setControler(ControlerControlGUI controlGUI)
{
controlerControlGUI=controlGUI;
}
在 main class 中你可以输入:
FXMLLoader loader=new
FXMLLoader(getClass().getResource("ControlGUI.fxml"));
Parent watchBtns=loader.load();
city.getWatchman().setControler(loader.getController());
watchBtns.setLayoutX(840);
watchBtns.setLayoutY(100);
groupCity.getChildren().add(watchBtns);
我将尝试解释最后的代码部分。首先,您使用定义了控制器的 fxml 文件制作 FXMLLoader。然后你加载它。 (如果你不调用 load() 这将不起作用)。之后,您必须调用 getController 以在您的函数中拥有相同的控制器,并且您可以从外部调用控制器函数来控制您的 GUI 部分。
这里介绍了如何将 Object
的文本绑定到 Label
或 TextField
以通过操作对象来操作 GUI,反之亦然。
请注意,此答案侧重于您的问题,但并未为您提供复制和粘贴解决方案。为此,我将整个项目(包括 pom.xml)推送到 repo on my GitHub,以防你想克隆它并玩转它。
我使用了 Maven, you can find various ways to set up your environment here 的模块化项目。
应用程序:(主要class)
package com.broudy;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
/**
* JavaFX App
*/
public class App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("primary"));
stage.setScene(scene);
stage.show();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
return fxmlLoader.load();
}
public static void main(String[] args) {
launch();
}
}
守望者:
package com.broudy;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Watchman {
private StringProperty manipulatedText;
public Watchman() {
this.manipulatedText = new SimpleStringProperty("howdy!");
}
public String getManipulatedText() {
return manipulatedText.get();
}
public StringProperty manipulatedTextProperty() {
return manipulatedText;
}
public void setManipulatedText(String manipulatedText) {
this.manipulatedText.set(manipulatedText);
}
}
主控制器:
package com.broudy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class PrimaryController {
@FXML
private Label manipulatedLBL;
@FXML
private Button primaryButton;
@FXML
private TextField manipulatedTF;
@FXML
private Button manipulateWatchmanBTN;
private int i = 0;
@FXML
private void initialize() {
List<String> texts = new ArrayList<>();
texts.add("Hey! It works... Click again...");
texts.add("Again...");
texts.add("And again...");
texts.add("Wohooo");
texts.add("Yipeeeeeee!");
texts.add("Notice: ...");
texts.add("The text is changed in Watchman class but these change as well...");
Watchman watchman = new Watchman();
manipulatedTF.textProperty().bind(watchman.manipulatedTextProperty());
manipulatedLBL.textProperty().bind(watchman.manipulatedTextProperty());
// This is another acceptable way of assigning actions to buttons, etc.
manipulateWatchmanBTN.setOnAction(click -> {
watchman.setManipulatedText(texts.get(i++));
// This is just to reset the text
if (i >= texts.size()) {
i = 0;
}
});
}
@FXML
private void switchToSecondary() throws IOException {
App.setRoot("secondary");
}
}
简要说明:
PrimaryController
创建了一个 Watchman
实例并将其 textProperty
(manipulatedText
) 绑定到 TextField
和 Label
的textProperty
。
请注意,这里的绑定是单向的,这意味着只有 manipulatedText
会影响 TextField
和 Label
而不是相反。为此,您可以使用 bindBidirectional
.
现在,单击 manipulateWatchmanBTN
只会更改 Watchman
的 manipulatedText
的文本 - 这是对您第二个问题的回答 .因为我们将 GUI 绑定到它,所以我们使用 SceneBuilder 创建的 GUI 元素也会发生变化 - 这是对您第一个问题的回答。
随时根据您的具体需要进行调整。
我正在 Java 中编写模拟器应用程序。有 3 种不同的 classes。 classes 中的某些更改必须更改 GUI 中的 TextField(SceneBuilder 制作)。在 gui 中单击按钮,必须在 classes 中更改对象。我用 SceneBuilder
制作了 GUI,我知道如何使用控制器 class。
有什么方法可以使用控制器 class for FXML
in object class 来更改 TextField 中的文本吗?像这样:
@Override
public void run() {
while (0 != 1) {
if (!stack.isEmpty())
controls.settfAI("INFECTED"); //controls is FXML controller // settfAI is id of text field
try {
sleep(3000);
} catch (InterruptedException e) {
CCLogger.cclogger(Watchman.class.getName(), Level.INFO, e);
}
}
}
第二个问题,当我点击按钮时,我可以编程改变控件中的对象class吗?像这样:
@FXML
Button btnOne; //btnOne is id in SceneBuilder file
//...
// AmbulanceCar ambulanceCar=new AmbulanceCar();
public void clicked() {
ambulanceCar.go(); // send ambulance car in some location
}
我的程序有很多按钮和 3 个必须更改模拟器状态的 TextField。
更新: 我有城市和移动的人。当人被感染时,Watchman 必须在 TextField 中看到人的位置。我有带有按钮和文本字段的 fxml。我知道 Watchman class 必须有来自 fxml 的 Controler。我得到控制器
Parent watchBtns = FXMLLoader.load(getClass().getResource("ControlGUI.fxml"));
URL contronLinkUrl=Paths.get("/ControlGUI.fxml").toUri().toURL();
FXMLLoader loader=FXMLLoader.load(contronLinkUrl);
之后,我用
将Controler发送给Watchmanclasscity.getWatchman().setControler(loader.getController());
在 Watchman class 中,我尝试使用以下代码编辑 TextField:
public void setControler(ControlerControlGUI controlGUI)
{
controlerControlGUI=controlGUI;
System.out.println("Controler set!");
}
@Override
public void run()
{
System.out.println("Watchman started!");
while(0!=1)
{
try {
if(!stack.isEmpty())
{
controlerControlGUI.settfAI("INFECTED");
}
sleep(3000);
} catch (InterruptedException e) {
CCLogger.cclogger(Watchman.class.getName(), Level.INFO, e);
}
}
}
现在我得到了错误
Caused by: java.lang.ClassCastException: class javafx.scene.layout.AnchorPane cannot be cast to class javafx.fxml.FXMLLoader (javafx.scene.layout.AnchorPane is in module javafx.graphics of loader 'app'; javafx.fxml.FXMLLoader is in module javafx.fxml of loader 'app')
更新,如果下面的答案对你来说很复杂... 在控制器 class 中,您可以放置您要控制的对象。在我的例子中是这样的:
Person infectedPerson;
Ambulance ambulance;
//call in main function
public void setInfectedInfo(Person person,Ambulance amb)
{
infectedPerson=person;
ambulance=amb;
}
在其他 class 中,我将此代码用于为 fxml 和 class 设置相同的控制器,这将同时使用它们
Stack<Alarm> stack= new Stack<>();
Vector<Ambulance> ambulances=new Vector<>();
ControlerControlGUI controlerControlGUI;
public void setControler(ControlerControlGUI controlGUI)
{
controlerControlGUI=controlGUI;
}
在 main class 中你可以输入:
FXMLLoader loader=new
FXMLLoader(getClass().getResource("ControlGUI.fxml"));
Parent watchBtns=loader.load();
city.getWatchman().setControler(loader.getController());
watchBtns.setLayoutX(840);
watchBtns.setLayoutY(100);
groupCity.getChildren().add(watchBtns);
我将尝试解释最后的代码部分。首先,您使用定义了控制器的 fxml 文件制作 FXMLLoader。然后你加载它。 (如果你不调用 load() 这将不起作用)。之后,您必须调用 getController 以在您的函数中拥有相同的控制器,并且您可以从外部调用控制器函数来控制您的 GUI 部分。
这里介绍了如何将 Object
的文本绑定到 Label
或 TextField
以通过操作对象来操作 GUI,反之亦然。
请注意,此答案侧重于您的问题,但并未为您提供复制和粘贴解决方案。为此,我将整个项目(包括 pom.xml)推送到 repo on my GitHub,以防你想克隆它并玩转它。
我使用了 Maven, you can find various ways to set up your environment here 的模块化项目。
应用程序:(主要class)
package com.broudy;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
/**
* JavaFX App
*/
public class App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("primary"));
stage.setScene(scene);
stage.show();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
return fxmlLoader.load();
}
public static void main(String[] args) {
launch();
}
}
守望者:
package com.broudy;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Watchman {
private StringProperty manipulatedText;
public Watchman() {
this.manipulatedText = new SimpleStringProperty("howdy!");
}
public String getManipulatedText() {
return manipulatedText.get();
}
public StringProperty manipulatedTextProperty() {
return manipulatedText;
}
public void setManipulatedText(String manipulatedText) {
this.manipulatedText.set(manipulatedText);
}
}
主控制器:
package com.broudy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class PrimaryController {
@FXML
private Label manipulatedLBL;
@FXML
private Button primaryButton;
@FXML
private TextField manipulatedTF;
@FXML
private Button manipulateWatchmanBTN;
private int i = 0;
@FXML
private void initialize() {
List<String> texts = new ArrayList<>();
texts.add("Hey! It works... Click again...");
texts.add("Again...");
texts.add("And again...");
texts.add("Wohooo");
texts.add("Yipeeeeeee!");
texts.add("Notice: ...");
texts.add("The text is changed in Watchman class but these change as well...");
Watchman watchman = new Watchman();
manipulatedTF.textProperty().bind(watchman.manipulatedTextProperty());
manipulatedLBL.textProperty().bind(watchman.manipulatedTextProperty());
// This is another acceptable way of assigning actions to buttons, etc.
manipulateWatchmanBTN.setOnAction(click -> {
watchman.setManipulatedText(texts.get(i++));
// This is just to reset the text
if (i >= texts.size()) {
i = 0;
}
});
}
@FXML
private void switchToSecondary() throws IOException {
App.setRoot("secondary");
}
}
简要说明:
PrimaryController
创建了一个 Watchman
实例并将其 textProperty
(manipulatedText
) 绑定到 TextField
和 Label
的textProperty
。
请注意,这里的绑定是单向的,这意味着只有 manipulatedText
会影响 TextField
和 Label
而不是相反。为此,您可以使用 bindBidirectional
.
现在,单击 manipulateWatchmanBTN
只会更改 Watchman
的 manipulatedText
的文本 - 这是对您第二个问题的回答 .因为我们将 GUI 绑定到它,所以我们使用 SceneBuilder 创建的 GUI 元素也会发生变化 - 这是对您第一个问题的回答。
随时根据您的具体需要进行调整。