[RESOLVIDO] Navegação em JavaFX com FXML

6 respostas
A

Boa tarde, estou fazendo um projeto JavaFX com FXML e surgiu uma dúvida logo de cara e não encontrei no bendito google a resposta.
Eu usava JavaFX SEM fxml. E para executar o programa tinha que ter uma classe com o método main que dava o “launch” e a UI aparecia na minha frente.
Já com FXML essa classe não foi gerada. A dúvida é: Como faço para VER a UI ?
Outra dúvida é qual a melhor maneira de navegar entre as cenas? Após clicar num botão ele deve redirecionar para outra cena.

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<AnchorPane id="fundo" prefHeight="200.00009999999747" prefWidth="300.0000999999975" xmlns:fx="http://javafx.com/fxml" fx:controller="principalController">
  <children>
    <Label layoutX="14.0" layoutY="14.0" text="Selecione a opção desejada." textOverrun="ELLIPSIS" />
    <Button alignment="CENTER" layoutX="14.0" layoutY="52.0" mnemonicParsing="false" text="Cotações Futuras" textAlignment="LEFT" underline="false" visible="true" wrapText="false">
      <font>
        <Font size="12.0" fx:id="x1" />
      </font>
    </Button>
    <Button alignment="CENTER" font="$x1" layoutX="14.0" layoutY="82.0" mnemonicParsing="false" text="Cotações Físicas" textAlignment="LEFT" underline="false" visible="true" wrapText="false" />
    <Button alignment="CENTER" font="$x1" layoutX="14.0" layoutY="112.0" mnemonicParsing="false" text="Previsão do Tempo" textAlignment="LEFT" underline="false" visible="true" wrapText="false" />
    <Button alignment="CENTER" font="$x1" layoutX="14.0" layoutY="140.0" mnemonicParsing="false" text="Cortar Papel" textAlignment="LEFT" underline="false" visible="true" wrapText="false" />
    <ImageView id="ctv" layoutX="198.0" layoutY="124.0" pickOnBounds="true">
      <image>
        <Image url="@imagens/ctv.png" preserveRatio="true" smooth="true" />
      </image>
    </ImageView>
  </children>
  <stylesheets>
    <URL value="@estilo.css" />
  </stylesheets>
</AnchorPane>

6 Respostas

V

opa boa tarde,

então, para você identificar este FXML no seu código, você deve fazer duas etapas:

primeiro, deve criar a mesma Application, porém com uma pequena diferença...

public class MainApp extends Application {

	public static void main(String[] args) {
		launch(args);
	}

	@Override
	public void start(final Stage stage) throws Exception {
		Parent parent = FXMLLoader.load(getClass().getResource("main.fxml"));
		Scene scene = new Scene(parent);
		stage.setScene(scene);
		stage.show();
	}
}

Esse Parent é o que vai identificar seu FXML, através do FXMLLoader.load, agora o segundo passo é criar o seu Controller da tela. É uma outra classe implementada de uma Initializable. E seus componentes devem ter a Annotation @FXML para serem identificadas...

public class MainController implements Initializable {

	@FXML
	private Label lbTeste;
    @FXML
    private TextField txTeste;
    @FXML
    private Button btTestar;

	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
           btTestar.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
			      public void handle(ActionEvent arg0) {
				    // Ação do botão
			      }
           });
	}

}

Este método initialize é implementado do Initializable, e é nele que fica todas as ações dos componentes.
Pontos importantes: Aquele código "fx:controller=''" do seu FXML tem q ser EXATAMENTE o mesmo caminho e nome dessa classe Controller. E os componentes tem q ter o MESMO NOME, tanto em código, como no FXML.

Qualquer dúvida, é só dizer! :D

V

E para abrir outra cena, você instancia uma nova Application.

try {
    new SegundoApp().start(new Stage());
} catch (Exception e) {
    e.printStackTrace();
}

Se você precisa fechar a página anterior, então vc vai ter q criar uma variável Stage na sua Application, dar seu valor conforme o Stage do método start, para chamá-la no Controller.

public static Stage myStage;

/* Outros métodos... */

public void start(Stage stage) throws Exception {
    /* Outros códigos... */
    MainApp.myStage = stage;
}

Então, você usa o método close da Stage.

MainApp.myStage.close();

É isso aí! :D

A

Obrigado pela dica, ajudou muito.

Outra duvida:

Eu montei uma outra janela que cria checkbox através de um laço:

// * outras linhas *
 for(int j = 0; j < quotes.size() ;)
        {
            int cont = j+3;            
            for(int i = j ; i < cont ; i++){
                if(i < quotes.size()){
                    final int p = i;
                    final CheckBox cb = CheckBoxApoio.getCheckBox(quotes.get(i).getDESCRICAO()); // CRIA A CHECKBOX COM O TEXTO AO LADO
                    cb.setOnAction(new EventHandler<ActionEvent>() {

                        // EVENTO DE DESMARCAR E MARCAR A CHECKBOX
                        @Override
                        public void handle(ActionEvent event) {
                            if(cb.isSelected()){
                            selecionados.add(quotes.get(p));
                        }else{
                            selecionados.remove(quotes.get(p));
                        }
                       }
                    });
                    GridPane.setConstraints(cb, posX, posY); // DEFINE AS POSIÇÕES DA CHECKBOX
                    posX++;
                    grid.getChildren().add(cb);
                  }                
                }
            posX = 0;
            posY++;
            j = cont;
            }
//* outras linhas *

Logo essa página não está feita atraves do FXML, não consigo edita-la no Scene Builder, dificultando a criação da UI.
Queria saber se há como eu criar um FXML e manipular os botões que serão criados dinamicamente.
Obrigado!

V

Que bom que consegui ajudar =]

Então, se seu painel principal for indicado por FXML, se torna mais prático.

indicando com seu proprio painel de forma dinamica, e se necessário, coloque um ScrollPane, e indique o GridPane dentro do ScrollPane, para criar aquela barra de scroll conforme a criação do CheckBox.

private AnchorPane pane;

/* Demais códigos... */

for (int count = 0 ; count < 11 ; count++) {
    CheckBox chk = new CheckBox("teste" + String.valueOf(count));
    // Cria o Checkbox na posição Y conforme o "count" * a altura do componente
    // Por exemplo, 0 * 40 = 0 ; 1 * 40 = 40 ; 2 * 40 = 80, etc...
    chk.setLayoutY(count * chk.getPrefHeight()); 
    /* Demais códigos do Checkbox */
    pane.getChildren().add(chk);
}

Não sei se é bem isso que você esperava, mas acho que pode ajudar com a tática do ScrollPane...

Até mais! :D

A

Em relação a criação das CheckBox eu nao tive problemas, a minha dúvida é a manipulação delas pelo FXML, acho que não tem jeito de ‘montar’ essa tela atraves do FXML, pois ela necessita de dados que surgem a tempo de execução, entendeu?

Obrigado pela atenção, qualquer dúvida eu entro em contato novamente!

P

Muito boas as reposta!!!
vo compra seu livro XD

Criado 17 de janeiro de 2013
Ultima resposta 25 de jul. de 2014
Respostas 6
Participantes 3