Tag: javafx

JavaFX, exercício 3.1

package recursopa;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import recursopa.iu.gui.PaneOrganizer;

public class RecursoPA extends Application {
    public static void main(String[] args) {
        //passamos os argumentos para o subsistema gráfico os parametros
        launch(args); 
    }
 
    @Override
    //quando começa a aplicação
    public void start(Stage stage) throws Exception{
        PaneOrganizer po = new PaneOrganizer();
        Scene scene = new Scene(po,600,400);
        stage.setScene(scene); //aplica a cena no stage
        stage.setTitle("Exercicio de programação avançada");
        stage.setMinHeight(300.0);
        stage.setMinWidth(300.0);
        stage.show();
    }
}   
package recursopa.iu.gui;

import javafx.event.EventHandler;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import recursopa.logica.Desenho;
import recursopa.logica.Figura;

public class AreaDesenho extends Canvas {

    Desenho desenho;

    public AreaDesenho(Desenho desenho) {
        super(100.0, 100.0);
        this.desenho = desenho;
    }

    public void registaListeners() {
        //detectar as ações do rato
        this.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent t) {
                desenho.iniciaFigura((int) t.getX(),
                        (int) t.getY(),
                        (int) (Math.random() * 256),
                        (int) (Math.random() * 256),
                        (int) (Math.random() * 256)
                );
                atualiza();
            }
        });

        //usando lambda functions
        this.setOnMouseReleased((t) -> {
            desenho.atualizaFigura((int) t.getX(), (int) t.getY());
            atualiza();
        });
        this.setOnMouseDragged((t) -> {
            desenho.finalizaFigura((int) t.getX(), (int) t.getY());
            atualiza();
        });

    }

    void apagarCanvas(GraphicsContext gc) {
        gc.setFill(Color.rgb(233, 233, 0));
        gc.fillRect(0, 0, getWidth(), getHeight());
    }

    //para desenhar as figuras
    void atualiza() {
        //obter as ferramentas de desenho
        GraphicsContext gc = getGraphicsContext2D();
        apagarCanvas(gc);

        //rir buscar todas as figuras
        for (Figura fig : desenho.getListaFiguras()) {
            //fazer as operações sobre o GraphicsContext
            Color cor = Color.rgb(fig.getR(), fig.getG(), fig.getB());
            gc.setFill(cor);
            gc.fillOval(fig.getXi(), fig.getYi(), fig.getLargura(), fig.getAltura());
        }

        //desenhar a figura actual
        Figura figura = desenho.getActual();
        if (figura != null){
            Color cor = Color.rgb(figura.getR(), figura.getG(), figura.getB());
            gc.setFill(cor);
            gc.fillOval(figura.getXi(), figura.getYi(), figura.getLargura(), figura.getAltura());
        }

    }

    public void setDim(int w, int h) {
        setWidth(w);
        setHeight(h);
        atualiza();
    }

}

package recursopa.iu.gui;

import javafx.scene.layout.Pane;
import recursopa.logica.Desenho;

public class PaneOrganizer extends Pane {
    //vai extender sempre um dos containers possiveis,  extends Pane
    Desenho desenho;
    //Canvas canvas; //é uma zona de desenho
    AreaDesenho areaDesenho;

    public PaneOrganizer() {
        desenho = new Desenho();

        criaLayout(); //para criar os componentes que vão surgir no ecrã
        registaListeners(); // registar os comportamentos dos objectos

    }

    
    void criaLayout() {
        //adicionar o elemento ao Pane
        areaDesenho = new AreaDesenho(desenho);
        this.getChildren().add(areaDesenho);
    }

    private void registaListeners() {
        areaDesenho.registaListeners();
        
        this.widthProperty().addListener((e) -> {
            areaDesenho.setDim((int)PaneOrganizer.this.getWidth(), (int)PaneOrganizer.this.getHeight());
        });
        this.heightProperty().addListener((e) -> {
            areaDesenho.setDim((int)PaneOrganizer.this.getWidth(), (int)PaneOrganizer.this.getHeight());
        });
    }
}

package recursopa.logica;

import java.util.ArrayList;
import java.util.List;

public class Desenho {

    //para um conjunto de figuras, que ser´auma lista de figuras
    List<Figura> listaDeFiguras;
    Figura figuraAtual;

    public Desenho() {
        listaDeFiguras = new ArrayList<>();
    }

    public void iniciaFigura(int x, int y, int r, int g, int b) {
        figuraAtual = new Figura();
        figuraAtual.setRGB(r, g, b);
        figuraAtual.setPrimeiroPonto(x, y);
        figuraAtual.setSegundoPonto(x, y);
    }

    public void atualizaFigura(int x, int y) {
        if (figuraAtual != null) {
            figuraAtual.setSegundoPonto(x, y); //atualizar o segundo ponto
        }
    }

    public void finalizaFigura(int x, int y) {
        //para terminar a figura
        if(figuraAtual != null && listaDeFiguras !=null){
            listaDeFiguras.add(figuraAtual);
            figuraAtual = null;
        }
    }
    public Figura getActual(){
        return figuraAtual;
    }
    
    public List<Figura> getListaFiguras(){
        return listaDeFiguras;
    }
}

package recursopa.logica;

public class Figura {
//métodos necessários para gerir a figura

    int xi, yi, xf, yf; //posicao e tamanho
    int r, g, b; //para a cor

    public Figura() {

    }

    public int getXi() {
        return xi < xf ? xi : xf;
    }

    public int getYi() {
        return yi < yf ? yi : yf;
    }

    public int getXf() {
        return xf < xi ? xf : xi;
    }

    public int getYf() {
        return yf < yi ? yf : yi;
    }

    public int getR() {
        return r;
    }

    public int getG() {
        return g;
    }

    public int getB() {
        return b;
    }

