Como posso passar parâmetros para uma janela secundária em javafx? Existe uma maneira de se comunicar com o controlador correspondente?
Por exemplo: O usuário escolhe um cliente de uma TableView
e uma nova janela é aberta, mostrando as informações do cliente.
Stage newStage = new Stage();
try
{
AnchorPane page = (AnchorPane) FXMLLoader.load(HectorGestion.class.getResource(fxmlResource));
Scene scene = new Scene(page);
newStage.setScene(scene);
newStage.setTitle(windowTitle);
newStage.setResizable(isResizable);
if(showRightAway)
{
newStage.show();
}
}
newStage
seria a nova janela. O problema é que não consigo encontrar uma maneira de informar ao controlador onde procurar as informações do cliente (passando o id como parâmetro).
Alguma ideia?
Respostas:
Abordagem recomendada
Esta resposta enumera diferentes mecanismos para passar parâmetros para controladores FXML.
Para pequenas aplicações, eu recomendo passar parâmetros diretamente do chamador para o controlador - é simples, direto e não requer estruturas extras.
Para aplicativos maiores e mais complicados, vale a pena investigar se você deseja usar os mecanismos de Injeção de Dependência ou Barramento de Eventos em seu aplicativo.
Passando parâmetros diretamente do chamador para o controlador
Passe dados customizados para um controlador FXML, recuperando o controlador da instância do carregador FXML e chamando um método no controlador para inicializá-lo com os valores de dados necessários.
Algo como o seguinte código:
Um novo FXMLLoader é construído como mostrado no código de exemplo, ie
new FXMLLoader(location)
. O local é um URL e você pode gerar esse URL a partir de um recurso FXML:Cuidado para NÃO usar uma função de carga estática no FXMLLoader, ou você não poderá obter seu controlador da instância do carregador.
As instâncias FXMLLoader nunca sabem nada sobre objetos de domínio. Você não passa diretamente objetos de domínio específicos do aplicativo para o construtor FXMLLoader; em vez disso, você:
Este blog (por outro escritor) fornece uma alternativa, mas semelhante, exemplo .
Configurando um controlador no FXMLLoader
Você pode construir um novo controlador no código, passando os parâmetros desejados do seu chamador para o construtor do controlador. Depois de criar um controlador, você pode configurá-lo em uma instância FXMLLoader antes de chamar o método de
load()
instância .Para definir um controlador em um carregador (no JavaFX 2.x), você NÃO PODE definir um
fx:controller
atributo no seu arquivo fxml.Devido à limitação da
fx:controller
definição no FXML, eu pessoalmente prefiro obter o controlador do FXMLLoader do que configurá-lo no FXMLLoader.Como o controlador recuperar parâmetros de um método estático externo
Este método é exemplificado pela resposta de Sergey ao Javafx 2.0 How-to Application.getParameters () em um arquivo Controller.java .
Usar injeção de dependência
O FXMLLoader suporta sistemas de injeção de dependência como Guice, Spring ou Java EE CDI, permitindo que você defina uma fábrica de controladores personalizados no FXMLLoader. Isso fornece um retorno de chamada que você pode usar para criar a instância do controlador com valores dependentes injetados pelo respectivo sistema de injeção de dependência.
Um exemplo de injeção de dependência de aplicativo e controlador JavaFX com Spring é fornecido na resposta para:
Uma abordagem realmente agradável e limpa de injeção de dependência é exemplificada pela estrutura afterburner.fx com um exemplo de aplicativo de air-hacks que a utiliza. O afterburner.fx depende do JEE6 javax.inject para executar a injeção de dependência.
Use um barramento de eventos
Greg Brown, o criador e implementador original da especificação FXML, geralmente sugere considerar o uso de um barramento de eventos, como o Guava EventBus , para comunicação entre controladores instanciados FXML e outra lógica de aplicativo.
Perguntas e Respostas de acompanhamento
É uma solução funcional para um problema. Um estágio é retornado da
showCustomerDialog
função para que uma referência a ele possa ser armazenada por uma classe externa que deseje fazer algo, como ocultar o estágio com base em um clique no botão na janela principal, posteriormente. Uma solução alternativa orientada a objeto pode encapsular a funcionalidade e a referência de estágio dentro de um objeto CustomerDialog ou fazer com que um CustomerDialog estenda o Stage. Um exemplo completo de uma interface orientada a objetos para uma caixa de diálogo personalizada que encapsula dados de FXML, controlador e modelo está além do escopo desta resposta, mas pode fazer uma publicação interessante no blog para qualquer pessoa que queira criar uma.Informações adicionais fornecidas pelo usuário StackOverflow chamado @dzim
Exemplo de injeção de dependência de inicialização de primavera
A questão de como fazê-lo "The Spring Boot Way", houve uma discussão sobre JavaFX 2, que eu respondi no link permanente em anexo. A abordagem ainda é válida e testada em março de 2016, no Spring Boot v1.3.3.RELEASE: https://stackoverflow.com/a/36310391/1281217
Às vezes, convém passar os resultados de volta para o chamador, nesse caso, você pode conferir a resposta para a pergunta relacionada:
fonte
Neste exemplo, usaremos 5 arquivos:
Todos os arquivos estão listados na íntegra na parte inferior desta postagem.
O Objectivo: Para demonstrar que passa valores de
Controller1
aController2
e vice-versa.O fluxo do programa:
TextField
, aButton
e aLabel
. QuandoButton
clica em, a segunda janela é carregada e exibida, incluindo o texto digitado noTextField
.TextField
, aButton
e aLabel
. OLabel
irá exibir o texto inserido noTextField
na primeira cena.TextField
e clicar nelaButton
, a primeira cenaLabel
é atualizada para mostrar o texto inserido.Esta é uma demonstração muito simples e certamente pode significar alguma melhoria, mas deve tornar o conceito muito claro.
O código em si também é comentado com alguns detalhes do que está acontecendo e como.
Main.java:
Controller1.java:
Controller2.java:
Layout1.fxml:
Layout2.fxml:
fonte
loader.setController(this)
e adicionar o controlador no arquivo FXML trava o aplicativoloader.getController()
A classe javafx.scene.Node possui um par de métodos setUserData (Object) e Object getUserData ()
Que você pode usar para adicionar suas informações ao nó.
Então, você pode chamar page.setUserData (info);
E o controlador pode verificar se as informações estão definidas. Além disso, você pode usar o ObjectProperty para transferência de dados de retrocesso, se necessário.
Observe uma documentação aqui: http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html Antes da frase "Na primeira versão, o handleButtonAction () é marcado com @FXML para permitir que a marcação definida no documento do controlador a invoque. No segundo exemplo, o campo do botão é anotado para permitir que o carregador defina seu valor. O método initialize () é anotado da mesma forma. "
Portanto, você precisa associar um controlador a um nó e configurar os dados do usuário para o nó.
fonte
Aqui está um exemplo para passar parâmetros para um documento fxml através do namespace.
Defina o valor
External Text
para a variável de espaço para nomelabelText
:fonte
FXMLLoader.CONTROLLER_KEYWORD
,FXMLLoader.LOCATION_KEY
,FXMLLoader.RESOURCES_KEY
e qualquer seqüência usado como valor para ofx:id
atributo.Isso funciona ..
Lembre-se da primeira vez que imprimir o valor que passa, você será nulo. Você pode usá-lo após o carregamento do Windows, o mesmo para tudo o que você deseja codificar para qualquer outro componente.
fonte
Você precisa criar uma classe de contexto.
Você precisa apenas definir a instância do controlador na inicialização usando
e você pode usá-lo em todo o aplicativo usando apenas
Agora você pode passar parâmetros para qualquer controlador de todo o aplicativo.
fonte
Sim você pode.
Você precisa adicionar o primeiro controlador:
Em seguida, no segundo, declare um cliente e, em seguida, na parte inferior do seu controlador:
fonte
Aqui está um exemplo para usar um controlador injetado pelo Guice.
Aqui está uma implementação concreta do carregador:
Observe que este exemplo carrega a vista no centro de um BoarderPane que é a raiz da cena no palco. Isso é irrelevante para o exemplo (detalhes de implementação do meu caso de uso específico), mas decidiu deixá-lo como alguns podem achar útil.
fonte
Você pode optar por usar uma lista pública observável para armazenar dados públicos ou apenas criar um método setter público para armazenar dados e recuperar do controlador correspondente
fonte
Por que responder a uma pergunta de 6 anos?
Um dos conceitos mais fundamentais do trabalho com qualquer linguagem de programação é como navegar de um (janela, formulário ou página) para outro. Além disso, ao fazer essa navegação, o desenvolvedor geralmente deseja passar dados de uma (janela, formulário ou página) e exibir ou usar os dados transmitidos.
Embora a maioria das respostas aqui forneça exemplos bons ou excelentes de como fazer isso, pensamos que seria necessário aumentá-los. um ponto ou dois ou três
Dissemos três porque navegaremos entre três (janela, formulário ou página) e usaremos o conceito de variáveis estáticas para passar dados (janela, formulário ou página)
. Também incluiremos algum código de tomada de decisão enquanto nós navegamos
Iniciar controlador
Controlador Page One
Controlador da página dois
Abaixo estão todos os arquivos FXML
fonte