我试图在我的JavaFX接口类中实现一个进度指示器,它相应地更新到我的“读者”类,该类解析日志并跟踪它所取得的进展。
我目前的方法是创建一个单独的线程来运行Reader(这是因为当运行Reader时,界面会变得无响应),当Reader取得进展时,它将直接更新界面进度指示器。
接口类:
public class Interface extends Application {
public ProgressBar pb = new ProgressBar(0);
public ProgressIndicator pi = new ProgressIndicator(0);
private BorderPane bp = new BorderPane();
private Stage stage = new Stage();
private Scene scene = new Scene(bp, 400, 190);
private Button run = new Button();
private Button browseInputPath = new Button();
private Button browseOutputPath = new Button();
private CheckBox runAutomatically = new CheckBox("Run Automatically");
private TextField inputPath = new TextField();
private TextField outputPath = new TextField();
private HBox InputPath = new HBox(5);
private HBox OutputPath = new HBox(5);
private HBox progress = new HBox(10);
private File configFile = new File("config.txt");
private JFileChooser fc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage arg0) throws Exception {
initializeConfigFile();
initializeHBoxes();
initializeProps();
bp.setTop(progress);
bp.setBottom(OutputPath);
bp.setCenter(InputPath);
stage.setResizable(false);
stage.setScene(scene);
stage.show();
if ( runAutomatically.isSelected() ) { runReader(); }
}
@SuppressWarnings("deprecation")
private void runReader() {
run.setDisable(true);
browseInputPath.setDisable(true);
browseOutputPath.setDisable(true);
inputPath.setDisable(true);
outputPath.setDisable(true);
Reader reader = new Reader(inputPath.getText(), outputPath.getText());
Thread t = new Thread(reader, "thread");
t.start();
stage.setOnCloseRequest(event -> { t.stop(); });
}
private void writeConfigFile(Boolean runAuto, String inputPath, String outputPath) throws FileNotFoundException {
PrintWriter printer = new PrintWriter(new FileOutputStream(configFile, false));
printer.println("RunAutomatically: " + runAuto);
printer.println("InputDirectory: " + inputPath);
printer.println("OutputDirectory: " + outputPath);
printer.close();
}
private void initializeConfigFile() throws IOException {
if ( !configFile.exists() ) {
File inputFolder = new File("input");
File outputFolder = new File("output");
inputFolder.mkdir();
outputFolder.mkdir();
writeConfigFile(false, inputFolder.getAbsolutePath(), outputFolder.getAbsolutePath());
}
Scanner input = new Scanner(configFile);
while ( input.hasNext() ) {
if ( input.next().contains("RunAutomatically:") ) {
String temp = input.next();
if ( temp.contains("true")) {
runAutomatically.setSelected(true);
} else { runAutomatically.setSelected(false); }
}
if ( input.next().contains("InputDirectory:") ) { inputPath.setText(input.next()); }
if ( input.next().contains("OutputDirectory:") ) { outputPath.setText(input.next()); }
}
input.close();
}
private void initializeHBoxes() {
InputPath.setPadding(new Insets(15, 12, 10, 12 ));
InputPath.setStyle("-fx-background-color: #336699;");
InputPath.getChildren().add(inputPath);
InputPath.getChildren().add(browseInputPath);
OutputPath.setPadding(new Insets(15, 12, 15, 12 ));
OutputPath.setStyle("-fx-background-color: #336699;");
OutputPath.getChildren().add(outputPath);
OutputPath.getChildren().add(browseOutputPath);
progress.setPadding(new Insets(15, 12, 15, 12 ));
progress.setStyle("-fx-background-color: #336699;");
progress.getChildren().add(run);
progress.getChildren().add(runAutomatically);
progress.getChildren().add(pb);
progress.getChildren().add(pi);
}
private void initializeProps() {
run.setText("Start");
run.setPrefSize(75, 40);
Tooltip runHelper = new Tooltip("Begins process to parse log files. Files are taken from input directory path and completed files are placed in output directory path.");
Tooltip.install(run, runHelper);
run.setOnAction(event -> { runReader(); });
pb.setPrefSize(125, 30);
Tooltip pbHelper = new Tooltip("Total Transactions Completed for File");
Tooltip.install(pb, pbHelper);
pi.setPrefSize(100, 100);
Tooltip piHelper = new Tooltip("Total Files Completed");
Tooltip.install(pi, piHelper);
browseInputPath.setText(" ... ");
browseInputPath.setPrefSize(75, 30);
browseInputPath.setOnAction(event -> {
fc.setDialogTitle("Choose Input Directory");
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnValue = fc.showOpenDialog(null);
if ( returnValue == JFileChooser.APPROVE_OPTION) { inputPath.setText(fc.getSelectedFile().getAbsolutePath()); }
});
browseOutputPath.setText(" ... ");
browseOutputPath.setPrefSize(75, 30);
browseOutputPath.setOnAction(event -> {
fc.setDialogTitle("Choose Output Directory");
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnValue = fc.showOpenDialog(null);
if ( returnValue == JFileChooser.APPROVE_OPTION) { outputPath.setText(fc.getSelectedFile().getAbsolutePath()); }
});
runAutomatically.setOnAction(e -> {
try {
if ( runAutomatically.isSelected() ) {
writeConfigFile(true, inputPath.getText(), outputPath.getText());
} else { writeConfigFile(false, inputPath.getText(), outputPath.getText()); }
} catch (FileNotFoundException e2 ) { e2.printStackTrace(); }
});
Tooltip autoRunHelper = new Tooltip("If selected, program will automatically run on program startup.");
Tooltip.install(runAutomatically, autoRunHelper);
inputPath.setPrefSize(300, 30);
Tooltip inputPathHelper = new Tooltip("Input Path Directory");
Tooltip.install(inputPath, inputPathHelper);
outputPath.setPrefSize(300, 30);
Tooltip outputPathHelper = new Tooltip("Output Path Directory");
Tooltip.install(outputPath, outputPathHelper);
}
}
阅读类:
public class Reader extends Interface implements Runnable {
private ArrayList<ArrayList<String>> database;
private String storeInfo;
private String date;
private String inputDirectory;
private String outputDirectory;
private int finalTransactionNumber;
private int firstTransactionNumber;
private int totalTransactions = 0;
private int completedTransactions = 0;
private int totalFiles = 0;
private int completedFiles = 0;
public Reader(String inputDirectory, String outputDirectory) {
this.inputDirectory = inputDirectory;
this.outputDirectory = outputDirectory;
}
public void run() {
try {
File[] directory = new File(inputDirectory).listFiles();
totalFiles = directory.length;
for ( int i = 0; i < totalFiles; i++ ) {
completedTransactions = 0;
initializeArrayList(directory[i]);
storeInfo = retrieveStoreInfo(directory[i]);
date = retrieveLogDate(directory[i]);
new File(outputDirectory + "\\" + date).mkdirs();
File output = new File(outputDirectory + "\\" + date + "\\" + storeInfo + ".txt");
readFile(directory[i]);
writeTransactionInfo(output);
updateFileProgress();
}
} catch (FileNotFoundException e) { e.printStackTrace(); }
}
/**
* Updates progress bar from extended interface class by calculating completed transactions per file.
* @throws InterruptedException
*/
private void updateTransactionProgress() {
if ( totalTransactions == 0 ) { super.pb.setProgress(0); }
completedTransactions++;
super.pb.setProgress( (completedTransactions + 0.0) / totalTransactions );
System.out.println(pb.getProgress());
}
/**
* Updates progress indicator (pie chart) from extended interface class by calculating total completed files.
*/
private void updateFileProgress() {
if ( totalFiles == 0 ) { super.pi.setProgress(0); }
completedFiles++;
super.pi.setProgress( (completedFiles + 0.0) / totalFiles );
}
/**
* Scans log file to retrieve and save transaction information.
* Time Complexity: O(n)
* @param inputFile
* @throws FileNotFoundException
* @throws InterruptedException
*/
private void readFile(File inputFile) throws FileNotFoundException {
int transactionNumber = firstTransactionNumber;
Scanner input = new Scanner(inputFile);
while ( transactionNumber < finalTransactionNumber ) {
String tempTime = input.next();
String tempLine = input.nextLine();
if ( !database.get(0).get(transactionNumber - firstTransactionNumber).equals("-1") && !database.get(1).get(transactionNumber - firstTransactionNumber).equals("-1") && !database.get(2).get(transactionNumber - firstTransactionNumber).equals("-1") && !database.get(3).get(transactionNumber - firstTransactionNumber).equals("-1")) {
System.out.println("found transaction: " + transactionNumber);
updateTransactionProgress();
transactionNumber++;
} else if ( tempLine.contains("StartTransaction") && tempLine.contains("#" + transactionNumber) ) {
database.get(0).set(transactionNumber - firstTransactionNumber, tempTime);
} else if ( tempLine.contains("EndTransaction") && tempLine.contains("#" + transactionNumber) ) {
database.get(1).set(transactionNumber - firstTransactionNumber, tempTime);
} else if ( tempLine.contains("FTransType=") && tempLine.contains("" + transactionNumber) ) {
if ( database.get(2).get(transactionNumber - firstTransactionNumber).equals("-1") ) {
database.get(2).set(transactionNumber - firstTransactionNumber, (parseTransactionType(tempLine)));
} else {
database.get(3).set(transactionNumber - firstTransactionNumber, (parseTransactionType(tempLine)));
}
} else if ( tempLine.contains("PrePayTrsNumber=") && tempLine.contains("#" + transactionNumber)) {
database.get(4).set(transactionNumber - firstTransactionNumber, "Prepaid");
} else if ( !input.hasNextLine() ) {
if ( database.get(1).get(transactionNumber - firstTransactionNumber).equals("-1") && database.get(3).get(transactionNumber - firstTransactionNumber).equals("-1") ) {
database.get(1).set(transactionNumber - firstTransactionNumber, "");
database.get(3).set(transactionNumber - firstTransactionNumber, "");
} else if ( database.get(3).get(transactionNumber - firstTransactionNumber).equals("-1") ) {
database.get(3).set(transactionNumber - firstTransactionNumber, "");
}
input.close();
input = new Scanner(inputFile);
}
}
input.close();
}
/**
* Creates and fills database ArrayList which holds individual ArrayLists for each type of transaction information.
* Also instantiates variables which assist the log scanning process.
* @param inputFile
* @throws FileNotFoundException
*/
private void initializeArrayList( File inputFile ) throws FileNotFoundException {
firstTransactionNumber = retrieveFirstTransactionNumber(inputFile);
finalTransactionNumber = retrieveFinalTransactionNumber(inputFile, firstTransactionNumber);
totalTransactions = (finalTransactionNumber - firstTransactionNumber);
System.out.println(firstTransactionNumber);
System.out.println(finalTransactionNumber);
//database[0] = startTimes; database[1] = endTimes; database[2] = FTransType1; database[3] = FTransType2; database[4] = isPrepaid
database = new ArrayList<ArrayList<String>>(5);
for ( int i = 0; i < 5; i++ ) { database.add(new ArrayList<String>(totalTransactions)); }
for ( int i = 0; i < totalTransactions; i++ ) {
database.get(0).add("-1");
database.get(1).add("-1");
database.get(2).add("-1");
database.get(3).add("-1");
database.get(4).add("");
}
}
/**
* Parses strings from transaction log to retrieve transaction type.
* @param tempLine
* @return transaction type
*/
private String parseTransactionType(String tempLine) {
if ( tempLine.contains("Sale")) {
return "Sale";
} else if ( tempLine.contains("Void")) {
return "Void";
} else if ( tempLine.contains("PayOut")) {
return "PayOut";
} else if ( tempLine.contains("PayIn")) {
return "PayIn";
} else if ( tempLine.contains("Drop")) {
return "Drop";
} else if ( tempLine.contains("CloseBank")) {
return "CloseBank";
} else if ( tempLine.contains("OpenBank")) {
return "OpenBank";
} else if ( tempLine.contains("Refund")) {
return "Refund";
} else { return ""; }
}
/**
* Writes transaction information withheld in the database ArrayList to output file.
* @param outputFile
* @throws FileNotFoundException
*/
private void writeTransactionInfo(File outputFile) throws FileNotFoundException {
try {
PrintWriter writer = new PrintWriter(new FileOutputStream(outputFile, false));
writer.close();
writer = new PrintWriter(new FileOutputStream(outputFile, true));
for ( int i = 0; i < database.get(0).size(); i++ ) {
writer.println(firstTransactionNumber + i + "," + database.get(0).get(i) + "," + database.get(1).get(i) + "," + database.get(2).get(i) + ","
+ database.get(3).get(i) + "," + database.get(4).get(i) + "," + storeInfo + "," + date);
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Used to initialize transaction number variable; Locates first transaction number used.
* @param inputFile
* @return transaction number
* @return -1 if transaction number is not found
* @throws FileNotFoundException
*/
private int retrieveFirstTransactionNumber(File inputFile) throws FileNotFoundException {
Scanner input = new Scanner(inputFile);
while ( input.hasNext() ) {
String temp = input.next();
if ( temp.contains("StartTransaction") ) {
temp = input.next();
if ( temp.equals("Trs") ) {
temp = input.next();
input.close();
temp = temp.substring(1, temp.length());
return Integer.parseInt(temp);
}
}
}
input.close();
return -1;
}
/**
* Returns last transaction number in log; used to determine when file reader should stop.
* @param inputFile
* @param firstTransactionNumber
* @return -1 if not found
* @throws FileNotFoundException
*/
private int retrieveFinalTransactionNumber(File inputFile, int firstTransactionNumber) throws FileNotFoundException {
Scanner input = new Scanner(inputFile);
String temp = null;
int finalTransactionNumber = -1;
while ( input.hasNextLine() ) {
temp = input.nextLine();
if ( temp.contains("#" + Integer.toString(firstTransactionNumber).substring(0, 1)) && temp.contains("StartTransaction")) {
finalTransactionNumber = Integer.parseInt(temp.substring(87, 94));
}
}
input.close();
return finalTransactionNumber;
}
/**
* Retrieves register ID and store number
* @param inputFile
* @return computerName
* @throws FileNotFoundException
*/
private String retrieveStoreInfo(File inputFile) throws FileNotFoundException {
Scanner input = new Scanner(inputFile);
String computerName = null;
while ( computerName == null && input.hasNext() ) {
String temp = input.next();
if ( temp.startsWith("SPR") ) { computerName = temp; }
}
input.close();
return computerName;
}
/**
* Retrieves date of log file
* @param inputFile
* @return date
* @throws FileNotFoundException
*/
private String retrieveLogDate(File inputFile) throws FileNotFoundException {
Scanner input = new Scanner(inputFile);
String temp = null;
while ( input.hasNext() ) {
temp = input.next();
if ( temp.contains("Date:")) {
temp = input.next().replace('/', '-');
input.close();
return temp;
}
}
input.close();
return "";
}
}
当我在每次调用updateTransactionProgress()后检查进度栏时,该值正在正确更新。它只是没有更新Interface类中的进步栏。
我是多线程新手,不确定自己是否理解正确。我查阅了教程和其他示例,但没有找到多少帮助。我会很感激你的帮助。
编辑:包含整个类文件以获取更多详细信息。
如果没有足够的信息来做出明智的猜测,我建议你添加一个线程。sleep()
到读卡器
线程的运行()
实现。从你发布的内容来看,你的阅读器线程很可能在不Rest的情况下消耗了所有可用的处理器时间,因此GUI线程永远没有机会跳入并更新显示。
如果添加Thread.sleep()
解决了您发布的问题,您需要为您的Reader
线程确定一个合适的位置和持续时间,以便在您的run()
实现中定期让位。
看起来你的阅读器
类扩展了一个与你想象中不同的类。你叫超级。progressBar。setProgress()
,它正在调用父类接口
的进度条来更改它。即使Interface
扩展了GUI
类,GUI
中的progressBar
也是私有的,因此您无法访问它。我建议您在实例化阅读器
时,将进度条从GUI
类传递到阅读器
。
public class GUI extends Application {
private ProgressBar _progressBar = new ProgressBar(0);
// Methods which display GUI w/ progressBar
private void runReader() {
// progressBar should be instantiated by now, of course
Reader reader = new Reader(_progressBar, "input Path", "output Path");
Thread t = new Thread(reader, "reader thread");
t.start();
}
}
public class Reader extends Interface implements Runnable {
private final ProgressBar _progressBar = bar;
public void Reader(ProgressBar bar, String in, String out){
_progressBar = bar;
// Rest of constructor here
}
//Main processing methods that call 'updateTransactionProgress()'
private void updateTransactionProgress() {
if ( totalTransactions == 0 ) { super.pb.setProgress(0); }
completedTransactions++;.
// Call to Platform.runLater() to run the update on the JavaFX Application Thread
Platform.runLater(() -> {
_progressBar.setProgress((completedTransactions + 0.0) /
totalTransactions);
});
}
}
主要内容:创建ProgressIndicator进度指示器()以动态更改饼图的形式显示JavaFX中的操作进度。以下代码显示如何使用不确定值创建。 上面的代码生成以下结果。 创建ProgressIndicator 以下代码通过传递值来创建。 可以使用空构造函数创建没有参数的进度指示器。然后可以使用方法分配值。 如果无法确定进度,可以在不确定模式下设置进度控制,直到确定任务的长度。 以下代码显示如何创建一个完成25%的。 上面的代码生成以下结果。
我搜索了al堆栈溢出,我只找到了进度条。就像windows中的进度条和...我正在寻找一个多步骤进度条。就像我们在网上购物网站上存档信息时所拥有的一样。例如,它有4个步骤。1-选择产品2-填写信息...然后在每一步中,所有这些都是打开的,直到我们现在在那一步。下一步就走了。JavaFX中有thrick的插件吗?
我正在创建一个JavaFX桌面应用程序,我在上面模拟一些工作负载。我希望应用程序有一个动态更新的进度指示器(随着时间的推移),以显示加载过程是如何进行的。这是我的应用程序类: 这是我的预加载程序类: 另外,我需要说的是,我已经检查了这两个问题(预加载程序中的progressbar不更新和javafx预加载程序不更新进度),但没有找到解决问题的方法。 非常感谢您抽出时间。
问题内容: 我的应用程序中出现JavaFX(jdk 1.8.0_91)上的一个讨厌的错误,该错误中显示并更新了几个进度条(随机或同时显示)。有时,尤其是在填充进度条时(它具有进度条的样式类),但有时甚至一无所获,软件块和该跟踪出现了几次(并非总是相同的数字,而是最后一次)一次是27次): 然后在这27条痕迹之后跟随着大量的此消息: 线程“ JavaFX应用程序线程”中的异常java.lang.Ar
问题内容: 我同时使用Javafx和线程,并且遇到了这个问题,我制作了一个按钮,然后单击该按钮(使用事件处理程序)时,我做了一个for循环,将按钮更改为1,2,3,4 ,5,然后在每个中间延迟一秒钟。像倒计时! 但是发生的事情是延迟了5秒钟,并将按钮的文本更改为5。 问题是我希望看到它在1到5之间变化,但我看到的只是在5秒延迟结束时为5。我认为它会更改按钮文本,但看不到。我可能与类中的方法有关。
我同时使用Javafx和线程,我经常遇到这个问题,我制作了一个按钮,然后当单击按钮时(使用事件处理程序),我制作了一个for循环,将按钮更改为1、2、3、4、5,然后在每个按钮中间延迟一秒钟。就像倒计时一样! 但实际情况是,它会延迟5秒钟,并将按钮的文本更改为5。 问题是我想看到它在1到5之间变化,但我看到的只是5秒延迟结束时的5。我假设它会更改按钮文本,但我看不到它。我可能不得不处理<代码>。在