ManejadorPantallas-1.pdf

13
Oracle Blogs Home Products & Services Downloads Support Partners Communities About Login Oracle Blog Angela's Blog Angela's Blog « Managing Multiple... | Main | Managing Multiple... » Manejando Multiples Pantallas en JavaFX (Parte I) By Angela Caicedo on Feb 14, 2013 (English version) Una de las mejores cosas de mi trabajo es que tengo la oportunidad de escribir código y jugar con las últimas technologias. He sido desarrolladora de JavaFX ya por varios años y he creado todo tipo de demostraciones. El año pasado me encontré con un problema que algunos de ustedes pueden de estar teniendo hoy en dia: Como navigar entre pantallas y como manejar fácilmente el stack the pantallas en nuestro scene graph? Esta es la razón por al cual me he decidido a escribir este blog y compartir con ustedes este pequeno framework que escribi para mi aplicacion. Para JavaOne 2012 decidí crear una aplicacion para un casino, y necesitaría una pantalla diferente para cada juego: Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan... 1 de 13 20/02/14 20:05

Transcript of ManejadorPantallas-1.pdf

Oracle

Blogs HomeProducts & ServicesDownloadsSupportPartnersCommunitiesAboutLogin

Oracle Blog

Angela's Blog

Angela's Blog

« Managing Multiple... | Main | Managing Multiple... »

Manejando Multiples Pantallas en JavaFX (Parte I)

By Angela Caicedo on Feb 14, 2013

(English version)

Una de las mejores cosas de mi trabajo es que tengo la oportunidad de escribir códigoy jugar con las últimas technologias. He sido desarrolladora de JavaFX ya por variosaños y he creado todo tipo de demostraciones. El año pasado me encontré con unproblema que algunos de ustedes pueden de estar teniendo hoy en dia: Como navigarentre pantallas y como manejar fácilmente el stack the pantallas en nuestro scenegraph? Esta es la razón por al cual me he decidido a escribir este blog y compartir conustedes este pequeno framework que escribi para mi aplicacion.

Para JavaOne 2012 decidí crear una aplicacion para un casino, y necesitaría unapantalla diferente para cada juego:

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

1 de 13 20/02/14 20:05

Crear las pantallas fue la parte mas fácil: Utilizé NetBeans y JavaFX Scene Builder.

Para NetBeans hay varias opciones:

Puedes crear New Project, y seleccionar JavaFX FXML Application. Esta opcióngenera un projecto que contiene 3 archivos: un archivo fxml, una clasecontrolladora, y una clase main. El archivo fxml es donde todos los componentesthe la interfaz gráfica con definidos. El controlador, tiene la injeccion de loselementos fxml junto con algunos métodos utilizados por dicha interfaz gráfica.Finalmente, la clase main carga el archivo fxml, y comienza la ejecucion de laapplicación.

La segunda opición es a partir de un projecto existente. Puedes hacer clickderecho en el projecto y seleccionar Add Empty fxml file. Una pantalla tepreguntara si deseas la creación del controllador asociado con el nuevo archivofxml, en mi opinion, si se debe de crear esta clase controladora y mas tarde eneste blog miraremos por que. A diferencia de la opción anterior, en este caso nose crea una clase main, y en algún lugar de nuestro código estamos a cargo decargar y desplegar los componentes gráficos creados en el archivo fxml.

A partir del fxml inicial, podemos editar fácilmente este archivo usando JavaFX SceneBuilder. Es verdaderamente fácil de usar, y puedes encontrar tutoriales hacerca deesto aqui.

Ahora, todo parece muy simple, verdad? Bueno, no tanto. A medida de que vamoscreando las pantallas, nos encontraremos que tenemos un montón de archivos fxml yun montón de clases controladoras, una por cada pantalla creada. Esto parece

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

2 de 13 20/02/14 20:05

rasonable, ya que no queremos por ningún motivo tener la definición de todas laspantallas en un solo archivo fxml. Pero como manejarlas?

Miremos que debemos de tener en cuenta:

