Kor*_*ann 5 java user-interface multithreading task
我有一个 JavaFX 程序,我想在其中导入一个文件并从该文件中读取所有内容(应该是 .txt)并将其写入一个字符串,以便我可以对其进行处理。因为文件有时很大,让我的程序说“无响应”之类的,我想添加一个 ProgressBar,以显示当前的进度并阻止程序崩溃。
起初,我只是在对话框中添加了一个 ProgressBar,它会根据绑定打开和更新。但是 GUI 没有更新,所以我发现我必须做一个在后台运行的新线程,所以我的程序不会停止响应。所以我把所有的东西都打包成一个任务并用一个线程开始任务,但是现在带有 ProgressBar 的 Dialog 甚至没有出现,所以我调试它并发现程序甚至没有执行任务,就像, 没有做任何事情就过去了。
这是我当前的代码,我希望任何人都可以帮助我解决我的问题或向我解释任务/线程:
我的处理程序:
package application.handler;
import application.data.KTChat;
import application.gui.MyRootPane;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.MenuItem;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class MyHandler implements EventHandler<ActionEvent> {
private MyRootPane mp;
private FileChooser fc;
private Stage primaryStage;
private KTChat kt;
public MyHandler(MyRootPane mp, Stage primaryStage) {
this.mp = mp;
fc = new FileChooser();
fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text files (*.txt)", "*.txt"));
this.primaryStage = primaryStage;
kt = new KTChat(mp);
}
@Override
public void handle(ActionEvent event) {
String mdata = ((MenuItem)(event.getSource())).getId();
if(mdata.equalsIgnoreCase("import")) {
kr.readFile(fc.showOpenDialog(primaryStage));
}
}
public KTChat getKT() {
return kt;
}
}
Run Code Online (Sandbox Code Playgroud)
MyRootPane(我的 GUI):
package application.gui;
import java.io.File;
import application.handler.MyHandler;
import javafx.beans.property.DoubleProperty;
import javafx.collections.ObservableList;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MyRootPane extends BorderPane {
private TextArea eingabe = new TextArea();
private TextArea ausgabe = new TextArea();
private MenuBar mb = new MenuBar();
private Menu m2 = new Menu("Settings");
private MenuItem mi4 = new MenuItem("Import chat");
private Stage primaryStage;
private MyHandler mh;
private FortschrittDialog fd = new FortschrittDialog();
public MyRootPane(Stage primaryStage) {
this.primaryStage = primaryStage;
mh = new MyHandler(this, primaryStage);
initSettings();
setTop(mb);
setCenter(eingabe);
setBottom(ausgabe);
}
public void initSettings() {
ausgabe.setEditable(false);
eingabe.setPrefHeight(500);
ausgabe.setPrefHeight(500);
mi4.setId("import");
mi4.setOnAction(mh);
m2.getItems().add(mi4);
mb.getMenus().add(m2);
}
public void eingabeSetText(String eingabe) {
this.eingabe.setText(eingabe);
}
public String eingabeGetText() {
return eingabe.getText();
}
public void startFortschrittDialog() {
fd.show();
}
public void endFortschrittDialog() {
fd.close();
}
public void isFortschrittDialogCompleted() {
if(fd.isCompleted()) endFortschrittDialog();
}
public DoubleProperty progressP() {
return fd.getPBProgressProperty();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我的 KTChat 原本应该构建 String 的地方:
package application.data;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import application.gui.MyRootPane;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
public class KTChat {
private String chat;
private MyRootPane mp;
public KTChat(MyRootPane mp) {
this.mp = mp;
}
public void setChat(String eingabeGetText) {
this.chat = eingabeGetText;
getChat();
}
public void readFile(File chat) {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
if(chat.getName().contains("KakaoTalk_")) {
mp.startFortschrittDialog();
mp.setFortschritt(-1.0f);
String s = "";
String gesamt = "";
double laenge = 0;
try(BufferedReader brCount = new BufferedReader(new FileReader(chat))) {
while((s=brCount.readLine())!=null) {
laenge++;
}
} catch (IOException e) {
System.out.println("Fehler beim zählen");
}
double momentanErreicht = 0;
try(BufferedReader br = new BufferedReader(new FileReader(chat))) {
while((s=br.readLine())!=null) {
momentanErreicht++;
updateProgress(momentanErreicht, laenge);
s = s.replace("ß", "ß");
s = s.replace("ö", "ö");
s = s.replace("ü", "ü");
s = s.replace("ä", "ä");
s = s.replace("Ä", "Ä");
s = s.replace("Ü", "Ü");
s = s.replace("Ö", "Ö");
gesamt += s+"\n";
}
} catch (FileNotFoundException e1) {
System.out.println("File not found");
} catch (IOException e2) {
System.out.println("IOException");
}
mp.isFortschrittDialogCompleted();
mp.eingabeSetText(gesamt);
setChat(mp.eingabeGetText());
getChat();
} else mp.mhNichtPassendesFile();
return null;
}
};
mp.progressP().bind(task.progressProperty());
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
Run Code Online (Sandbox Code Playgroud)
我的 ProgressBar 所在的对话框:
package application.gui;
import javafx.beans.property.DoubleProperty;
import javafx.scene.control.Dialog;
import javafx.scene.control.ProgressBar;
@SuppressWarnings("rawtypes")
public class FortschrittDialog extends Dialog {
private ProgressBar pb = new ProgressBar();
public FortschrittDialog() {
pb.setPrefWidth(500);
pb.setProgress(-1f);
getDialogPane().setContent(pb);
}
public DoubleProperty getPBProgressProperty() {
return pb.progressProperty();
}
public boolean isCompleted() {
if(pb.getProgress()==1.0) return true;
else return false;
}
}
Run Code Online (Sandbox Code Playgroud)
最后但并非最不重要的是 Main 类:
package application;
import application.gui.MyRootPane;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
MyRootPane root = new MyRootPane(primaryStage);
Scene scene = new Scene(root,1280,720);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("KT-Chat-Statistics V1.1");
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试包含与问题相关的所有内容,您应该能够复制粘贴代码来自己测试。我真的不明白为什么它不起作用。
我发现了问题。对于遇到同样问题或只是想知道的其他人,这是我做错的事情:
您无法在后台任务期间调用 JavaFX-Thread-Methods,因此每个到达任务外部的方法(我认为只有 mp.-methods)都不会被执行。因此,我制作的对话框中的进度条将起作用,但对话框将不会显示,因为显示对话框的方法位于 MyRootPane-Class 中。正如我们现在所知,JavaFX-Thread-Methods 无法在后台任务期间执行。
因此,以下是代码中的具体更改,因此它可以发挥作用:您必须将所有 mp.-methods 放在任务之外,因此在通过线程启动任务之前,只需打开其中的对话框,例如:
mp.progressP().bind(task.progressProperty());
mp.startFortschrittDialog();
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
Run Code Online (Sandbox Code Playgroud)
我希望这是清晰易懂的,谢谢大家的宝贵时间。