    public void setRGB(int r, int g, int b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    public void setPrimeiroPonto(int x, int y) {
        this.xi = x;
        this.yi = y;
    }

    public void setSegundoPonto(int x, int y) {
        this.xf = x;
        this.yf = y;
    }

    public int getLargura() {
        return Math.abs(xf - xi); //não interessa a ordem dos valores
    }

    public int getAltura() {
        return Math.abs(yf - yi); //não interessa a ordem dos valores
    }
}

Tags : ,

exercício javaFx

Tópicos: máquina de estados, interface gráfica, threads,

o diagrama da máquina de estados:

o projeto:

o código:

package jfxsomajogo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import jfxsomajogo.modelo.SomaJogoObs;
import jfxsomajogo.ui.SomaUI;

public class JFXSomaJogo extends Application {

    public static void main(String[] args) {
        launch(args);;
    }
    
    @Override
    public void start(Stage primaryStage){
        primaryStage.setTitle("Acereta nos números");
        SomaJogoObs a = new SomaJogoObs();
        SomaUI ui = new SomaUI(a);
        Scene scene = new Scene(ui, 300,250);
        primaryStage.setScene(scene);
        primaryStage.show();
     
        //que serve para fechar a janela
        primaryStage.setOnHidden((WindowEvent event) -> {
            a.paraRelogio();
        });
    }
    
}
package jfxsomajogo.fsm;

import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.modelo.SomaDados;

public class AguardaNomeJogador extends SomaFSMAdapter {

    public AguardaNomeJogador(SomaDados dados) {
        super(dados);
    }

    //transição
    @Override
    public ISomaFSM defineJogador(String nome) {
        dados.defineNomeJogador(nome);
        if (dados.jogadorValido()) {
            dados.reset(); //iniciação do jogo
            return new AguardaResposta(dados); //novo estado
        }else{
            return this;
        }
    }

    //cada um retorna o seu próprio identicador
    //para evitar o uso do instanceof e o get class
    @Override
    public EstadoID obtemEstadoID() {
        return EstadoID.AGUARDA_NOME;
    }

}

package jfxsomajogo.fsm;

import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.modelo.SomaDados;

public class AguardaReinicio extends SomaFSMAdapter {

    public AguardaReinicio(SomaDados dados) {
        super(dados);
    }

    //este estado é basicamente, um "press any key to conitnue"
    @Override
    public ISomaFSM recomeca() {
        return new AguardaNomeJogador(dados);
    }

    @Override
    public EstadoID obtemEstadoID() {
        return EstadoID.AGUARDA_REINICIO;
    }
}

package jfxsomajogo.fsm;

import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.modelo.SomaDados;

public class AguardaResposta extends SomaFSMAdapter{

    AguardaResposta(SomaDados dados) {
        super(dados);
    }

    @Override
    public ISomaFSM tentaResposta(int n) {
        dados.tentaResposta(n);
        if(dados.excedeuErros()){
            return new AguardaReinicio(dados); //muda de estado
        }else{
            return this; //fica no mesmo estado
            //return new AguardaResposta(dados); //alternativa, mostramos evolução do estado
        }
    }
    
    @Override
    public ISomaFSM relogioAvanca() {
        dados.diminuiCountDown();
        if(dados.excedeuErros()){
            return new AguardaReinicio(dados);
        }else{
            return this;
        }
    }

    @Override
    public EstadoID obtemEstadoID(){
        return EstadoID.AGUARDA_RESPOSTA; //para evitar o instance of
    }
}

package jfxsomajogo.fsm;

import java.io.Serializable;
import jfxsomajogo.integracao.EstadoID;

public interface ISomaFSM extends Serializable{
    //vai servir para definir um estado, transições:
    default ISomaFSM defineJogador(String nome){return this;} 
    //implementação default, pode ser no Adpater
    default ISomaFSM tentaResposta(int n){return this;}
    default ISomaFSM recomeca(){return this;}
    default ISomaFSM relogioAvanca(){return this;}
    EstadoID obtemEstadoID(); //retorna um ID
    
    //default, permite a implementação default mas devia ser no adaptar e não aqui.
    //mudar no final para ver como fica
}

package jfxsomajogo.fsm;

import jfxsomajogo.modelo.SomaDados;

public abstract class SomaFSMAdapter implements ISomaFSM{
    //guarda a referencia para o modelo de dados
    protected final SomaDados dados;
    //protected para os outros estados poderem aceder à informação
    
    protected SomaFSMAdapter(SomaDados dados){
        this.dados = dados;
    }
    
    //public AdividnhaDados obtemDados(){return dados;}
    //usa-se protected para isto
    
    //implementações de default de cada um dos métodos de 
    
}


package jfxsomajogo.integracao;
//isto é um package que vai ser usado pelo modelo de dados e pela interface


import jfxsomajogo.fsm.AguardaReinicio;

public enum EstadoID {
    //os ID dos estados
    AGUARDA_NOME, AGUARDA_RESPOSTA, AGUARDA_REINICIO
}

//este package agrupa as enumerações e constantes relacioandos com
//integração entre vários módulos da aplicação
//assim, a UD nao tem que improtar coisas dos packages de dados ou FSM
package jfxsomajogo.integracao;
//isto é um package que vai ser usado pelo modelo de dados e pela interface

public enum MsgCode {
    START, RIGHT, WRONG, TIMEOUT
}

package jfxsomajogo.integracao;
//isto é um package que vai ser usado pelo modelo de dados e pela interface

public enum PropsID {
    
    //podiam ser usadas constantes
    //"" -> alteração gráfica
    PROP_ESTADO("prop_estado"),
    PROP_DESAFIO("prop_desafio"),
    PROP_RELOGIO("prop_relogio");
    
    String valor;

    private PropsID(String v) {
        this.valor = v;
    }

    @Override
    public String toString() {
        return valor;
    }
}

package jfxsomajogo.modelo;

import java.io.Serializable;
import java.util.Random;
import jfxsomajogo.integracao.MsgCode;

public class SomaDados implements Serializable {

    private static final int COUNTDOWN_TIMEOUT = 10;
    private static final int MAX_ERROS = 3;
    private static final int MIN_VALOR = 1;
    private static final int MAX_VALOR = 100;