Lo primero que se nos viene a la cabeza es utilizar un StackPane, correcto?Ponemos todas las pantallas en este Stack, una encima de la otra, y la que este enel tope del Stack es la que sería desplegada. Para cambiar de pantalla, sería tanfácil como cambiar de posición las pantallas en dicho Stack. Esto, aunque parecesimple, no sería buena idea, ya que el rendimiento de la aplicación se veriaseriamente afectado. El scene graph sería inmenso, y cargado de componentesgráficos que no son nisiquiera visibles. Uno de las primeras reglas en JavaFXpara tener buen rendimiento es mantener el scene graph pequeño.

Definitivamente deseamos mantener archivos fxml separados, uno por cadapantalla. El diseño y el mantenimiento de estos serán muchisimo mas fácil deesta manera.

También tiene sentido tener un controlador por cada pantalla. De nuevo,queremos mantener separados no sólo los componentes gráficos sino tambien loscomportamientos asociados a estos.

Necesitamos definir una navegacion limpia y fácil entre las pantallas.

Una vez más, MANTIENE el scene graph pequeño!

Entonces, que podríamos hacer?

StackPane sigue siendo una opción excelente como contenedor, simplemente sedebe manejar de forma apropiada. En el framework que you cree, el stack panesólo posee una pantalla en el stack al tiempo. Para mi aplicación yo opté por unaimagen común como fondo de la aplicación, asi las transiciones entre pantallas

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

3 de 13 20/02/14 20:05

serían mas fáciles. Para pasar a una nueva pantalla, una serie de animacionestienen lugar. Por simplicidad de este framework utilicé "fade transitions", peropuedes cambiar y utilizar la transición que desees.La imagen de fondo de la applicación siempre permanece en el scene graph, y esvisible todo el tiempo. Para movernos a una nueva pantalla, la primera transicion'fade' tiene lugar, haciendo desaparecer los componentes graficos de la pantallaactual. El framework utiliza un EventHandler, el cual será notificado cuando estatransición 'fade' termine. Cuando esto sucede, pasamos a retirar los componentsde la pantalla que estaba siendo desplegada y que en este momento ya soninvisibles. Luego adicionamos los componentes gráphicos de la nueva pantalla(pantalla a ser desplegada) que por defecto son invisibles, pasando luego aejecutar una nueva transicion en la que hacemos visibles todos sus componentes.De esta manera, solo una pantalla esta cargada en el scene graph y no se veraafectada el buen rendimiento de la aplicación. Aqui estan los pasos a seguir:

Mostrar la pantalla principal

El usuario selecciona un juego

La pantalla actual empieza a desaparecer (transición). Al terminar, esta esretirada el scene graph y la nueva pantalla comienza a hacerce visible.

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

4 de 13 20/02/14 20:05

Hasta que finalmente la nueva pantalla es completamente visible.

El StackPane termina tan sólo con una pantalla en su scene graph.

Con este método, se puede especificar cualquier transicion deseada entrepantallas. Estas pueden entrar de arriba hacia abajo, or entrarhorizontalmente por uno de los lados: puedes implementar la animación quedesees.

Ahora miremos el código:

Primero, todas las pantallas necesitan saber sobre su padre, en nuestro caso fuela pantalla main, ya que necesitamos poder regresar al menu principal una vez elusuario termine de jugar, o simplemente porque el usuario desee seleccionar unnuevo juego. Para esto necesitaremos una interfaz común (ControlledScreen),con un método para la injección del padre(setScreenParent).

public interface ControlledScreen {

//This method will allow the injection of the Parent ScreenPane

public void setScreenParent(ScreensController screenPage);

}

1.

Por cada pantalla mantenemos un archivo fxml separado, al igual que una clase2.

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

5 de 13 20/02/14 20:05

controladora, como lo mensionamos al principio de este blog. Cada controladordebe implementar ControlledScreen, para que todos ellos compartan el mismotipo, y podamos mas tarde asociara el padre a cada pantalla.

public class Screen1Controller implements Initializable,

ControlledScreen {

ScreensController myController;

@Override

public void initialize(URL url, ResourceBundle rb) {

// TODO

}

public void setScreenParent(ScreensController screenParent){

myController = screenParent;

}

//any required method here

}

