Friday, August 10, 2018

Layouts no JavaFX (parte 1)

JavaFX é uma API Java para construir aplicações com recursos avançados de interface gráfica com o usuário que rodam em uma variedade de dispositivos, desktop, mobile ou web.

Os componentes ou controles de interface gráfica podem ser os mais variados, como figuras geométricas, botões, tabelas, editores de texto, imagens, etc. Antes de iniciar a construção de uma tela, você precisa saber como irá dispor esses componentes na tela. Componentes indevidamente alinhados podem aumentar a curva de aprendizado do software e isso não é desejável em nenhum sistema.

Layout Managers

A forma como os controles de interface estão dispostos na janela é chamada de layout. A classes do JavaFX que servem de container para os demais controles da tela são chamadas de layout managers
e os controles nela incluídos são chamados de filhos ou children, eles podem ser adicionados ou removidos do container a qualquer momento. O que diferencia cada layout manager do outro é a forma como ele expões os children. Nessa primeira parte analisamos 5 layout managers: FlowPane, BorderPane, HBox, VBox e StackPane. Todos do pacote javafx.scene.layout.

FlowPane

FlowPane deixa os controles flutuarem ou se auto-ajustarem de acordo com os limites da janela ou do container. Por defualt, havendo espaço, os controles vão sendo expostos horizontalmente. Abaixo um código de exemplo de um FlowPane com três botões e dois radio buttons.
    
package _01flow;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class Main extends Application {

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

 @Override
 public void start(Stage primaryStage) throws Exception {

  ExemploFlowPane exemplo = new ExemploFlowPane();
  
  Scene scene = new Scene(exemplo.flowPane);  
  primaryStage.setScene(scene);
  primaryStage.setTitle("Exemplo Flow Pane");  
  primaryStage.setWidth(300);
  primaryStage.setHeight(200);
  primaryStage.show();    
 }

 public class ExemploFlowPane {

  public FlowPane flowPane;
  
  public ExemploFlowPane() {

   Button left = new Button("left");
   Button center = new Button("center");
   Button right = new Button("right");
   ToggleGroup group = new ToggleGroup();
   RadioButton rd1 = new RadioButton("option 1");   
   RadioButton rd2 = new RadioButton("option 2");
   rd1.setToggleGroup(group);
   rd2.setToggleGroup(group);

   flowPane = new FlowPane(8,8);
   flowPane.setAlignment(Pos.CENTER);   
   flowPane.getChildren().addAll(left, center, rd1, rd2, right);
   
   left.setOnAction(e -> flowPane.setAlignment(Pos.CENTER_LEFT));
   center.setOnAction(e -> flowPane.setAlignment(Pos.CENTER));
   right.setOnAction(e -> flowPane.setAlignment(Pos.CENTER_RIGHT));  
  }
 }
}
    


Ao redimensionar a janela, os controles mudam a disposição

Com FlowPane, os componentes são realinhados a medida que o espaço se altera.

BoderPane

BorderPane é um layout divido em cinco regiões: Norte, Sul, Oeste, Centro e Leste:


Assim, você só pode inserir os componente em uma dessas regiões. O exemplo abaixo coloca um botão em cada uma das regiões. Em cada botão é registrado o evento de desaparecer quando clicado, deixando vazio o espaço que ele ocupa no BorderPane:
    
package _02borderPane;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Main extends Application {

 public static void main(String[] args) {
  launch(args);
 }
 
 @Override
 public void start(Stage primaryStage) throws Exception {
 
  ExempĺoBorderPane exemplo = new ExempĺoBorderPane();
  Scene scene = new Scene(exemplo.borderPane);  
  primaryStage.setScene(scene);
  primaryStage.setTitle("Exemplo Border Pane");  
  primaryStage.setWidth(500);
  primaryStage.setHeight(500);
  primaryStage.show(); 
 }
 
 public class ExempĺoBorderPane implements EventHandler{
  
  public BorderPane borderPane = new BorderPane();
  String[] names = {"Hide North", "Hide South", "Hide East", "Hide West", "Hide Center"};
  Button[] buttons = new Button[5];
    
  public ExempĺoBorderPane() {

   for(int i = 0; i < names.length; i++) {
    buttons[i] = new Button(names[i]);
    buttons[i].setOnAction(this);
    buttons[i].setMaxHeight(Double.MAX_VALUE);
    buttons[i].setMaxWidth(Double.MAX_VALUE);
   }
   borderPane.setTop(buttons[0]);
   borderPane.setLeft(buttons[3]);
   borderPane.setCenter(buttons[4]);
   borderPane.setRight(buttons[2]);
   borderPane.setBottom(buttons[1]);
  }

  @Override
  public void handle(ActionEvent event) {

   for(Button button : buttons) {
    
    if(event.getSource() == button)
     button.setVisible(false);
    else
     button.setVisible(true);
   }
  }
 }
}
    