    private String jogador = "X";
    private MsgCode msg; //ver o estado actual
    private int pontuacao, erros;
    private int numA, numB;
    private int countdown;
    Random rand;

    SomaDados() {
        rand = new Random();
        jogador = "X";
        msg = MsgCode.START;
        pontuacao = erros = numA = numB = -1;
        countdown = -1;

    }

    public final void reset() {
        pontuacao = 0;
        erros = 0;
        novoDesafio();
        msg = MsgCode.START;
    }

    public void defineNomeJogador(String nome) {
        jogador = nome;
    }

    public void novoDesafio() {
        numA = rand.nextInt(MAX_VALOR - MIN_VALOR + 1) + MIN_VALOR;
        numB = rand.nextInt(MAX_VALOR - MIN_VALOR + 1) + MIN_VALOR;
        resetCountDown();
    }

    public void diminuiCountDown() {
        --countdown;
        if (countdown <= 0) {
            msg = MsgCode.TIMEOUT;
            erros++;
            novoDesafio();
        }
    }

    public void tentaResposta(int resp) {
        if (resp == (numA + numB)) {
            pontuacao++;
            msg = MsgCode.RIGHT;
            novoDesafio();
        } else {
            erros++;
            msg = MsgCode.WRONG;
        }
    }

    //para ver a evolução dos estados
    public boolean jogadorValido() {
        //se indicar o nome, pode ir para jogar
        return jogador != null && jogador.length() > 0;
    }

    public boolean excedeuErros() {
        return erros >= MAX_ERROS;
    }

    //obtem info para o ecrã
    public String obtemNomeJogador() {
        return jogador;
    }

    public int obtemNumA() {
        return numA;
    }

    public int obtemNumB() {
        return numB;
    }

    public int obtemPontuacao() {
        return pontuacao;
    }

    public int obtemErros() {
        return erros;
    }

    public int obtemCountDown() {
        return countdown;
    }

    public MsgCode obtemMsg() {
        return msg;
    }

    private void resetCountDown() {
        countdown = COUNTDOWN_TIMEOUT;
    }
}

package jfxsomajogo.modelo;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import jfxsomajogo.fsm.AguardaNomeJogador;
import jfxsomajogo.fsm.ISomaFSM;
import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.integracao.MsgCode;
import jfxsomajogo.integracao.PropsID;

//esta é a classe "contexto" da máquina de estados
//tem a máquina de estados + dados
//máquina de estados
public class SomaJogo implements Serializable {

    private final SomaDados dados = new SomaDados(); //criar o modelo de dados
    private ISomaFSM estado = null;  //define o estado incial

    public SomaJogo() {
        estado = new AguardaNomeJogador(dados);
    }

    //defineEstado recebe o próximoe stado
    private Set<PropsID> defineEstado(ISomaFSM prox, PropsID... eventosBase) {
        //isto vai ajudar no observable, vai avisar a vista
        Set<PropsID> eventos = new HashSet<>(Set.of(eventosBase));
        ISomaFSM anterior = estado;
        estado = prox;
        if (anterior != prox) {
            eventos.add(PropsID.PROP_ESTADO);
        }
        return eventos;
    }

    //operação do sistema ("dispositivo") contexto da FSM
    //-> reencaminha para FSM
    //os métodos que permitem a transição de estados
    //ponte entre o estado, o modelo de estados e a vista
    public Set<PropsID> defineJogador(String nome) {
        //ao inves de retornar o estado pode ser um return de boolean
        //retornar Set<PropsID>, um conjunto de situações de jogo que ajuda na vista do jogo
        //para a parte gráfica
        return defineEstado(estado.defineJogador(nome));
    }

    public Set<PropsID> tentaResposta(int n) {
        return defineEstado(estado.tentaResposta(n), PropsID.PROP_DESAFIO);
        //estas duas significa que podem acontecer dois eventos, e disparar o fire de uma das duas
    }

    public Set<PropsID> recomeca() {
        return defineEstado(estado.recomeca());
    }

    public Set<PropsID> relogioAvanca() {
        return defineEstado(estado.relogioAvanca(), PropsID.PROP_RELOGIO, PropsID.PROP_DESAFIO);
    }

       
    public EstadoID obtemEstadoID() {
        return estado.obtemEstadoID();
    }

    //obtenção de dados para uso nas UI
    //informação relevanta para mostrar ao utilizador
    //-> reencaminha para dados
    
    //isto é o mesmo que os gets apenas traudizdo para obtem
    //para serem mostrados no UI do utilziador
    
    public String obtemNomeJogador() {
        return dados.obtemNomeJogador();
    }

    public int obtemNumA() {
        return dados.obtemNumA();
    }

    public int obtemNumB() {
        return dados.obtemNumB();
    }

    public int obtemPontuacao() {
        return dados.obtemPontuacao();
    }

    public int obtemErros() {
        return dados.obtemErros();
    }

    public MsgCode obtemMsg() {
        return dados.obtemMsg();
    }

    public int obtemCountDown() {
        return dados.obtemCountDown();
    }
    
    //não devemos retornar o modelo SomaDados todo
    //porque se o fizermos vamos dar hipotese a quem faz
    //a vista de alterar os dados

}

package jfxsomajogo.modelo;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.integracao.MsgCode;
import jfxsomajogo.integracao.PropsID;

//missao principal - adicionar o suporte para ligacao a vistas
// = property change support
//mantem a ligacao separada do contexto da FGSM e dados
//permite save/load a FSM+dados sem dependencia (referencia) a vistas
//adiciona save/load neste nivel e age sobre o modelo (contexto da FSM)
public class SomaJogoObs {

    //os propertir change support
    SomaJogo jogo = null; //a referencia para o jogo, maquina de estados
    private PropertyChangeSupport props = null;

    private final Timer relogio;
    private final Temporizador segundos;

    public SomaJogoObs() {
        jogo = new SomaJogo();
        props = new PropertyChangeSupport(jogo);

        relogio = new Timer();
        segundos = new Temporizador();
        relogio.schedule(segundos, 0, 1000);
    }

