JavaFX - Thread com ProgressBar

Boa noite pessoal,

Estou tentando criar uma janelinha, uma dialog, que somente exiba um progressbar para indicar que o sistema está funcionando. O meu problema é que até consigo fazer a janela aparecer, mas ou ela é renderizada antes ou depois da outra operação (no caso uma de salvamento) executar.

Para criar a janela eu criei as seguintes classes:


public class DialogUtilPB extends Application{

    private static String caminhoPct = "./";
    
    private static String caminhoPctFxml = caminhoPct + "fxml/";
    
    private String title;
    private String msg;
    private Node node;
    private CrtDlgPB control;

    public DialogUtilPB(Node node, String msg){
        this.node = node;
        this.msg = msg;
    }
    
    public DialogUtilPB(Node node, String title, String msg){
        this(node, msg);
        this.title = title;
    }
    
    
    private static String getDlgPB() {
        return caminhoPctFxml + "DialogPB.fxml";
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = null;
        FXMLLoader fxml = new FXMLLoader();

        try {
            fxml.setLocation(DialogUtilPB.class.getResource(getDlgPB()));
            root = (Parent) fxml
                    .load(DialogUtilPB.class.getResourceAsStream(getDlgPB()));
                    

        } catch (IOException e) {
            e.printStackTrace();
        }
        Stage stage = new Stage();
        
        preencheCrtMensagemPb((CrtDlgPB) fxml.getController(), msg, root);
        
        stage.setTitle(title);
        stage.setScene(new Scene(root));
        stage.initModality(Modality.APPLICATION_MODAL);
        if(node != null){
            stage.initOwner(node.getScene().getWindow());
        }
        
        stage.sizeToScene();
        stage.show();
        
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public void setNode(Node node) {
        this.node = node;
    }

    private CrtDlgPB preencheCrtMensagemPb(CrtDlgPB x, String texto, Node root) {
        x.setMensagem(texto);
        x.setRoot(root);
        control = x;
        return x;
    }
    
    public void fechar(){
        control.fechar();
    }
    
    
}


public class CrtDlgPB implements Initializable{

    @FXML
    private Label lbMsg;
    
    @FXML
    private ProgressBar pbProgress;
    
    @FXML
    private Node root;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        pbProgress.setProgress(ProgressBar.INDETERMINATE_PROGRESS);
    }

    public void setMensagem(String msg) {
        this.lbMsg.setText(msg);
    }
    
    public void fechar(){
        ((Stage)root.getScene().getWindow()).close();
    }

    public void setRoot(Node root) {
        this.root = root;
    }



    
    
    
}


E tento invocar dessa forma:

    public void salvar(){
        System.out.println("aki 2 ");

        //Crio uma thread
        Task<Void> ts = new Task<Void>() {
            
            @Override
            protected Void call() throws Exception {

                //Instancio a classe
                DialogUtilPB x = new DialogUtilPB(root.getRoot(), "Salvando...");
                try {
                    //Executo a janela
                    x.start(new Stage());
                    
                    //Realizo um processamento qualquer
                    for(int i = 0; i<1000000;i++){
                        System.out.println("aki 1 " + i);
                    }
                    //Fecho a janela
                    x.fechar();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        };
        
        Platform.runLater(ts);
        

    }


1 curtida

Bom, vc quer q a janela abra, e o ProgressBar seja carregado né?, pelo oq eu to vendo esse for vai realizar um processo desse em menos de 1 segundo, não daria tempo de nada! e vc inicia a janela dentro do task ainda! o certo é iniciar antes de iniciar o Task! mas me explica melhor, vc quer q a janela abre é o progressBar fica carregando ?
depois do task vc tem q dizer para o progressBar observar o Task ex:

progresso.progressProperty().bind(task.progressProperty());

ai dentro do Task vc atualiza o ProgressBar usando:

updateProgress(1, 100);

Boa noite Jean,

Então é isso mesmo. A idéia é que o método seja ativado e a janelinha com o ProgressBar apareça (eu coloquei ele com valor indefinido) e após a execução do método essa janelinha feche. Para realizar o teste eu nivelei o for para rodar pelos menos uns dez segundos

Boa noite :slight_smile: já q ele é indefinito, vc tem q usar o Thread.sleep() para ele esperar um tempo não?
tipo dentro to Task

//espera 10 segundos
Thread.sleep(10 * 1000);
//depois de 10 segundos fecha
x.fechar();

Obs: recomendo iniciar a Task desta maneira:

Thread t = new Thread(task);
t.setDaemon(true);
t.start();
1 curtida

Metade do problema está resolvido. Deixei o código assim:

    public void salvar(){
        System.out.println("aki 2 ");

        //Instancio a classe
        try {
            DialogUtilPB x = new DialogUtilPB(root.getRoot(), "Salvando...");
            x.start(new Stage());
            
        //Crio uma thread
        Task<Void> ts = new Task<Void>() {

            @Override
            protected Void call() throws Exception {

                //                Thread.sleep(10 * 1000);

                //Realizo um processamento qualquer
                for(int i = 0; i<100000;i++){
                    System.out.println("aki 1 " + i);
                }
                //Fecho a janela
                x.fechar();
                return null;
            }
        };



            Thread t = new Thread(ts);
            t.setDaemon(true);
            t.start();
            

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


Agora a dialog abre, só não consigo fechar a mesma. Mas já é uma vitória estar abrindo a janela.

1 curtida

Esqueci de uma coisa, não podemos fechar uma janela pelo Task, temos que pedir outro @Override da Task é esse aqui:

   @Override
   protected void succeeded() {
    super.succeeded(); 
    }

na hora que o Call retorna esse é chamado, ai nele vc fecha a janela :slight_smile:
ficando assim no seu código:

    public void salvar(){
        System.out.println("aki 2 ");

        //Instancio a classe
        try {
            DialogUtilPB x = new DialogUtilPB(root.getRoot(), "Salvando...");
            x.start(new Stage());
            
        //Crio uma thread
        Task<Void> ts = new Task<Void>() {

            @Override
            protected Void call() throws Exception {

                //                Thread.sleep(10 * 1000);

                //Realizo um processamento qualquer
                for(int i = 0; i<100000;i++){
                    System.out.println("aki 1 " + i);
                }
                //ao retornar vai executar o Succeeded
               return null;
            }
          @Override
           protected void succeeded() {
           super.succeeded(); 
           x.fechar();
       }
 };

o Thread.sleep() não funcionou no seu caso né?

Realmente não tinha funcionado o Thread.sleep(). Mas esse método succeeded() foi mágico, resolveu todo o problema.

Muito obrigado!
Valeu mesmo!
:slightly_smiling:

1 curtida