Abrir FXML em um Pane dentro da Scene principal

2 respostas
D

Olá Pessoal,

Estou desenvolvendo um projeto e tenho um client desktop em javaFX. A minha ideia é que ao clicar em um botão para abrir um formulário de cadastro ou para manipular alguma informação do sistema o fxml correspondente abra em um anchorpane no meio da janela mas sobreposto como se fosse um popup. A partir dai eu posso minimizar ele dentro da aplicação e abrir quando necessário, aplicar opacidade se necessário, etc.

sou novo no fórum e este é o meu primeiro post, não tenho muita experiência com fóruns espero não estar falando besteira rsrsrsrsrsrs

Segue abaixo o fonte fxml da minha página principal:
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.chart.*?>
<?import javafx.scene.canvas.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane maxHeight="606.0" maxWidth="600.0" minHeight="-Infinity" minWidth="200.0" prefHeight="600.0" prefWidth="1024.0" stylesheets="@../css/mac_os.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="presentation.DesktopClientPresentation">
   <padding>
      <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
   </padding>
   <children>
      <Circle fill="DODGERBLUE" layoutX="537.0" layoutY="153.0" radius="30.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fill="DODGERBLUE" layoutX="330.0" layoutY="441.0" radius="30.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fill="DODGERBLUE" layoutX="211.0" layoutY="471.0" radius="30.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fill="DODGERBLUE" layoutX="72.0" layoutY="441.0" onMouseClicked="#abrirCadProduto" radius="30.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fill="DODGERBLUE" layoutX="526.0" layoutY="526.0" radius="60.0" stroke="BLACK" strokeType="INSIDE" />
      <MenuBar layoutY="2.0" prefHeight="32.0" prefWidth="600.0">
        <menus>
          <Menu mnemonicParsing="false" text="File">
            <items>
              <MenuItem mnemonicParsing="false" text="Close" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Edit">
            <items>
              <MenuItem mnemonicParsing="false" text="Delete" />
            </items>
          </Menu>
          <Menu mnemonicParsing="false" text="Help">
            <items>
              <MenuItem mnemonicParsing="false" text="About" />
            </items>
          </Menu>
        </menus>
      </MenuBar>
      <AreaChart layoutX="49.0" layoutY="74.0" prefHeight="352.0" prefWidth="471.0" AnchorPane.bottomAnchor="184.0" AnchorPane.leftAnchor="39.0" AnchorPane.rightAnchor="90.0" AnchorPane.topAnchor="64.0">
        <xAxis>
          <CategoryAxis side="BOTTOM" />
        </xAxis>
        <yAxis>
          <NumberAxis side="LEFT" />
        </yAxis>
      </AreaChart>
      <Circle fill="DODGERBLUE" layoutX="450.0" layoutY="381.0" radius="30.0" stroke="BLACK" strokeType="INSIDE" />
      <Circle fill="DODGERBLUE" layoutX="507.0" layoutY="270.0" radius="30.0" stroke="BLACK" strokeType="INSIDE" />
   </children>
</AnchorPane>

Não me ocupei ainda com a parte de design mas é mais ou menos isso que vai ser, os CircleFills na página inicial terão no evento onClicked do mouse a chamada de método que abre o fxml correspondente dentro de um anchor pane no centro da janela. É ele que eu queria manipular com minimizar, mover, restaurar mas tudo dentro da janela principal sem sair do programa ou mudar o scene principal.

Segue abaixo o código controller:
public class DesktopClientPresentation implements Initializable{

    private Controller controller = new ClientController();

    @FXML private Button btnProduto,
                            btnLocalDeEstoque,
                            btnFornecedores,
                            btnMesas,
                            btnMovimentos;

    @FXML private AnchorPane paneCenter;
    private Scene scene;