    //registar o interesse das vistas, quando uma determinada propriedade for alterada
    //
    public void registaPropertyChangeListener(PropsID prop, PropertyChangeListener listener) {
        props.addPropertyChangeListener(prop.toString(), listener);
    }

    private void disparaEventos(Set<PropsID> eventos) {
        for (var e : eventos) {
            props.firePropertyChange(e.toString(), null, null);
        }

        //alternaiva ao for
        //eventos.forEach((e) -> {
        //props.firePropertyChange(e.toString(), null, null);
        //});
    }

    public void paraRelogio() {
        segundos.cancel();
        relogio.purge(); //eliminar todas as as timer text 
        relogio.cancel();
    }

    // inicio: métodos que fazem a ponte entre as vistas e a maquina de estados
    public void relogioAvanca() {
        disparaEventos(jogo.relogioAvanca());
    }

    // operação do sistema ("dispotivo") - reencaminha para jogo depois p/ FSM
    public void defineJogador(String nome) {
        disparaEventos(jogo.defineJogador(nome));
    }

    public void tentaResposta(int n) {
        disparaEventos(jogo.tentaResposta(n));

        //alternaiva ao udo do disparaEventos
        //jogo.tentaResposta(n);
        //props.firePropertyChange(PropsID.PROP_DESAFIO, null. null);
        //props.firePropertyChange(PropsID.PROP_ESTADO, null. null);
    }

    public void recomeca() {
        disparaEventos(jogo.recomeca());
    }

    public EstadoID obtemEstadoID() {
        return jogo.obtemEstadoID();
    }
    //fim: métodos que fazem a ponte entre as vistas e a maquina de estados

    //obenção de dados para uso das UI - reencaminha p/jogo (depois para dados)
    public String obtemNomeJogador() {
        return jogo.obtemNomeJogador();
    }

    public int obtemNumA() {
        return jogo.obtemNumA();
    }

    public int obtemNumB() {
        return jogo.obtemNumB();
    }

    public int obtemPontuacao() {
        return jogo.obtemPontuacao();
    }

    public int obtemErros() {
        return jogo.obtemErros();
    }

    public MsgCode obtemMSG() {
        return jogo.obtemMsg();
    }

    public int obtemCountDown() {
        return jogo.obtemCountDown();
    }

    //load/save
    public void saveGame(String filename) {
        ObjectOutputStream out;
        try {
            out = new ObjectOutputStream(new FileOutputStream(filename));
            out.writeObject(jogo);
            out.close();
        } catch (IOException e) {
            Logger.getLogger(SomaJogoObs.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    public void loadGame(String filename) {
        ObjectInputStream in;
        try {
            in = new ObjectInputStream(new FileInputStream(filename));
            jogo = (SomaJogo) in.readObject();
            in.close();
            props.firePropertyChange(PropsID.PROP_ESTADO.toString(), null, null);
        } catch (IOException | ClassNotFoundException e) {
            Logger.getLogger(SomaJogoObs.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    //time taks
    class Temporizador extends TimerTask {
        @Override
        public void run() {
            relogioAvanca();
        }
    }
}

package jfxsomajogo.ui;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.integracao.MsgCode;
import jfxsomajogo.integracao.PropsID;
import jfxsomajogo.modelo.SomaJogoObs;


//esta é uma classe genérica, que é um adpater para PropertyChangeListener
//PropertyChangeListenerJFXAdapter faz com que seja implementado o PropertyChangeListener
//vai implementar o propertyChange, que é o método obrigatório pelo inteface método PropertyChangeListener
//e sempre que ele for chamado, e antes de correr o código pretendido ele faz um  
// Platform.runLater(() do método onChange(evt);
// e quanto ele for corrido ele já foi corrido no contexto do .runLater(()
//com o objecto qd é criado é abstracto 
//por exemplo propsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() 
//sou obrigado a implementar o onChange(), com todo o código necessário
//para as alterações que eu necessito 
//e assim o onChange() já foi executado na thread do javaFX
//evito assim que estoire, e que acontece quanto tentamos executar código a partir de uma thread
//difernte da que está responsavel por fazer a gestão dos componentes gráficos
//isto por causa da utilização do timer, porque o timer está numa thread à parte


abstract class PropertyChangeListenerJFXAdapter implements PropertyChangeListener{
    @Override
    public final void propertyChange(PropertyChangeEvent evt){
        Platform.runLater(()->{
            onChange(evt);
        });
    }
abstract public void onChange(PropertyChangeEvent evt);
}


public class SomaUI extends BorderPane {

    SomaJogoObs adivObs;

    public SomaUI(SomaJogoObs a) {
        adivObs = a;
        FileChooser fileChooser = new FileChooser();

        //esta funcao esta extensa. passar código para funcções auxiliares
        //implica passar as refs locais dos componentes para a classe
        //cria componentes
        //menu
        MenuBar menuBar = new MenuBar();

        Menu fileMenu = new Menu("file");
        MenuItem fileNew = new MenuItem("new");
        MenuItem fileSave = new MenuItem("save");
        MenuItem fileLoad = new MenuItem("load");
        MenuItem fileExit = new MenuItem("exit");
        fileMenu.getItems().addAll(fileNew, fileSave, fileLoad, fileExit);

        Menu aboutMenu = new Menu("about");
        MenuItem aboutInfo = new MenuItem("info");
        aboutMenu.getItems().addAll(aboutInfo);

        menuBar.getMenus().addAll(fileMenu, aboutMenu);
        setTop(menuBar);

        //eventos para os menus
        //file->new
        fileNew.setOnAction((ActionEvent e) -> {
            adivObs.recomeca();
        });
        //file-> save
        fileSave.setOnAction((ActionEvent e) -> {
            File f = fileChooser.showSaveDialog(getScene().getWindow());
            if (f != null) {
                adivObs.saveGame(f.getAbsolutePath());
            }

        });

        //file -> load
        fileLoad.setOnAction((ActionEvent e) -> {
            File f = fileChooser.showSaveDialog(getScene().getWindow());
            if (f != null) {
                adivObs.loadGame(f.getAbsolutePath());
            }

        });

        //file -> exit
        fileExit.setOnAction((ActionEvent e) -> {
            encerra();
            ((Stage) getScene().getWindow()).close();

            //Platform.exit(); //funciona apenas em windows
        });
        //about
        aboutInfo.setOnAction((ActionEvent e) -> {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setHeaderText("acerca disto");
            alert.getDialogPane().setContentText("programa de javafx");

            alert.showAndWait();
        });

        StackPane areaUtil = new StackPane();
        areaUtil.setPadding(new Insets(10));

        UINome uinome = new UINome(); //é um pane
        UIJoga uijoga = new UIJoga(); //é um pane
        UIFim uifim = new UIFim();

        uijoga.setVisible(false);
        uifim.setVisible(false);

        areaUtil.getChildren().addAll(uinome, uijoga, uifim);

        setCenter(areaUtil);
    }

    public void encerra() {
        adivObs.paraRelogio();
    }

    class UINome extends VBox {

        private final Label lNome = new Label("escreve nome");
        private final TextField tfNome = new TextField();
        private final Button btnDefineNome = new Button("ok");

        public UINome() {
            super(10); //espaçamento entre items
            adivObs.registaPropertyChangeListener(PropsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    setVisible(adivObs.obtemEstadoID() == EstadoID.AGUARDA_NOME);
                }
            });
            btnDefineNome.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent t) {
                    adivObs.defineJogador(tfNome.getText());
                }
            });
            tfNome.setOnKeyPressed(e -> {
                if (e.getCode() == KeyCode.ENTER) {
                    adivObs.defineJogador(tfNome.getText());
                }
            });
            getChildren().addAll(lNome, tfNome, btnDefineNome);

        }

    }

    class UIJoga extends VBox {

        private final Label lMsg = new Label();
        private final Label lDesafio = new Label();
        private final TextField tfResposta = new TextField();
        private final Button btnEnviaResposta = new Button("ok");
        private final Label lRelogio = new Label();
        Map<MsgCode, String> mensagens = new HashMap<>();

        public UIJoga() { //1,39
            super(10); //espaçamento entre items
            mensagens.put(MsgCode.START, "vamos começar");
            mensagens.put(MsgCode.RIGHT, "certo. outro desafio");
            mensagens.put(MsgCode.WRONG, "errado. tenta outra vez");
            mensagens.put(MsgCode.TIMEOUT, "tempo excedido. outro desafio");

            btnEnviaResposta.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent t) {
                    tentaResposta();
                }
            });
            tfResposta.setOnKeyPressed(e -> {
                if (e.getCode() == KeyCode.ENTER) {
                    tentaResposta();
                }
            });

