[RESOLVIDO] Navegação em JavaFX com FXML

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>

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…

[code]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();
}

}[/code]

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…

[code]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
		      }
       });
}

}[/code]

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! :smiley:

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.

[code]public static Stage myStage;

/* Outros métodos… */

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

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

É isso aí! :smiley:

Obrigado pela dica, ajudou muito.

Outra duvida:

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

[code] // * outras linhas *
for(int j = 0; j < quotes.size() :wink:
{
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() {

                    // 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 *[/code]

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!

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.

[code] 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);
}
[/code]

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

Até mais! :smiley:

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!

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