    /**
     * Called to initialize a controller after its root element has been
     * completely processed.
     *
     * @param location  The location used to resolve relative paths for the root object, or
     *                  <tt>null</tt> if the location is not known.
     * @param resources The resources used to localize the root object, or <tt>null</tt> if
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    public void abrirCadProduto(Event event) throws IOException {

        System.out.println("Abrir Cadastro de Produtos: " + event);

        FXMLLoader fxmlLoader = new FXMLLoader();

        fxmlLoader.setLocation(ProdutosController.class.getResource("/fxml/produtos.fxml"));

        this.paneCenter = (AnchorPane) fxmlLoader.load();

        this.scene = new Scene(this.paneCenter);

    }
}
produtos.fxml
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>


<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <SplitPane dividerPositions="0.29797979797979796" layoutX="139.0" layoutY="30.0" prefHeight="300.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <items>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
               <children>
                  <TableView layoutX="-12.0" layoutY="41.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                    <columns>
                      <TableColumn prefWidth="21.0" text="ID" />
                      <TableColumn prefWidth="45.0" text="Descrição" />
                        <TableColumn prefWidth="70.0" text="Quantidade" />
                    </columns>
                     <columnResizePolicy>
                        <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
                     </columnResizePolicy>
                  </TableView>
               </children>
            </AnchorPane>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
               <children>
                  <HBox layoutX="107.0" layoutY="259.0" spacing="10.0">
                     <children>
                        <Button mnemonicParsing="false" text="Novo" />
                        <Button mnemonicParsing="false" text="Cancelar" />
                        <Button mnemonicParsing="false" text="Locais de Estoque" />
                        <Button mnemonicParsing="false" text="Salvar" />
                     </children>
                  </HBox>
                  <Label layoutX="14.0" layoutY="6.0" text="Detalhes do Produto" />
                  <TabPane layoutY="49.0" prefHeight="248.0" prefWidth="417.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="50.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="50.0">
                    <tabs>
                      <Tab text="Geral">
                        <content>
                          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
                        </content>
                      </Tab>
                      <Tab text="Estoque">
                        <content>
                          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                                 <children>
                                    <GridPane AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
                                       <columnConstraints>
                                          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                                          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                                          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                                          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                                       </columnConstraints>
                                       <rowConstraints>
                                          <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                                          <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
                                       </rowConstraints>
                                       <children>
                                          <Label layoutX="42.0" layoutY="70.0" text="Quantidade:" GridPane.rowIndex="1" />
                                          <HBox spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
                                             <children>
                                                <Label layoutX="123.0" layoutY="70.0" text="12" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                                                <Label layoutX="143.0" layoutY="70.0" text="un" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                                                <Label layoutX="174.0" layoutY="70.0" text="(1 cx)" GridPane.columnIndex="1" GridPane.rowIndex="1">
                                                   <HBox.margin>
                                                      <Insets />
                                                   </HBox.margin>
                                                </Label>
                                             </children>
                                          </HBox>
                                          <Label layoutX="14.0" layoutY="14.0" text="Local de Estoque:" />
                                          <SplitMenuButton layoutX="123.0" layoutY="10.0" mnemonicParsing="false" text="SplitMenuButton" GridPane.columnIndex="1">
                                            <items>
                                              <MenuItem mnemonicParsing="false" text="Action 1" />
                                              <MenuItem mnemonicParsing="false" text="Action 2" />
                                            </items>
                                          </SplitMenuButton>
                                       </children>
                                    </GridPane>
                                 </children>
                              </AnchorPane>
                        </content>
                      </Tab>
                    </tabs>
                  </TabPane>
               </children>
            </AnchorPane>
        </items>
      </SplitPane>
   </children>
</AnchorPane>
ProdutosController.java
package presentation;

import javafx.fxml.Initializable;

import java.net.URL;
import java.util.ResourceBundle;

/**
 * Created by Augusto on 08/05/2015.
 */
public class ProdutosController implements Initializable {
    /**
     * Called to initialize a controller after its root element has been
     * completely processed.
     *
     * @param location  The location used to resolve relative paths for the root object, or
     *                  <tt>null</tt> if the location is not known.
     * @param resources The resources used to localize the root object, or <tt>null</tt> if
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        System.out.println("Produtos");
    }
}

No controller do produtos.fxml eu apenas coloquei pra exibir uma mensagem no console me sinalizando que o mesmo foi inicializado. Apenas pra saber se deu certo...

Código da app principal

package view;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.net.URL;

/**
 * Created by Augusto on 24/04/2015.
 */
public class App extends Application{