            adivObs.registaPropertyChangeListener(PropsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    if (adivObs.obtemEstadoID() == EstadoID.AGUARDA_RESPOSTA) {
                        setVisible(true);
                        defineMensagens(); //atualziar todas as labels com o texto em causa
                        intiTfResposta(); //por o texto a vazio (escrita do texto), quando existe mudança de estado
                    } else {
                        setVisible(false);
                    }
                }
            });

            adivObs.registaPropertyChangeListener(PropsID.PROP_DESAFIO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    defineMensagens();
                }
            });

            adivObs.registaPropertyChangeListener(PropsID.PROP_RELOGIO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    //para processamento futuro caso necessário
                }
            });

            getChildren().addAll(lMsg, lDesafio, tfResposta, btnEnviaResposta, lRelogio);
            defineMensagens();
        }

        private void defineMensagens() {
            lMsg.setText(mensagens.getOrDefault(adivObs.obtemMSG(), "nao compreendo.."));
            //adivObs.obtemMSG() com ajuda de um switch case para obter as mensagens (string) acerca do estado
            //em que se encontra
            //a alternativa foi a opção de se usar um Map<MsgCode, String> mensagens

            lDesafio.setText(adivObs.obtemNomeJogador()
                    + " ,quando é "
                    + adivObs.obtemNumA()
                    + " + "
                    + adivObs.obtemNumB() + "?"
            );
            lRelogio.setText("tempo restante: " + adivObs.obtemCountDown());
        }

        private void intiTfResposta() {
            //serve para apagar a resposta que é escrita
            //e só acontece quando existe mudança de estado
            tfResposta.setText("");
            tfResposta.requestFocus();

        }

        private void tentaResposta() {
            try {
                int val = Integer.parseInt(tfResposta.getText());
                adivObs.tentaResposta(val);
                intiTfResposta();

            } catch (NumberFormatException e) {

            }
        }
    }

    class UIFim extends VBox {

        private final Label lResultado = new Label();
        private final Button btnRecomecar = new Button("Novo jogo");

        public UIFim() {
            super(5);
            adivObs.registaPropertyChangeListener(PropsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() {
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    if (adivObs.obtemEstadoID() == EstadoID.AGUARDA_REINICIO) {
                        setVisible(true);
                        lResultado.setText(adivObs.obtemNomeJogador()
                                + ", o teu resultado:\n"
                                + "pontuação: "
                                + adivObs.obtemPontuacao()
                                + "\n"
                                + "Erros:" + +adivObs.obtemErros()
                                + "(obviamente)\n\n"
                                + "ok para jogar outra vez\n\n"
                        );
                        //formatação com \n em ambiente grafico - tem tudo a ver
                    } else {
                        setVisible(false);
                    }
                }
            });
            btnRecomecar.setOnAction((ActionEvent e) -> {
                adivObs.recomeca();
            }
            );
            getChildren().addAll(lResultado, btnRecomecar);
        }

    }

}

Tags : ,

JavaFX, exercício 3

package recursopa;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import recursopa.iu.gui.PaneOrganizer;

public class RecursoPA extends Application {
    public static void main(String[] args) {
        //passamos os argumentos para o subsistema gráfico os parametros
        launch(args); 
    }
 
