Passar os dados da tela de pesquisa para outro form?

803 views
Skip to first unread message

Vinicius Vasconcelos

unread,
Sep 2, 2014, 7:36:51 PM9/2/14
to java...@googlegroups.com
Boa noite pessoal, 
estou fazendo um crud e estou com dúvida na alteração... minha situação é a seguinte: Tenho o Form1 que é de cadastro, tenho o botão pesquisa que chama o Form2( lista), no Form2 tenho um botão de Alterar que ao ser clicado leva os dados para o Form1 para serem alterados...consigo passar as informações, mas sempre chama um novo Form1... gostaria de saber como poderei fazer para ao clicar no botao de alterar fechar a tela de pesquisa e os dados irem para o formulário que chamou e não criar um novo... Alguém poderia me dar uma dica. Obrigado.

Segue o código de como estou chamando as telas:

Código da tela de cadastro que chama a tela de pesquisa...
public void chamaForm2(ActionEvent aciton) throws IOException{
Parent parent = FXMLLoader.load(getClass().getResource("/application/Form2.fxml"));
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();
}

Faço uma new Stage(). Carrega o dados clicados, mas sempre abre uma nova tela
public void alteraForm1(ActionEvent event) throws IOException{
Cliente cli;
cli=tabelaListaClientes.getSelectionModel().getSelectedItem();
           cliController.setIdController(cli.getId());
           cliController.setNomeController(cli.getNome());        
   
Parent parent = FXMLLoader.load(getClass().getResource("/application/Form1.fxml"));
Stage stage = new Stage();
Scene scene = new Scene(parent);
            stage.setScene(scene);    
stage.show();
}

Vinicius Vasconcelos

unread,
Sep 4, 2014, 11:01:06 AM9/4/14
to java...@googlegroups.com
Tentei fazer assim para fechar a Stage de outro controlador:
Nas duas classes criei:  public static Stage stage;
E logo depos do stage.show() do método alterar fiz: form1.getStage().close(); form2.getStage().close(); mas erro: java.lang.NullPointerException
obs.: Minhas classes implementa Initializable

Junior Tada

unread,
Sep 7, 2014, 10:48:09 PM9/7/14
to java...@googlegroups.com
Vinícius, basicamente o que vc precisa fazer é enviar informações de um controller para o outro, e de acordo com as boas práticas recomendadas pela oracle isto deve ser feito utilizando ResourceBundle.
Bom vc instancia um ResourceBundle e joga nele qualquer coisa que será utilizada no outro controller e recebe esses dados no método initialize do controller para o seu arquivo fxml.
Eu procurei a documentação aqui e não encontrei, pq eles alteraram algumas coisas do lançamento do javafx 2.0 para as versões subsequentes e acho que estão corrigindo, mas acho que aqui no grupo mesmo tem alguns tópicos mais antigos sobre isso. Vou postar aqui um exemplo simples que tenho em uma aplicação que fiz mas seguindo a documentação ainda do lançamento, na verdade eu não sei ao certo o que mudou, mas esse código ainda funciona.

