javafx 以一种方法将多个字符串添加到 TextArea -> Everything is written once at the end
javafx adding multiple strings into TextArea in one method -> Everything is written once at the end
我有一个 javafx 程序,我想用它来分析网站。一开始我只想将站点的源代码打印到 TextArea 中,但在此之前,我写 "loading website sourcecode..."
我的目标是先写 "loading website sourcecode...",然后在网站解析完成几秒钟后,添加源代码。
在我按下按钮的那一刻,没有任何反应,3-5 秒后立即显示 "loading website sourcecode..." 消息和源代码。
所以我其实是想一个接一个地显示字符串。我已经用谷歌搜索了 2 个小时,并尝试了线程、invokelater、platform.runLater() 等等,但没有任何效果,代码很简单。
ModelView.java - 控制器 Class
package root;
import javafx.application.Platform;
...
public class ModelView {
@FXML public TextField UrlInput;
// This gets called when the button is pressed
public void checkUrl() throws InterruptedException
{
String url = UrlInput.getText();
LogWriter lw = new LogWriter();
lw.printMsg("loading website sourcecode...");
lw.printMsg(HTMLParser.directUrlToCode(url));
}
}
LogWriter.java
package root;
import javafx.beans.value.ObservableValue;
...
public class LogWriter extends Thread{
@FXML TextArea Log;
public LogWriter()
{
Log = (TextArea) Main.scene.lookup("#Log");
}
void printMsg(String s)
{
Log.setText(this.Log.getText()+"\n"+s);
}
}
编辑:
关于 HTMLParser 方法没有太多可说的,但我补充说它扩展了 Thread。
我尝试将 ModelView.java 更改为:
ModelView.java - 版本 2
package root;
import javafx.application.Platform;
...
public class ModelView<V> {
@FXML public TextField UrlInput;
// This gets called when the button is pressed
public void checkUrl() throws InterruptedException
{
String url = UrlInput.getText();
LogWriter lw0 = new LogWriter();
lw0.start();
lw0.printMsg("loading website sourcecode...");
HTMLParser hp = new HTMLParser();
hp.start();
LogWriter lw1 = new LogWriter();
lw1.start();
lw1.printMsg(hp.directUrlToCode(url));
}
}
还是一样的效果
编辑2:
这是我试过的另一个版本,在这种情况下,"loading website sourcecode..."甚至没有显示,我继续尝试...
ModelView.java checkUrl() - 版本 3
public void checkUrl() throws InterruptedException
{
String url = UrlInput.getText();
Task<Void> task = new Task<Void>(){
@Override protected Void call() throws Exception {
if(isCancelled()) {
updateMessage("Cancelled");
LogWriter lw = new LogWriter();
lw.printMsg("loading website sourcecode...");
}
return null;
}
};
Thread t = new Thread(task);
t.start();
HTMLParser hp = new HTMLParser();
LogWriter lw1 = new LogWriter();
lw1.printMsg(hp.directUrlToCode(url));
}
首先,从 JavaFX 应用程序线程外部操作可观察变量不是一个好主意。您将无法将其他变量绑定到它(您将得到 IllegalStateException
s)
其次,我会像这样实现 LogWriter
:
// ...
public class LogWriter {
private final TextArea txtLog;
public LogWriter(TextArea txtLog) {
this.txtLog = txtLog;
}
void printMsg(final String s) {
if (!Platform.isFxApplicationThread()) {
Platform.runLater(new Runnable() {
@Override
public void run() {
printMsg(s);
}
});
} else {
txtLog.setText(txtLog.getText() + "\n" + s);
}
}
}
并这样使用它:
//...
@FXML
private TextArea txtLog;
// ...
public void checkUrl() {
final String url = UrlInput.getText();
final LogWriter lw = new LogWriter(txtLog);
Task<String> task = new Task<String>() {
@Override
protected String call() {
lw.printMsg("loading website sourcecode...");
return HTMLParser.directUrlToCode(url);
}
@Override
protected void succeeded() {
super.succeeded();
lw.printMsg(getValue());
}
@Override
protected void failed() {
super.failed();
if (getException() != null) {
getException().printStackTrace();
}
lw.printMsg("failed!");
}
};
new Thread(task).start();
}
请注意 HTMLParser
不需要扩展 Thread
。
我有一个 javafx 程序,我想用它来分析网站。一开始我只想将站点的源代码打印到 TextArea 中,但在此之前,我写 "loading website sourcecode..."
我的目标是先写 "loading website sourcecode...",然后在网站解析完成几秒钟后,添加源代码。
在我按下按钮的那一刻,没有任何反应,3-5 秒后立即显示 "loading website sourcecode..." 消息和源代码。
所以我其实是想一个接一个地显示字符串。我已经用谷歌搜索了 2 个小时,并尝试了线程、invokelater、platform.runLater() 等等,但没有任何效果,代码很简单。
ModelView.java - 控制器 Class
package root;
import javafx.application.Platform;
...
public class ModelView {
@FXML public TextField UrlInput;
// This gets called when the button is pressed
public void checkUrl() throws InterruptedException
{
String url = UrlInput.getText();
LogWriter lw = new LogWriter();
lw.printMsg("loading website sourcecode...");
lw.printMsg(HTMLParser.directUrlToCode(url));
}
}
LogWriter.java
package root;
import javafx.beans.value.ObservableValue;
...
public class LogWriter extends Thread{
@FXML TextArea Log;
public LogWriter()
{
Log = (TextArea) Main.scene.lookup("#Log");
}
void printMsg(String s)
{
Log.setText(this.Log.getText()+"\n"+s);
}
}
编辑:
关于 HTMLParser 方法没有太多可说的,但我补充说它扩展了 Thread。
我尝试将 ModelView.java 更改为:
ModelView.java - 版本 2
package root;
import javafx.application.Platform;
...
public class ModelView<V> {
@FXML public TextField UrlInput;
// This gets called when the button is pressed
public void checkUrl() throws InterruptedException
{
String url = UrlInput.getText();
LogWriter lw0 = new LogWriter();
lw0.start();
lw0.printMsg("loading website sourcecode...");
HTMLParser hp = new HTMLParser();
hp.start();
LogWriter lw1 = new LogWriter();
lw1.start();
lw1.printMsg(hp.directUrlToCode(url));
}
}
还是一样的效果
编辑2:
这是我试过的另一个版本,在这种情况下,"loading website sourcecode..."甚至没有显示,我继续尝试...
ModelView.java checkUrl() - 版本 3
public void checkUrl() throws InterruptedException
{
String url = UrlInput.getText();
Task<Void> task = new Task<Void>(){
@Override protected Void call() throws Exception {
if(isCancelled()) {
updateMessage("Cancelled");
LogWriter lw = new LogWriter();
lw.printMsg("loading website sourcecode...");
}
return null;
}
};
Thread t = new Thread(task);
t.start();
HTMLParser hp = new HTMLParser();
LogWriter lw1 = new LogWriter();
lw1.printMsg(hp.directUrlToCode(url));
}
首先,从 JavaFX 应用程序线程外部操作可观察变量不是一个好主意。您将无法将其他变量绑定到它(您将得到 IllegalStateException
s)
其次,我会像这样实现 LogWriter
:
// ...
public class LogWriter {
private final TextArea txtLog;
public LogWriter(TextArea txtLog) {
this.txtLog = txtLog;
}
void printMsg(final String s) {
if (!Platform.isFxApplicationThread()) {
Platform.runLater(new Runnable() {
@Override
public void run() {
printMsg(s);
}
});
} else {
txtLog.setText(txtLog.getText() + "\n" + s);
}
}
}
并这样使用它:
//...
@FXML
private TextArea txtLog;
// ...
public void checkUrl() {
final String url = UrlInput.getText();
final LogWriter lw = new LogWriter(txtLog);
Task<String> task = new Task<String>() {
@Override
protected String call() {
lw.printMsg("loading website sourcecode...");
return HTMLParser.directUrlToCode(url);
}
@Override
protected void succeeded() {
super.succeeded();
lw.printMsg(getValue());
}
@Override
protected void failed() {
super.failed();
if (getException() != null) {
getException().printStackTrace();
}
lw.printMsg("failed!");
}
};
new Thread(task).start();
}
请注意 HTMLParser
不需要扩展 Thread
。