    @Override
    //quando começa a aplicação
    public void start(Stage stage) throws Exception{
        PaneOrganizer po = new PaneOrganizer();
        Scene scene = new Scene(po,600,400);
        stage.setScene(scene); //aplica a cena no stage
        stage.setTitle("Exercicio de programação avançada");
        stage.setMinHeight(300.0);
        stage.setMinWidth(300.0);
        stage.show();
    }
}   
package recursopa.iu.gui;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import recursopa.logica.Figura;

public class PaneOrganizer extends Pane {
    //vai extender sempre um dos containers possiveis,  extends Pane

    Figura fig;
    Ellipse elipse;

    public PaneOrganizer() {
        fig = new Figura();
        fig.setPrimeiroPonto(0, 0);
        fig.setSegundoPonto(100, 50);
        fig.setRGB(0, 50, 0);

        criaLayout(); //para criar os componentes que vão surgir no ecrã
        registaListeners(); // registar os comportamentos dos objectos
        atualizaElipse();

    }

    void criaLayout() {
        //adicionar o elemento ao Pane
        elipse = new Ellipse();
        this.getChildren().add(elipse);
    }

    public void registaListeners() {
        //detectar as ações do rato
        this.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent t) {
                fig.setPrimeiroPonto((int) t.getX(), (int) t.getY());
                fig.setSegundoPonto((int) t.getX(), (int) t.getY());
                fig.setRGB((int) (Math.random() * 256), (int) (Math.random() * 256), (int) (Math.random() * 256));
                atualizaElipse();
            }
        });

        //usando lambda functions
        this.setOnMouseReleased((t) -> {
            fig.setSegundoPonto((int) t.getX(), (int) t.getY());
            atualizaElipse();
        });
        this.setOnMouseDragged((t) -> {
            fig.setSegundoPonto((int) t.getX(), (int) t.getY());
            atualizaElipse();
        });

    }

    //para desenhar a elipse
    void atualizaElipse() {
        //elipse.setFill(Color.GREEN);
        elipse.setFill(Color.rgb(fig.getR(), fig.getG(), fig.getB())); //para ir buscar as informações à fig
        //elipse.setCenterX(200.0);
        elipse.setCenterX((fig.getXi() + fig.getXf()) / 2);
        //elipse.setCenterY(200.0);
        elipse.setCenterY((fig.getYi() + fig.getYf()) / 2);
        //elipse.setRadiusX(150.0);
        elipse.setRadiusX(fig.getLargura() / 2);
        //elipse.setRadiusY(100.0);
        elipse.setRadiusY(fig.getAltura() / 2);
    }

}

package recursopa.logica;
public class Figura {
//métodos necessários para gerir a figura

    int xi, yi, xf, yf; //posicao e tamanho
    int r, g, b; //para a cor

    public Figura() {

    }

    public int getXi() {
        return xi;
    }

    public int getYi() {
        return yi;
    }

    public int getXf() {
        return xf;
    }

    public int getYf() {
        return yf;
    }

    public int getR() {
        return r;
    }

    public int getG() {
        return g;
    }

    public int getB() {
        return b;
    }

    public void setRGB(int r, int g, int b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    public void setPrimeiroPonto(int x, int y) {
        this.xi = x;
        this.yi = y;
    }

    public void setSegundoPonto(int x, int y) {
        this.xf = x;
        this.yf = y;
    }

    public int getLargura() {
        return Math.abs(xf - xi); //não interessa a ordem dos valores
    }

    public int getAltura() {
        return Math.abs(yf - yi); //não interessa a ordem dos valores
    }
}

Tags : ,

JavaFX, exercícios

Relembrar para o netBeans correr um projeto com JavaFX e nas propriedades de um projeto:

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

public class RecursoPA extends Application {
    public static void main(String[] args) {
        //passamos os argumentos para o subsistema gráfico os parametros
        launch(args); 
    }
 
    @Override
    //quando começa a aplicação
    public void start(Stage stage) throws Exception{
        BorderPane bp = new BorderPane();
        Label label1 = new Label("programação avançada");
        Label label2 = new Label("outra label");
        bp.setBottom(label1);
        bp.setTop(label2);
        //criar a cena
        Scene scene = new Scene(bp,400,400); //raiz da cena, e dimensões
        //adicionar a cena ao palco
        stage.setScene(scene);
        stage.show();
    }
}   
Tags : ,

JavaFX, exercício 2

package javafx03;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx03.iu.gui.PaneOrganizer;

public class Javafx03 extends Application {

    public static void main(String[] args) {
        //redirecionar a execução para o método launch
        launch(args);
    }

    @Override
    public void init() throws Exception {
        //inicar qualquer coisa antes do start
        System.out.println("init");
        super.init();
    }

    //méotod obrigatório abstract do Application
    @Override
    public void start(Stage stage) throws Exception {
        System.out.println("start");
        //no palco vão ocorrer cenas
        PaneOrganizer po = new PaneOrganizer();
        Scene cena = new Scene(po, 600, 400);
        stage.setScene(cena);
        stage.setTitle("programação avançada!");
        stage.setMinWidth(300);
        stage.setMinHeight(200);
        stage.show();
    }

    @Override
    public void stop() throws Exception {
        System.out.println("stop");
        super.stop();
    }

}
package javafx03.iu.gui;

import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;

import javafx.scene.shape.Ellipse;
import javafx03.logica.Figura;

//pane, usa o espaço todo disponivel
public class PaneOrganizer extends Pane {

    //criar a figura
    Figura figura;
    Ellipse elipse;

    public PaneOrganizer() {
        this.figura = new Figura();
        figura.setPrimeiroPonto(0, 0);
        figura.setSegundoPonto(100, 50);
        figura.setRGB(0, 255, 0);

        criarLayout();
        registaListeners();
        atualizaFigura();
    }

    private void criarLayout() {
        //criar uma nova elipse
        /*
        elipse.setCenterX(200);
        elipse.setCenterY(100);
        elipse.setFill(Color.GREEN);
        elipse.setRadiusX(200); 
        elipse.setRadiusY(100);
         */
        //adicionar a elipse ao pane
        elipse = new Ellipse();
        this.getChildren().add(elipse);
    }

