简体   繁体   中英

JavaFX Auto Open new Window

I have A.fxml and B.fxml. A runing with Java Application override start method. I want to every 40 min in loop(5 times) { open new stage B.fxml and wait stage.close, if stage close continue loop open new stage B fxml. Loop this five times. I try timer timertask i could not. I try JavaFX Service i could not. I create Mythread extend Thread object. This time i could not control loop for next stage. When for statement start opening 5 stage. But i want to loop wait for currentstage is close then go next loop. This is my fail code;

public class Driver extends Application {

public static Stage stage;

@Override
public void start(Stage primaryStage) throws Exception {
    FXMLLoader loader = new FXMLLoader(getClass().getResource(View.SETTINGS));
    Parent root = loader.load();
    Scene scene = new Scene(root);
    stage = primaryStage;
    stage.setScene(scene);
    stage.setTitle("Info Library");
    stage.setResizable(false);
    stage.show();
    RandomQuestionThread thread = new RandomQuestionThread();
    if (DBContext.settings.isAbbreviation() || DBContext.settings.isTranslation()) {
        thread.start();
    }
}

public static void main(String[] args) throws InterruptedException {
    DBContext.settings = DBContext.getInstance().settings().getSettings();

    launch(args);
    HibernateUtil.getSessionFactory().close();
}

}

public class RandomQuestionThread extends Thread {
Thread randomThread = new Thread(this);
private String fxml;
private static String TITLE;


@Override
public void run() {
    while (true) {
        try {
            Thread.sleep(DBContext.settings.getAutoQuestionTime() * 6000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        for (int i = 0; i<DBContext.settings.getAutoQuestionCount(); i++) {
            randomFxml();
            Platform.runLater(()->{
                Parent root = null;
                try {
                    root = new FXMLLoader(getClass().getResource(fxml)).load();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Stage stage = new Stage();
                stage.setScene(new Scene(root));
                stage.setTitle(TITLE);
                stage.show();
                System.out.println(currentThread().getName());
            });
        }
    }
}

private void randomFxml() {
    int start = 0;
    if (DBContext.settings.isTranslation() && DBContext.settings.isAbbreviation()) {
        start = new Random().nextInt(2);
    } else if (DBContext.settings.isTranslation()) {
        start = 1;
    }

    switch (start) {
    case 0:
        fxml = View.ABBREVIATION;
        break;
    case 1:
        fxml = View.TRANSLATION;
        break;

    default:
        break;
    }
    if (start == 0) {
        TITLE = "KISALTMA SORUSU";
    } else TITLE = "ÇEVİRİ SORUSU";
}

}

I need to work more Java multi threads. But after fix this problem. Please explain where I'm doing wrong. In loop write console currentThread name console result "Java Apllication Thread". But i set my thread name "MyThread". I'm so confused.My brain gave blue screen error.

You've put your System.out.println(currentThread().getName()) statement into Platform.runLater() , which means that it will be executed on JavaFX Application Thread (see JavaDoc ).

Regarding your question about scheduling some task to repeat fixed number of times with predefined rate, this post could help you.

In loop write console currentThread name console result "Java Apllication Thread". But i set my thread name "MyThread". I'm so confused.

Using Platform.runLater you schedule the Runnable to be executed on the javafx application thread instead of the current thread which allows you to modify the UI, but also results in the current thread being the javafx application thread instead of the thread you call Platform.runLater from...

If you want to continue the "loop" after the window has been closed, you should schedule opening the next window after the last one has been closed. Stage.showAndWait() is a convenient way to wait for the stage to be closed.

For scheduling I'd recommend using a ScheduledExecutorService :

private ScheduledExecutorService executor;

@Override
public void stop() throws Exception {
    // stop executor to allow the JVM to terminate
    executor.shutdownNow();
}

@Override
public void init() throws Exception {
    executor = Executors.newSingleThreadScheduledExecutor();
}

@Override
public void start(Stage primaryStage) {
    Button btn = new Button("Start");
    btn.setOnAction(new EventHandler<ActionEvent>() {

        public void handle(ActionEvent event) {
            // just display a "empty" scene
            Scene scene = new Scene(new Pane(), 100, 100);
            Stage stage = new Stage();
            stage.setScene(scene);

            // schedule showing the stage after 5 sec
            executor.schedule(new Runnable() {

                private int openCount = 5;

                @Override
                public void run() {
                    Platform.runLater(() -> {
                        stage.showAndWait();
                        if (--openCount > 0) {
                            // show again after 5 sec unless the window was already opened 5 times
                            executor.schedule(this, 5, TimeUnit.SECONDS);
                        }
                    });
                }

            }, 5, TimeUnit.SECONDS);

        }
    });

    StackPane root = new StackPane();
    root.getChildren().add(btn);

    Scene scene = new Scene(root);

    primaryStage.setScene(scene);
    primaryStage.show();
}

I fix this. I used Timer and TimeTask in my main controller init method. And its work. But same code in app start method or in mian method stage didnt wait. I used stageshowandwait() method but thread didnt wait. But same code woked in main controller init method. Why i dont know.

Timer timer = new Timer();
    TimerTask timerTask = new TimerTask() {

        @Override
        public void run() {
            Platform.runLater(()->{
                for (int i = 0; i<4; i++) {
                    Parent root = null;
                    try {
                        root = new FXMLLoader(getClass().getResource(View.ABBREVIATION)).load();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    Stage stage = new Stage();
                    stage.setScene(new Scene(root));
                    stage.setTitle("deneme");
                    stage.showAndWait();
                }
            });
        }
    };

    timer.schedule(timerTask, 6000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM