有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java进度指示器在主代码停止之前不会显示

我为一个愚蠢的问题挣扎了好几天,我需要你的帮助。我只是试图在一个单独的阶段中显示一个不确定的流程指示器,如下面的那个,而我的主代码执行一个循环。如果循环时满足某个条件,则应关闭进度阶段,并继续执行主代码

enter image description here

现在,我能够在主代码开始循环之前打开一个新的阶段,但是阶段中还不会显示进度指示器。但一旦满足条件,指示灯就会突然出现在舞台上并旋转。但只要主代码再次开始运行,指示器就会冻结,但仍然可见

我将简要解释下面的每段代码的作用。如何使加载阶段最初显示时指示器可见,然后在调用showMessage()方法时该阶段关闭?基本上,我想向用户显示后台循环正在发生,直到主代码达到showMessage()

Main。java 我不会发布它,因为它只创建了第一个GUI。它使用menu.fxml作为FXMLLoader中的资源。。。并且menu.fxml使用Controller.java作为控制器

控制器。java 这段代码更改了主GUI中的场景,使其具有新的布局,要求用户单击其中一个可见按钮。然后检查源按钮是否为Button1。。。如果是,则创建/显示一个使用sample.fxml作为资源的新阶段。然后运行最后一个文件Loop.java

public class Controller implements Initializable {

    public Stage loadingStage;

    @FXML
    ProgressIndicator progressIndicator;

    public void handlerButtonClick() throws IOException {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("field.fxml"));
        Parent rootOne = loader.load();
        ((Controller) loader.getController()).setPrimaryStage(primaryStage);
        ((Controller) loader.getController()).setPrimaryScene(scene);
        sceneField = new Scene(rootOne, 420, 510);
        primaryStage.setScene(sceneField);
        primaryStage.setTitle("Import Data");
        primaryStage.show();
    }

    public void fieldOption(ActionEvent e) throws Exception {

        source = e.getSource();
        if (source == Button1) {

            Loop loopObj = new Main();
            String[] args = {};

            //Create new stage to contain the Progress Indicator
            FXMLLoader loader2 = new FXMLLoader(getClass().getResource("sample.fxml"));
            Parent root2 = loader2.load();
            Controller2 controller = loader2.getController();
            loadingStage = new Stage();
            loadingStage.setTitle("Loading Stage");
            Scene scene = new Scene(root2, 200, 200);
            loadingStage.setScene(scene);
            loadingStage.show();

            //Runs the looper
            loopObj.start(stage);
        }

    }

样本。fxml

此代码创建进度指示器,并使用控制器Controller2

<AnchorPane prefHeight="200.0" prefWidth="200.0" xmlns:fx="http://javafx.com/fxml/1"
            xmlns="http://javafx.com/javafx/2.2" fx:controller="Controller2">
    <children>
        <ProgressIndicator fx:id="progressIndicator" layoutX="78.0" layoutY="55.0" progress="-1.0"/>
    </children>
</AnchorPane>

控制器2。java 此代码实现Initializable以使进度指示器可见:

public class Controller2 implements Initializable {
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        ProgressIndicator progressIndicator = new ProgressIndicator();
        progressIndicator.setVisible(true);
    }
}

循环。java 这是执行循环的主代码。加载阶段应显示进度指示器,直到Loop.java调用其showMessage()函数,此时加载阶段关闭。我知道这些方法中的一种似乎是不必要的,但这只是因为它们是为了演示而剥离的

public class Loop extends Application {
    @Override
    public void start(Stage ignored) throws Exception {
        Platform.setImplicitExit(false);
        for (int i = 0; i <= 100; i++) {
            if (i == 75){
                saveAttachment("Hello");
            }
        }
    }

    public static void saveAttachment(String subject) throws IOException, MessagingException {
        showMessage(subject);
    }

    private static void showMessage(String subject) throws IOException, MessagingException {
        // Close the loading stage here.
    }
}

注意它如何使用public void start(Stage ignored)。主要的java使用public void start(Stage primaryStage)。也许这是不好的。 我很沮丧,请帮帮我

更新

我已经应用了Brian的建议,并且在Controller.java中添加了一个新任务,如下所示:

 Stage loadingStage = new Stage();

           //create task object
           Task<Void> task = new Task<Void>(){
               @Override
               protected Void call() throws Exception{
                   System.out.println("Background task started...");
                   FXMLLoader loader2 = new FXMLLoader(getClass().getResource("sample.fxml"));
                   Parent root2 = loader2.load();
                   Controller2 controller = loader2.getController();
                   loadingStage.setTitle("Hello World");
                     Scene scene = new Scene(root2, 450, 250);
                   System.out.println("HERE6");
                   loadingStage.setScene(scene);
                   System.out.println("HERE7");
                   loadingStage.show();
                   System.out.println("HERE8");
                   return null;
               }
           };

           Thread th = new Thread(task);
           th.setDaemon(true);
           System.out.println("Starting background task...");
           th.start();

现在的问题是,它没有到达打印输出行“HERE7”。它成功地进入任务并继续主代码,但任务没有超出打印“HERE6”的位置,因此没有打开新的阶段。有什么好处


共 (1) 个答案

  1. # 1 楼答案

    在Ctlr2中有ProgressIndicator progressIndicator = new ProgressIndicator();,但如果它在FXML文件中,则不会创建新文件。出于某种原因,就像你在第一个Ctlr中做的那样

    但这并不能解决您的问题,您正在JavaFX应用程序线程(GUI线程)上运行所有程序。可能发生的事情(我没有真正阅读代码)是,你在同一个线程上做这两件事,进度指示器必须等待main完成,然后它才能更新GUI。你需要为任务和并发性添加标签

    点击这里,搜索更多例子。 https://stackoverflow.com/a/22847734/2855515