    private void registaListeners() {
        //podia ser feito numa classe à parte
        this.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent t) {
                figura.setPrimeiroPonto((int) t.getX(), (int) t.getY());
                figura.setSegundoPonto((int) t.getX(), (int) t.getY());
                figura.setRGB((int) (Math.random() * 256), (int) (Math.random() * 256), (int) (Math.random() * 256));
                atualizaFigura();
            }
        });
        //com lambda
        this.setOnMouseDragged((t) -> {
            figura.setSegundoPonto((int) t.getX(), (int) t.getY());
            atualizaFigura();
        });

//        this.setOnMouseReleased((t) -> {
//            figura.setSegundoPonto((int) t.getX(), (int) t.getY());
//            atualizaFigura();
//        });

    }

    private void atualizaFigura() {
        elipse.setFill(Color.rgb(figura.getR(), figura.getG(), figura.getB()));
        elipse.setCenterX((figura.getXi() + figura.getXf()) / 2);
        elipse.setCenterY((figura.getYi() + figura.getYf()) / 2);
        elipse.setRadiusX(figura.getAltura() / 2);
        elipse.setRadiusY(figura.getLargura() / 2);
    }
}
package javafx03.logica;

public class Figura {

    int xi, xf;
    int yi, yf;
    int r, g, b;

    public Figura() {

    }

    public int getXi() {
        return xi;
    }

    public int getXf() {
        return xf;
    }

    public int getYi() {
        return yi;
    }

    public int getYf() {
        return yf;
    }

    public int getR() {
        return r;
    }

    public int getG() {
        return g;
    }

    public int getB() {
        return b;
    }

    public void setRGB(int r, int g, int b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    public void setPrimeiroPonto(int x, int y) {
        this.xi = x;
        this.yi = y;
    }

    public void setSegundoPonto(int x, int y) {
        this.xf = x;
        this.yf = y;
    }

    public int getLargura() {
        return Math.abs(xf - xi);
    }

    public int getAltura() {
        return Math.abs(xf - xi);
    }
}
Tags : ,

JavaFX, exercício 1

Uso de:

Com:

package javafx02;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx02.PaneOrganizer.PaneOrganizer;

public class JavaFx02 extends Application {

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

    @Override
    public void init() throws Exception {
        super.init();
        System.out.println("onInit");
    }

    @Override
    public void start(Stage stage) throws Exception {
        System.out.println("onStart");
        PaneOrganizer brd = new PaneOrganizer();
         Scene scene = new Scene(brd, 600, 400);
        stage.setScene(scene);
        stage.setTitle("Programação avançada");
        stage.show();
    }

    @Override
    public void stop() throws Exception {
        super.stop();
        System.out.println("onStop");
    }
}
package javafx02.PaneOrganizer;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;

public class PaneOrganizer extends BorderPane {

    Button btnVerde, btnAzul;
    Label lblVerde, lblAzul;
    int numerVerde, numeroAzul;

    public PaneOrganizer() {
        createPane();
        //registerListener1();
        //registerListener2();
        //registerListener3();
        //registerListener4();
        registerListener5();
        numerVerde=0;
        numeroAzul=0;
    }

    void createPane() {
        btnVerde = new Button("Green");
        btnVerde.setTextFill(Color.GREEN);
        btnAzul = new Button("Blue");
        btnAzul.setTextFill(Color.BLUE);
        //numeros dinamicos
        lblVerde = new Label("#Verde: 0");
        lblAzul = new Label("#Azul: 0");

        HBox hbox = new HBox();
        hbox.getChildren().addAll(btnVerde, btnAzul);
        hbox.setSpacing(25);
        hbox.setPadding(new Insets(10));
        hbox.setAlignment(Pos.CENTER);
        this.setTop(hbox);
        
        //numeros dinamicos
         HBox hboxlbl = new HBox();
        hboxlbl.getChildren().addAll(lblVerde, lblAzul);
        hboxlbl.setSpacing(25);
        hboxlbl.setPadding(new Insets(10));
        hboxlbl.setAlignment(Pos.CENTER);
        hboxlbl.setBackground(new Background(new BackgroundFill(Color.rgb(255, 255, 255), CornerRadii.EMPTY, Insets.EMPTY)));
        this.setBottom(hboxlbl);

        /*
        //outras coisas!
        Label l1 = new Label("Texto 1");
        l1.setFont(Font.font("Times New Roman", FontWeight.BOLD, FontPosture.ITALIC, 24));
        l1.setTextFill(Color.rgb(0, 255, 0));
        l1.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));
        l1.setPadding(new Insets(10, 20, 30, 40));
        //brd.setTop(l1);

        Label l2 = new Label("Texto 2");
        l2.setTextFill(Color.rgb(0, 123, 123));

        HBox hbox = new HBox();
        hbox.getChildren().addAll(l1, l2);
        hbox.setStyle("-fx-background-color: #00ffff;"); //outra forma, css
        hbox.setPadding(new Insets(10));
        hbox.setAlignment(Pos.CENTER);
        hbox.setSpacing(25);
        this.setTop(hbox);

        //brd.setBottom(l2);
        BorderPane.setAlignment(l2, Pos.CENTER);
         */
    }

    //1ºalternativa, usando uma inner class
    void registerListener1() {
        btnVerde.setOnAction(new ProgBotaoVerde1()); //o que vai ser executado, um objecto do tipo!
        btnAzul.setOnAction(new ProgBotaoAzul1()); //o que vai ser executado, um objecto do tipo!
    }

    class ProgBotaoVerde1 implements EventHandler<ActionEvent> {

        @Override
        public void handle(ActionEvent t) {
            //quando o botão for clicado
            System.out.println("Oi botão verde - inner class");
            //aceder ao objecto de fora ou então criar uma varivel ou via construtor
            PaneOrganizer.this.setBackground(new Background(new BackgroundFill(Color.rgb(0, 255, 0), CornerRadii.EMPTY, Insets.EMPTY)));
        }

    }

    class ProgBotaoAzul1 implements EventHandler<ActionEvent> {