    /**
     * The main entry point for all JavaFX applications.
     * The start method is called after the init method has returned,
     * and after the system is ready for the application to begin running.
     * <p/>
     * <p>
     * NOTE: This method is called on the JavaFX Application Thread.
     * </p>
     *
     * @param primaryStage the primary stage for this application, onto which
     *                     the application scene can be set. The primary stage will be embedded in
     *                     the browser if the application was launched as an applet.
     *                     Applications may create other stages, if needed, but they will not be
     *                     primary stages and will not be embedded in the browser.
     */
    @Override
    public void start(Stage primaryStage) throws Exception {

        Parent mainPane = FXMLLoader.load(getClass().getResource("/fxml/main.fxml"));
        Scene scene = new Scene(mainPane, 800, 600);
        primaryStage.setTitle("Projeto de Conclusão de Curso");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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


}

Eu tentei encontrar no google coisas como vários scenes em uma janela, fxml dentro de anchorpane entre outras coisas... meu inglês é bem pobre e sei que tem muito material em inglês de javafx e muitos de ótima qualidade mas to desenvolvendo ainda minha habilidade com inglês...

2 Respostas

Janerson

Bom, vamos lá!!!

Baixe a lib JFXtras https://oss.sonatype.org/content/repositories/snapshots/org/jfxtras/jfxtras-labs/8.0-r4-SNAPSHOT/jfxtras-labs-8.0-r4-20150707.080203-166.jar

Site do projeto: http://jfxtras.org

Adicione a lib ao seu Classpath

Agora vamos ao código(um tanto quanto tosco).

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import jfxtras.labs.scene.control.window.CloseIcon;
import jfxtras.labs.scene.control.window.MinimizeIcon;
import jfxtras.labs.scene.control.window.Window;



public class InnerWindow extends Application {

    private static int count = 1;

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button btn = new Button("New Window");
        AnchorPane anchorPane = new AnchorPane(btn);

        btn.setOnAction(a-&gt;{
            //Slider para controlar a opacidade da Janela(Window - JFXtras)
            Slider slider = new Slider(0,1,1);

            Text text = new Text();
            text.setText("Janela: " + count);
            text.setFill(Color.WHITE);
            text.setFont(Font.font(15));

            BorderPane borderPane = new BorderPane();
            borderPane.setCenter(text);
            borderPane.setBottom(slider);


            //Criando nossa janela
            Window window = new Window("Window: "+count);
            
            //Posicionado na tela
            window.setLayoutX(300);
            window.setLayoutY(150);
            
            //Definindo o tamanho
            window.setPrefSize(300, 300);
            
            //Add. icones close e minimize
            window.getLeftIcons().addAll(new CloseIcon(window));
            window.getRightIcons().addAll(new MinimizeIcon(window));
            
            //Add. o borderPane na Window
            window.getContentPane().getChildren().addAll(borderPane);
            
            //Fazendo o bind da opacidade com o slider
            window.opacityProperty().bind(slider.valueProperty());
            
            anchorPane.getChildren().addAll(window);
            count++;
        });

        primaryStage.setScene(new Scene(anchorPane, 800, 600));
        primaryStage.show();

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

}

No exemplo fiz tudo no código, mas você pode usar fxml para criar sua tela e setar esse fxml no Window

Repare na Window 2, o controle do Slider sobre a opacidade da Janela

L

Boa noite!

ao utilizar esse código, esta me dando um erro Window window = new Window("Window: "+count); o eclipse não esta reconhecendo esse comando!

Criado 8 de maio de 2015
Ultima resposta 16 de ago. de 2018
Respostas 2
Participantes 3