【发布时间】:2017-03-07 21:14:37
【问题描述】:
我正在开发一个应用程序来检测网络钓鱼网站,在 javafx 中。我有一个“预测”按钮,可以在其 EventHandler 中进行所有必要的处理。我还希望能够使用有关在处理过程中获得多远的信息来更新 ProgressBar。我为此使用了一个任务,使用最终结果调用 updateProgress 和 updateValue。
但是,如果发生异常,我想更新 UI,然后立即终止 EventHandler 的执行,使用带有一些错误值的 updateProgress。但是,updateProgress 不会立即更新 UI。有没有什么东西不仅可以从 EventHandler 内部更新 UI,比如 Task,还可以让我准确控制 UI 更新的时间?
作为参考,这是我的完整事件处理程序代码:
predict.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event)
{
Task<Result> task = new Task<Result>()
{
@Override
protected Result call() throws Exception
{
String url = urlText.getText();
ArffData arffData = new ArffData();
try
{
updateProgress(1, 10);
URL uri = new URL(url);
String domain = uri.getHost();
arffData.setUrlSimilarity(DataGatherer.readLevenshtein(domain));
updateProgress(2, 10);
boolean redirection = DataGatherer.getRedirectionStatus(url);
arffData.setRedirection(redirection);
updateProgress(3, 10);
Response response = Jsoup.connect(url).execute();
arffData.setSpellingErrors(DataGatherer.getSpellingErrors(response).size());
}
catch (IOException e1)
{
updateProgress(-1, 10); //Should update UI before terminating
return null;
}
Classifier rf;
Instances instances;
try
{
updateProgress(4, 10);
rf = (Classifier) SerializationHelper.read("RF100.model");
instances = new DataSource("phishingData.arff").getDataSet();
}
catch (Exception e1)
{
updateProgress(-1, 10);
return null;
}
if (instances.classIndex() == -1)
instances.setClassIndex(instances.numAttributes() - 1);
String offers = offerText.getValue();
String lf = lfText.getValue();
updateProgress(5, 10);
Instance inst = InstanceSetup.setUpInstance(arffData, offers, lf, instances);
try
{
updateProgress(6, 10);
double clsLabel = rf.classifyInstance(inst);
instances.add(inst);
rf.buildClassifier(instances);
SerializationHelper.write("RF100.model", rf);
Evaluation eval = new Evaluation(instances);
eval.crossValidateModel(rf, instances, 10, new Random(1));
boolean phishing = clsLabel ==0 ?true: false;
Result result = new Result(phishing, eval.pctCorrect());
updateProgress(10, 10);
if(clsLabel == 0)
{
predictionLabel.setText("the given website IS a phishing website.");
}
else
{
predictionLabel.setText("the given website IS NOT a phishing website.");
}
updateValue(result);
accuracyLabel.setText("PhishGuard is " + String.format("%.4f%%", eval.pctCorrect()) +
" confident in this prediction.");
return result;
}
catch (Exception e)
{
updateProgress(-1, 10);
return null;
}
}
};
task.progressProperty().addListener(new ChangeListener<Number>()
{
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
{
switch(newValue.intValue())
{
case 1:
{
pBar.setProgress(10);
progressLabel.setText(progressLabels[1]);
}
case 2:
{
pBar.setProgress(30);
progressLabel.setText(progressLabels[2]);
}
case 3:
{
pBar.setProgress(50);
progressLabel.setText(progressLabels[3]);
}
case 4:
{
pBar.setProgress(70);
progressLabel.setText(progressLabels[4]);
}
case 5:
{
pBar.setProgress(80);
progressLabel.setText(progressLabels[5]);
}
case 6:
{
pBar.setProgress(90);
progressLabel.setText(progressLabels[6]);
}
case 10:
{
pBar.setProgress(100);
progressLabel.setText(progressLabels[0]);
}
case -1:
{
predictionLabel.setText("a prediction could not be made.");
accuracyLabel.setText("");
pBar.setProgress(0);
progressLabel.setText(progressLabels[0]);
}
}
}
});
task.valueProperty().addListener(new ChangeListener<Result>(){
@Override
public void changed(ObservableValue<? extends Result> observable, Result oldValue, Result newValue)
{
// TODO Auto-generated method stub
boolean phishing = newValue.isPhishing();
if(phishing)
{
predictionLabel.setText("the given website IS a phishing website.");
}
else
{
predictionLabel.setText("the given website IS NOT a phishing website.");
}
accuracyLabel.setText("PhishGuard is " + String.format("%.4f%%", newValue.getAccuracy()) +
" confident in this prediction.");
}
});
new Thread(task).start();
}});
【问题讨论】:
-
我不确定你在问什么。也许是:Can I pause a background Task / Service?。也许不是……
-
tasks have in-built exception handling,所以也许使用它可能比“使用带有一些错误值的 updateProgress”更好。
-
Task javadoc 有关于如何取消任务的信息,也许这就是你所说的“停止执行”的意思,尽管你也提到了“立即终止 EventHandler 的执行”,这似乎与任务,所以我不确定这是否有帮助。当您遇到竞争条件时,立即终止在多个线程上运行的东西通常是一个坏主意。通常,您需要某种合作沟通才能优雅地取消。
-
使用 Platform.runLater 见 stackoverflow.com/questions/15160410/… 和 stackoverflow.com/questions/16708931/…
-
进度值不是总是在0到1之间吗?
标签: java javafx concurrency