        @Override
        public void handle(ActionEvent t) {
            //quando o botão for clicado
            System.out.println("Oi botão azul - inner class");
            //aceder ao objecto de fora ou então criar uma varivel ou via construtor
            PaneOrganizer.this.setBackground(new Background(new BackgroundFill(Color.rgb(0, 0, 255), CornerRadii.EMPTY, Insets.EMPTY)));
        }
    }

    //2ºalternativa, usando uma classe inline
    void registerListener2() {
        btnVerde.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                System.out.println("Oi botão azul - inline");
                PaneOrganizer.this.setBackground(new Background(new BackgroundFill(Color.rgb(0, 255, 0), CornerRadii.EMPTY, Insets.EMPTY)));
            }
        });
        btnAzul.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                System.out.println("Oi botão azul - inline");
                PaneOrganizer.this.setBackground(new Background(new BackgroundFill(Color.rgb(0, 0, 255), CornerRadii.EMPTY, Insets.EMPTY)));
            }
        });
    }

    //3ºalternativa, usando uma classe inline
    void registerListener3() {
        btnVerde.setOnAction(new ProcessaBotao(Color.GREEN)); //o que vai ser executado, um objecto do tipo!
        btnAzul.setOnAction(new ProcessaBotao(Color.BLUE)); //o que vai ser executado, um objecto do tipo!
    }

    class ProcessaBotao implements EventHandler<ActionEvent> {
        Color cor;
        public ProcessaBotao(Color cor) {
            this.cor = cor;
        }
        @Override
        public void handle(ActionEvent t) {
            //quando o botão for clicado
            System.out.println("Oi botão azul - inner class");
            //aceder ao objecto de fora ou então criar uma varivel ou via construtor
            PaneOrganizer.this.setBackground(new Background(new BackgroundFill(cor, CornerRadii.EMPTY, Insets.EMPTY)));
        }
    }
    
    //4ºalternativa, usando lambda functions
    void registerListener4() {
    btnVerde.setOnAction(
            (t)->{
                PaneOrganizer.this.setBackground(
                        new Background(new BackgroundFill(Color.GREEN, CornerRadii.EMPTY, Insets.EMPTY)));
            });
   
    btnAzul.setOnAction(
            (t)->{
                PaneOrganizer.this.setBackground(
                        new Background(new BackgroundFill(Color.BLUE, CornerRadii.EMPTY, Insets.EMPTY)));
            });
    }
    
    //dinamicos
    void registerListener5() {
        btnVerde.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                System.out.println("Oi botão azul - inline");
                PaneOrganizer.this.setBackground(new Background(new BackgroundFill(Color.rgb(0, 255, 0), CornerRadii.EMPTY, Insets.EMPTY)));
                numerVerde++;
                lblVerde.setText("#Verde: "+numerVerde);
            }
        });
        btnAzul.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                System.out.println("Oi botão azul - inline");
                PaneOrganizer.this.setBackground(new Background(new BackgroundFill(Color.rgb(0, 0, 255), CornerRadii.EMPTY, Insets.EMPTY)));
                numeroAzul++;
                lblAzul.setText("#Azul: "+numeroAzul);
            }
        });
    }
}
Tags :

JavaFX, construir aplicações com GUI em JAVA

Para começar a trabalhar com o JavaFX é necessário instalar na máquina:
https://openjfx.io/

que muito provavelmente vai redireccionar para o link:
https://gluonhq.com/products/javafx/

o download deve ser de:
openjfx-14.0.1_windows-x64_bin-sdk.zip

(ou então de uma versão LTS)

Em Windows depois é necessário descompactar o ZIP e copiar a pasta para:
\Program Files\Java

Antes de passar ao passo seguinte, recomendo que se instale a versão mais recente do Java, por exemplo a jdk-14.0.1_windows-x64_bin.exe e que desinstale todas as outras versões!!

Agora falta configurar o netbeans, v13:
criar uma nova biblioteca, tools->libraries
botão: new library
atribuir um nome, por exemplo JavaFX14
clicar em Add/JAR/Folder
e adicionar (seleccionar) todos os ficheiros jar da pasta: javafx-sdk-14.0.1\lib
voltar à janela principal do netbeans, e ir às propriedades do projeto
nas propriedades do projeto, escolher  a opção libraries e clicar em classpath e libraries
escolher a opção JavaFX14
e no separador Run adicionar ao modulepath adicionar a biblioteca JavaFX14
ainda nas propriedades e do lado esquerdo, escolher Run, VM options:
–module-path /Program Files/Java/javafx-sdk-14.0.1/lib –add-modules javafx.controls

e done!

(ou seguir isto https://openjfx.io/openjfx-docs/#IDE-NetBeans)

 
package javafx01;

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

public class JavaFx01 extends Application {
    public static void main(String[] args) {
        //passamos os argumentos para o subsistema gráfico os parametros
        launch(args); 
    }

    @Override
    //quando começa a aplicação
    public void start(Stage stage) throws Exception{
        BorderPane bp = new BorderPane();
        Label label1 = new Label("programação avançada");
        Label label2 = new Label("outra label");
        bp.setBottom(label1);
        bp.setTop(label2);
        //criar a cena
        Scene scene = new Scene(bp,400,400); //raiz da cena, e dimensões
        //adicionar a cena ao palco
        stage.setScene(scene);
        stage.show();
    }
}

Stage -> a janela da aplicação
Scene -> representa os elementos que vão estar presentes num stage
Node -> componentes específicos, são os nodes, que podemos ter dentro de cada cena (Canvas, ImageView, MediaView, Shape, Shape3D, SwingNode, EventTarget, Styleable: button, checkbox, combobox, label, listview, progressbar, radiobutton textfield)

Acerca dos objectos Pane existem estas opções:

Para projectos futuros:
em libraries->separador compile-> class path: e seleccionar a biblioteca JavaFX14
separador run -> modulepath: e seleccionar a biblioteca JavaFX14
e no run -> VM options -> –add-modules javafx.controls

Tags : , ,