gpt4 book ai didi

JavaFX 重定向 System.out 流 TextArea,仅在不用作具有固定 ID 的 FXML 组件时才工作。为什么?

转载 作者:行者123 更新时间:2023-11-30 03:48:54 27 4
gpt4 key购买 nike

所以这对我来说非常困惑。我决定将应用程序控制台重定向到 UI 中的 TextArea。

当我在 SceneBuilder 中使用固定文本区域(固定 ID)执行此操作,然后进行注释时

@FXML
private TextArea consoleTextArea;

什么也没发生。内容没有改变。是的,我确实在构造函数中初始化了它。并进一步初始化。这不是工作代码:

public class ConsoleController implements Initializable {

Thread t;
@FXML
private Label totalM;
@FXML
private Label freeM;
@FXML
private Label maxM;
@FXML
private TextArea consoleTextArea;

private Console console;
private PrintStream ps;


public ConsoleController() {
System.out.println("Called constructor");
totalM = new Label();
freeM = new Label();
maxM = new Label();
consoleTextArea = new TextArea();
console = new Console(consoleTextArea);
ps = new PrintStream(console, true);

}

@Override
public void initialize(URL location, ResourceBundle resources) {

redirectOutput(ps);


t = new Thread(() -> {
while (true) {
try {
Platform.runLater(() -> {
updateMemInfo();
});
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}

});
t.setPriority(Thread.MIN_PRIORITY);
t.setName("MemUpdateInfoThread");
t.setDaemon(true);
t.start();

}

private void updateMemInfo() {
totalM.setText("Total Memory (in bytes): " + Runtime.getRuntime().totalMemory());
freeM.setText("Free Memory (in bytes): " + Runtime.getRuntime().freeMemory());
maxM.setText("Max Memory (in bytes): " + Runtime.getRuntime().maxMemory());
}

private void redirectOutput(PrintStream prs) {
System.setOut(prs);
System.setErr(prs);
}

private void updateConsole(String text) {
for (int c : text.toCharArray()) {
try {
console.write(c);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

private class Console extends OutputStream {

private TextArea txtArea;

public Console(TextArea txtArea) {
this.txtArea = txtArea;
}

@Override
public void write(int b) throws IOException {
txtArea.appendText(String.valueOf((char) b));
}

}

}

经过一番编辑后,我决定不使用fxml id。只将id放在AnchorPane父级上,并在java代码中添加textArea。

  @FXML
private AnchorPane anchp;

private TextArea consoleTextArea;

//then added to anchor
anchp.getChildren().add(consoleTextArea);

工作代码:

public class ConsoleController implements Initializable {

Thread t;
@FXML
private Label totalM;
@FXML
private Label freeM;
@FXML
private Label maxM;
@FXML
private AnchorPane anchp;

private TextArea consoleTextArea;

private Console console;
private PrintStream ps;

public ConsoleController() {
System.out.println("Called constructor");
totalM = new Label();
freeM = new Label();
maxM = new Label();
anchp=new AnchorPane();
consoleTextArea = new TextArea();
console = new Console(consoleTextArea);
ps = new PrintStream(console, true);

}

@Override
public void initialize(URL location, ResourceBundle resources) {

anchp.getChildren().add(consoleTextArea);
AnchorPane.setTopAnchor(consoleTextArea, 0d);
AnchorPane.setLeftAnchor(consoleTextArea, 0d);
AnchorPane.setRightAnchor(consoleTextArea, 0d);
AnchorPane.setBottomAnchor(consoleTextArea, 0d);

redirectOutput(ps);

t = new Thread(() -> {
while (true) {
try {
Platform.runLater(() -> {
updateMemInfo();
});
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}

});
t.setPriority(Thread.MIN_PRIORITY);
t.setName("MemUpdateInfoThread");
t.setDaemon(true);
t.start();

}

private void updateMemInfo() {
totalM.setText("Total Memory (in bytes): " + Runtime.getRuntime().totalMemory());
freeM.setText("Free Memory (in bytes): " + Runtime.getRuntime().freeMemory());
maxM.setText("Max Memory (in bytes): " + Runtime.getRuntime().maxMemory());
}

private void redirectOutput(PrintStream prs) {
System.setOut(prs);
System.setErr(prs);
}

private void updateConsole(String text) {
for (int c : text.toCharArray()) {
try {
console.write(c);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

private class Console extends OutputStream {

private TextArea txtArea;

public Console(TextArea txtArea) {
this.txtArea = txtArea;
}

@Override
public void write(int b) throws IOException {
txtArea.appendText(String.valueOf((char) b));
}

}

}

为什么我无法在我正在使用的组件上使用固定ID来执行此操作?任何人都可以解释我做错了什么吗?

最佳答案

And yes i did initialized it in constructor.

这正是问题所在。切勿使用 @FXML 注释初始化注入(inject) Controller 的字段。

如果您使用 @FXML 注释字段,FXMLLoader 将使用 FXML 文件中声明的实例来初始化该字段,并与字段名称(“consoleTextArea”匹配) ") 到 fx:id 属性。显然,这一切都发生在构造函数完成之后,但在调用 initialize() 方法之前。因此,您传递给 Console 构造函数的 consoleTextArea 与您在调用 initalize() 方法时最终得到的实例是不同的实例被调用(以及稍后调用事件处理程序时)。

要解决此问题,请完全删除构造函数,并在 initialize() 方法中初始化您需要的其他部分(即 FXML 中未定义的内容)。

类似于:

public class ConsoleController implements Initializable {

Thread t;
@FXML
private Label totalM;
@FXML
private Label freeM;
@FXML
private Label maxM;
@FXML
private TextArea consoleTextArea;

private Console console;
private PrintStream ps;

@Override
public void initialize(URL location, ResourceBundle resources) {

console = new Console(consoleTextArea);
ps = new PrintStream(console, true);

redirectOutput(ps);


t = new Thread(() -> {
while (true) {
try {
Platform.runLater(() -> {
updateMemInfo();
});
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}

});
t.setPriority(Thread.MIN_PRIORITY);
t.setName("MemUpdateInfoThread");
t.setDaemon(true);
t.start();

}

// other methods as before...
}

关于JavaFX 重定向 System.out 流 TextArea,仅在不用作具有固定 ID 的 FXML 组件时才工作。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24915391/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com