javafx:使用Task更新UI,然后暂停执行

时间:2017-03-07 21:14:37

标签: java javafx concurrency

我正在javafx开发一个检测网络钓鱼网站的应用程序。我有一个"预测"在其EventHandler中执行所有必要处理的按钮。我还希望能够更新ProgressBar,其中包含有关处理过程中获取的信息。我为此使用了一个Task,使用最终结果调用updateProgress和updateValue。

但是,如果发生异常,我想更新UI,然后使用带有一些错误值的updateProgress立即终止EventHandler的执行。但是,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();
        }});

1 个答案:

答案 0 :(得分:1)

progressProperty()Task INDETERMINATE都是intValue()或者设置为0到1(含)之间的值。对于进度条:

  

0到1之间的正值表示0为0%且1为100%的进度百分比。任何大于1的值都被解释为100%。

因此,当您观察任务的进度值,然后获得-1时,只有三种可能性:1(当进度不确定时),0(当任务完成),或progressProperty(所有其他值)。当您使用任务INDETERMINATE注册听众时,它已处于intValue()状态,因此您看到的第一个更改为0 1(与您的任何内容都不匹配)在您看到10时,在任务完成之前,所有后续更改都会看到相同的值。此时,您将进度条的进度设置为pBar.progressProperty().bind(task.progressProperty()); pBar.textProperty().bind(task.messageProperty()); ,如上所述,将其解释为100%。

你真正想要做的只是将进度条的progress属性绑定到任务的progress属性(所以它们只是一起增加)。

要定期更新文本,您可以使用任务ProgressBar

因此,我将完全删除任务的进度属性上的侦听器,并将其替换为

updateMessage()

根据需要使用您需要的每条消息(稍后代码)调用Task

为此:

  

但是,如果发生异常,我想更新UI然后立即终止执行EventHandler

我假设你的意思是“终止执行Task”,因为事件处理程序早已完成。如评论中所述,call()默认处理异常。因此,您可以让异常从onFailed方法传播,并在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(); updateProgress(1, 10); updateMessage(progressLabels[1]); URL uri = new URL(url); String domain = uri.getHost(); arffData.setUrlSimilarity(DataGatherer.readLevenshtein(domain)); updateProgress(2, 10); updateMessage(progressLabels[2]); boolean redirection = DataGatherer.getRedirectionStatus(url); arffData.setRedirection(redirection); updateProgress(3, 10); updateMessage(progressLabels[3]); Response response = Jsoup.connect(url).execute(); arffData.setSpellingErrors(DataGatherer.getSpellingErrors(response).size()); Classifier rf; Instances instances; updateProgress(4, 10); updateMessage(progressLabels[4]); rf = (Classifier) SerializationHelper.read("RF100.model"); instances = new DataSource("phishingData.arff").getDataSet(); if (instances.classIndex() == -1) instances.setClassIndex(instances.numAttributes() - 1); String offers = offerText.getValue(); String lf = lfText.getValue(); updateProgress(5, 10); updateMessage(progressLabels[5]); Instance inst = InstanceSetup.setUpInstance(arffData, offers, lf, instances); updateProgress(6, 10); updateMessage(progressLabels[6]); 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); updateMessage(progressLabels[0]); 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; } }; pBar.progressProperty().bind(task.progressProperty()); pLabel.textProperty().bind(task.messageProperty()); 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."); } }); task.setOnFailed(e -> { predictionLabel.setText("a prediction could not be made."); accuracyLabel.setText(""); pBar.progressProperty().unbind(); pBar.setProgress(0); progressLabel.setText(progressLabels[0]); }); new Thread(task).start(); }}); 处理程序中执行UI更新。

结果如下所示:

imageView.subviews
相关问题