Ahora que cada controlador tiene la referencia de su padre, podemos pasara definir los métodos que realizarán la navegación. Por ejemplo, si deseamosregresar a la pantalla principal de uno de los juegos, debemos ejecutar elsiguiente método:

@FXML

private void goToMain(ActionEvent event){

myController.setScreen(ScreensFramework.MAIN_SCREEN);

}

Necesitamos una nueva clase (ScreensController) para majenar las pantallas:

Esta clase de heredar StackPane, ya que parece ser la opción mas adecuadapara nuestro escenario.

public class ScreensController extends StackPane {

ScreensController contiene un HashMap llamado screens. Esta colleccióncontiene parejas construídas por el identificador de la pantalla junto al nodo

3.

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

6 de 13 20/02/14 20:05

que representa la raiz de su scene graph.

private HashMap<String, Node> screens = new HashMap<>();

Esta clase debe definir métodos para addicionar, cargar y mostrar lapantalla adecuada:

addScreen(String id, Node screen) adiciona una pareja (id, screen) alHashMap screens.

public void addScreen(String name, Node screen) {

screens.put(name, screen);

}

loadScreen(String id, String resource) Este método carga el archivofxml especificado por resource, y obtiene el nodo raiz para you pantalla.También podemos obtener el controlador asociado con la pantalla, estonos permitirá configurar el padre. Esto es posible ya que todos loscontroladores comparten el mismo tipo ControlledScreen.Finalmente, la pantalla es adicionada al hash map llamado screens.Como se puede observar en el código, el archivo fxml que se hacargado, aun no se ha adicionado al scene graph, osea que aun no esdesplegado por JavaFX.

public boolean loadScreen(String name, String resource) {

try {

FXMLLoader myLoader = new

FXMLLoader(getClass().getResource(resource));

Parent loadScreen = (Parent) myLoader.load();

ControlledScreen myScreenControler =

((ControlledScreen) myLoader.getController());

myScreenControler.setScreenParent(this);

addScreen(name, loadScreen);

return true;

}catch(Exception e) {

System.out.println(e.getMessage());

return false;

}

}

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

7 de 13 20/02/14 20:05

setScreen(String screenName). Este método muestra la pantallaespecificada con el identificador dado.

Primero verificamos si la panatalla reconocida por eseidentificador ha sido cargada previamente.

También tenemos que chequear si hay ya una pantalla desplegada(necesitamos entonces hacer transiciones entre pantallas), o siesta es la primera pantalla a ser mostrada (simplemente semuestra la pantalla).

Si ya existe una pantalla, ejecutamos la transicion y definimos eleventHandler para que se haga cargo de la ejecución, una veztermine esta transición.

Una vez la antigua pantalla se hace invisible, se remueve del scenegraph, y se adiciona la nueva. De nuevo, una animación esrealizada para mostrar la nueva pantalla.

public boolean setScreen(final String name) {

if(screens.get(name) != null) { //screen loaded

final DoubleProperty opacity = opacityProperty();

//Is there is more than one screen

if(!getChildren().isEmpty()){

Timeline fade = new Timeline(

new KeyFrame(Duration.ZERO,

new KeyValue(opacity,1.0)),

new KeyFrame(new Duration(1000),

new EventHandler() {

@Override

public void handle(ActionEvent t) {

//remove displayed screen

getChildren().remove(0);

//add new screen

getChildren().add(0, screens.get(name));

Timeline fadeIn = new Timeline(

new KeyFrame(Duration.ZERO,

new KeyValue(opacity, 0.0)),

new KeyFrame(new Duration(800),

new KeyValue(opacity, 1.0)));

fadeIn.play();

}

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

8 de 13 20/02/14 20:05

}, new KeyValue(opacity, 0.0)));

fade.play();

} else {

//no one else been displayed, then just show

setOpacity(0.0);

getChildren().add(screens.get(name));

Timeline fadeIn = new Timeline(

new KeyFrame(Duration.ZERO,

new KeyValue(opacity, 0.0)),

new KeyFrame(new Duration(2500),

new KeyValue(opacity, 1.0)));

fadeIn.play();

}

return true;

} else {

System.out.println("screen hasn't been loaded!\n");

return false;

}

Tambien necesitamos un método unloadScreen(String name). Estesimplemente remueve la pantalla de nuestra hash map, reportando el statusde esta operación.

public boolean unloadScreen(String name) {

if(screens.remove(name) == null) {

System.out.println("Screen didn't exist");

return false;

} else {

return true;

}

}

Ahora lo único que necesitamos es comenzar a utilizar el framework. Aqui estauna pequeña parte de código que muestra como hacerlo.

public class ScreensFramework extends Application {

public static final String MAIN_SCREEN = "main";

public static final String MAIN_SCREEN_FXML = "main.fxml";

public static final String POKER_SCREEN = "poker";

public static final String POKER_SCREEN_FXML =

4.

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

9 de 13 20/02/14 20:05

"poker.fxml";

public static final String ROULETTE_SCREEN = "roulette";

public static final String ROULETTE_SCREEN_FXML =

"roulette.fxml";

@Override

public void start(Stage primaryStage) {

ScreensController mainContainer = new ScreensController();

mainContainer.loadScreen(ScreensFramework.MAIN_SCREEN,

ScreensFramework.MAIN_SCREEN_FXML);

mainContainer.loadScreen(ScreensFramework.POKER_SCREEN,

ScreensFramework.POKER_SCREEN_FXML);

mainContainer.loadScreen(ScreensFramework.ROULETTE_SCREEN,

ScreensFramework.ROULETTE_SCREEN_FXML);

mainContainer.setScreen(ScreensFramework.MAIN_SCREEN);

Group root = new Group();

root.getChildren().addAll(mainContainer);

Scene scene = new Scene(root);

primaryStage.setScene(scene);

primaryStage.show();

}

...

Este framework fue de bastante ayuda para la creación de mi aplicación y espero quetambién sea de utilidad para usteded. Pueden encontrar la implementación de esteframework, junto con tres clases para verificar que todo funcione en este link.

Tambien hay un video asociado a este blog que pueden encontrar aqui.

Category: Oracle

Tags: none

Permanent link to this entry

« Managing Multiple... | Main | Managing Multiple... »Comments:

Post a Comment:

Name:

guest

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

10 de 13 20/02/14 20:05

E-Mail:

URL:

Notify me by email of new comments

Remember Information?

Your Comment:HTML Syntax: NOT allowed

Please answer this simple math question

5 + 18 =

Preview Post

About

Angela Caicedo

Search

Enter search term:

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

11 de 13 20/02/14 20:05

Search only this blog

Recent Posts

Some samples using GPIO and I2C with Pi4JBeyond Beauty: JavaFX, I2C, Parallax, Touch, Raspberry Pi, Gyroscopes andMuch More. (Part I)Getting Started with Java ME Embedded 3.3 on Keil BoardManaging Multiple Screens in JavaFX. (Part II)Manejando Multiples Pantallas en JavaFX (Parte I)Managing Multiple Screens in JavaFX. (Part I)Unleash the Power of JavaFXJavaOne Countdown, Are you ready?JavaFX Deployment News!I'm BACK!!!!

Top Tags

cssfxmlholjavajavafxjavaone

Categories

OraclePersonal

Archives

« February 2014SunMonTueWedThuFriSat

12 3 4 5 6 7 89 10 11 12 13 14 1516 17 18 19 20 21 2223 24 25 26 27 28

Today

Bookmarks

Events

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

12 de 13 20/02/14 20:05

Oracle Technology NetworkOracle Technology Network BlogRecent ArticlesTechnology Newsletters

Menu

Blogs HomeWeblogLogin

Feeds

RSS

All/Oracle/PersonalComments

Atom

All/Oracle/PersonalComments

The views expressed on this blog are those of the author and do not necessarily reflectthe views of Oracle. Terms of Use | Your Privacy Rights | Cookie Preferences

Manejando Multiples Pantallas en JavaFX (Parte I... https://blogs.oracle.com/acaicedo/entry/manejan...

13 de 13 20/02/14 20:05