//instancia o ResourceBundle colocando qualquer objeto que vc irá precisar acessar no outro controller
//neste exemplo eu crio um stage e crio o resourcebundle e adiciono o stage no resourcebundle
final Stage stage = new Stage(StageStyle.DECORATED);
        ResourceBundle rb = new ResourceBundle() {
            @Override
            protected Object handleGetObject(String key) {
                if (key.contains("receitas")) {
                    return cli.getReceitas();
                } else if (key.contains("stage")) {
                    return stage;
                } else if (key.contains("view")) {
                    return "venda";
                } else {
                    return null;
                }
            }

            @Override
            public Enumeration<String> getKeys() {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };

Depois vc precisa adicionar o resourcebundle para o seu fxml e scene:
AnchorPane secondaryLayout = (AnchorPane) FXMLLoader.load(appotica_v2.AppOtica_v2.class.getResource("/view/receita.fxml"), rb, new JavaFXBuilderFactory());
Scene scene2 = new Scene(secondaryLayout, 1366, 768);
scene2.getStylesheets().add(AppOtica_v2.class.getResource("estilo.css").toExternalForm());
stage.setScene(scene2);
stage.show();

A partir do momento que vc chamou o método show() vc "pega" o resourcebundle no seu controller (no seu caso, pelo que entendi no controller do form2) no método initialize:
// initialize your logic here: all @FXML variables will have been injected
        if (resources != null) {
            if (resources.getObject("receitas") != null) {
                receitas = (Set<Receita>) resources.getObject("receitas");
                carregarTabela();
                carregarGraficos();
            }
            if (resources.getObject("stage") != null) {
                stage = (Stage) resources.getObject("stage");
            }
            if (resources.getObject("view") != null) {
                view = (String) resources.getObject("view");
            }
        }

Bom essa é umas das formas de ser feito, e como eu disse teve algumas modificações nas versões mais recentes, mas logo no lançamento da versão 2.0 era uma das formas recomendadas de se fazer comunicação entre controllers.  Se eu não me engano, acho que já na versão 2.0 do scene builder, o gerador de classe controller já gera uma variável resourcebundle sem vc precisar fazer nada no metodo initialize.
Não sei se ficou claro, mas espero ter ajudado.

Junior Tada

Vinicius Vasconcelos

unread,
Sep 8, 2014, 2:49:04 PM9/8/14
to java...@googlegroups.com
Olá Júnior, 
o que não consegui fazer até agora é: Form1 chama Form2. Quando clicar no botão altera do Form2 gostaria de fechar a Form2 e mostrar as informações no Form1... estou conseguindo passar as informações, mas sempre chamo uma nova tela e assim ficam 3 telas abertas...  

Faço uma new Stage(). Carrega o dados clicados, mas sempre abre uma nova tela
public void alteraForm1(ActionEvent event) throws IOException{
Cliente cli;
cli=tabelaListaClientes.getSelectionModel().getSelectedItem();
            cliController.setIdController(cli.getId());
            cliController.setNomeController(cli.getNome());          
    
Parent parent = FXMLLoader.load(getClass().getResource("/application/Form1.fxml"));
Stage stage = new Stage();
Scene scene = new Scene(parent);
             stage.setScene(scene);    
stage.show();
}

Esse código estar no Form2 e quando clicar nesse botão gostaria de fechar todas as telas e deixar apenas a tela que mostra as informaçoes! 
Poderia me dá uma dica de como fazer isso? Obrigado.

Junior Tada

unread,
Sep 8, 2014, 10:37:21 PM9/8/14
to java...@googlegroups.com
Então Vinícius, é exatamente aquele exemplo que te mandei. Dentro do action do seu form1 que invoca o form2 vc instacia um stage, instancia um resorcebundle e envia esse stage para o resourcebundle. Seria algo mais ou menos assim:
                //Esse código na action do seu form1 que invoca seu form2
                Cliente cli;
cli=tabelaListaClientes.getSelectionModel().getSelectedItem();
             cliController.setIdController(cli.getId());
             cliController.setNomeController(cli.getNome());
Stage stage = new Stage();
                
                ObjetoComAsInformacoesQueVcPrecisaNoForm1 seu_objeto;

           ResourceBundle rb = new ResourceBundle() {
                 @Override
                  protected Object handleGetObject(String key) {
                if (key.contains("seu_objeto")) {
                    return seu_objeto;
                } else if (key.contains("stage")) {
                    return stage;
                } else {
                    return null;
                }
            }

            @Override
            public Enumeration<String> getKeys() {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };

                //Aqui vai abrir e exibir o seu form2
Parent parent = FXMLLoader.load(getClass().getResource("/application/Form2.fxml"), rb);
Scene scene = new Scene(parent);
             stage.setScene(scene);    
stage.show();

Daí lá no controller do seu form2 vc pega esse resourcebundle com o stage e o seu objeto, passa as informações para o seu_objeto e na action do botão que fecha a janela vc da um stage.close() que o fluxo do seu programa vai voltar para o controller do form1 e vc pode utilizar as informações que vc jogou no seu_objeto.

Junior Tada

unread,
Sep 8, 2014, 10:43:09 PM9/8/14
to java...@googlegroups.com
Esqueci de perguntar, mas vc está usando janela modal ou Multiple Document Interface (tipo jdesktopPane e jinternalframe do swing) ? 

Vinicius Vasconcelos

unread,
Sep 11, 2014, 1:18:34 PM9/11/14
to java...@googlegroups.com
        Boa tarde pessoal. Olá Junior!
        Na tela de pesquisa coloquei MODAL. As outras múltiplas instâncias...
        Apanhei um bocado com ResourceBundle e sempre dava nullExcepiton na chamada do outro controlador! então voltei a pesquisar sobre variáveis estáticas e caso outra pessoa necessite vou postar como consegui resolver.
        Primeiro tentei chamar: form1.getStage().close() e resultado era NULL.
        Não sei se é a melhor maneira, mas funcionou. No controlador criei a variável - public static Stage stage = new Stage(); e fiz o GET. No método que chama o formulário coloca: Controller.stage=stage; E coloca esse código - Controller.getStage().close(); onde quer fechar a outra tela.

Obrigado pela ajuda. Abraço.

Junior Tada

unread,
Sep 11, 2014, 1:31:16 PM9/11/14
to java...@googlegroups.com
Vinícius no seu exemplo eu esqueci de colocar mas o stage tem que ser final:
final Stage stage = new Stage();
Acho que foi por isso que vc teve problemas. No primeiro exemplo que postei coloquei o stage como final.
Reply all
Reply to author
Forward
0 new messages