O espaço central vazio

HBox


O Layout HBox alinha os controles em uma linha horizontal ilimitada. No exemplo a seguir o evento do botão vai adicionando novos botões no HBox inicialmente vazia:

package _03HBox;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Main extends Application{

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

 @Override
 public void start(Stage primaryStage) throws Exception {

  ExemploHBox exemplo = new ExemploHBox();
  Scene scene = new Scene(exemplo.root);  
  primaryStage.setScene(scene);
  primaryStage.setTitle("Exemplo HBox");  
  primaryStage.setWidth(800);
  primaryStage.setHeight(200);
  primaryStage.show();
 }
 
 public class ExemploHBox{
    
  public HBox hBox;
  public BorderPane root;
  Button add;
  
  public ExemploHBox() {
  
   hBox = new HBox(5);
   root = new BorderPane();
   add = new Button("Add to Box");
   add.setOnAction(e -> hBox.getChildren().add(new Button("new element")));   
   root.setBottom(add);
   root.setCenter(hBox);   
  }
 }
}    




VBox

O layout VBox é como o HBox, porém com alinhamento verttical dos controles. No exemplo anterior, susbtitua HBox por VBox e o resultado é o que segue:


StackPane

StackPane empilha os controles em uma estrutura LIFO (Last In First Out), último que entra é o primeiro que sai. Dessa forma o último controle inserido é o que fica no topo. Geralemtne no uso de StackPane somente controle no topo deve ficar visível. No exemplo abaixo empilhamos no StackPane todos os layouts criados anteriormente, de modo que só o que está no topo fica visível. O botão next dispara um evento que manda o primeiro elemento da pilha para o final, deixando o próximo visível:
    
package _05StackPane;

import _01flow.Main.ExemploFlowPane;
import _02borderPane.Main.ExempĺoBorderPane;
import _03HBox.Main.ExemploHBox;
import _04VBox.Main.ExemploVBox;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

 @Override
 public void start(Stage primaryStage) throws Exception {
  
  ExemploStackPane stackPane = new ExemploStackPane();
  Scene scene = new Scene(stackPane.boderPane);
  primaryStage.setScene(scene);
  primaryStage.setTitle("Stack Pane");
  primaryStage.setWidth(600);
  primaryStage.setHeight(600);
  primaryStage.show();
  
 }

 public static void main(String[] args) {
  // TODO Auto-generated method stub
  launch(args);
 }
 
 class ExemploStackPane{
  
  StackPane stackPane;
  BorderPane boderPane = new BorderPane();

  public ExemploStackPane() {
  
   stackPane = new StackPane();
   ExemploFlowPane exemploFlowPane = new _01flow.Main().new ExemploFlowPane();
   ExempĺoBorderPane exempĺoBorderPane = new _02borderPane.Main().new ExempĺoBorderPane();
   ExemploHBox exemploHBox = new _03HBox.Main().new ExemploHBox();
   ExemploVBox exemploVBox = new _04VBox.Main().new ExemploVBox();
   
   stackPane.getChildren().add(exemploFlowPane.flowPane);
   stackPane.getChildren().add(exempĺoBorderPane.borderPane);
   stackPane.getChildren().add(exemploHBox.root);
   stackPane.getChildren().add(exemploVBox.root);   
   
   stackPane.getChildren().forEach(node -> node.setVisible(false));
   
   Button button = new Button("next");
   button.setOnAction(e -> {
    ObservableList list = stackPane.getChildren();
    Node top = list.get(list.size() - 1);
    Node newTop = list.get(list.size() - 2);    
    top.setVisible(false);
    top.toBack();    
    newTop.setVisible(true);    
   });
   
   boderPane.setCenter(stackPane);
   boderPane.setBottom(button);
  } 
 }
}
    



Na segunda parte deste post, analisamos o AnchorPane, GridPane, TilePane e BorderImage.

       

No comments:

Post a Comment