Vous êtes sur la page 1sur 13

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

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 cdigo y jugar con las ltimas technologias. He sido desarrolladora de JavaFX ya por varios aos y he creado todo tipo de demostraciones. El ao pasado me encontr con un problema que algunos de ustedes pueden de estar teniendo hoy en dia: Como navigar entre pantallas y como manejar fcilmente el stack the pantallas en nuestro scene graph? Esta es la razn 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 necesitara una pantalla diferente para cada juego:

1 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

Crear las pantallas fue la parte mas fcil: Utiliz NetBeans y JavaFX Scene Builder.

Para NetBeans hay varias opciones: Puedes crear New Project, y seleccionar JavaFX FXML Application. Esta opcin genera un projecto que contiene 3 archivos: un archivo fxml, una clase controlladora, y una clase main. El archivo fxml es donde todos los componentes the la interfaz grca con denidos. El controlador, tiene la injeccion de los elementos fxml junto con algunos mtodos utilizados por dicha interfaz grca. Finalmente, la clase main carga el archivo fxml, y comienza la ejecucion de la applicacin. La segunda opicin es a partir de un projecto existente. Puedes hacer click derecho en el projecto y seleccionar Add Empty fxml file. Una pantalla te preguntara si deseas la creacin del controllador asociado con el nuevo archivo fxml, en mi opinion, si se debe de crear esta clase controladora y mas tarde en este blog miraremos por que. A diferencia de la opcin anterior, en este caso no se crea una clase main, y en algn lugar de nuestro cdigo estamos a cargo de cargar y desplegar los componentes grcos creados en el archivo fxml.

A partir del fxml inicial, podemos editar fcilmente este archivo usando JavaFX Scene Builder. Es verdaderamente fcil de usar, y puedes encontrar tutoriales hacerca de esto aqui. Ahora, todo parece muy simple, verdad? Bueno, no tanto. A medida de que vamos creando las pantallas, nos encontraremos que tenemos un montn de archivos fxml y un montn de clases controladoras, una por cada pantalla creada. Esto parece

2 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

rasonable, ya que no queremos por ningn motivo tener la denicin de todas las pantallas 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 en el tope del Stack es la que sera desplegada. Para cambiar de pantalla, sera tan fcil como cambiar de posicin las pantallas en dicho Stack. Esto, aunque parece simple, no sera buena idea, ya que el rendimiento de la aplicacin se veria seriamente afectado. El scene graph sera inmenso, y cargado de componentes grcos que no son nisiquiera visibles. Uno de las primeras reglas en JavaFX para tener buen rendimiento es mantener el scene graph pequeo.

Denitivamente deseamos mantener archivos fxml separados, uno por cada pantalla. El diseo y el mantenimiento de estos sern muchisimo mas fcil de esta manera. Tambin tiene sentido tener un controlador por cada pantalla. De nuevo, queremos mantener separados no slo los componentes grcos sino tambien los comportamientos asociados a estos. Necesitamos denir una navegacion limpia y fcil entre las pantallas. Una vez ms, MANTIENE el scene graph pequeo!

Entonces, que podramos hacer?


StackPane sigue siendo una opcin excelente como contenedor, simplemente se debe manejar de forma apropiada. En el framework que you cree, el stack pane slo posee una pantalla en el stack al tiempo. Para mi aplicacin yo opt por una imagen comn como fondo de la aplicacin, asi las transiciones entre pantallas
3 de 13 20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

seran mas fciles. Para pasar a una nueva pantalla, una serie de animaciones tienen lugar. Por simplicidad de este framework utilic "fade transitions", pero puedes cambiar y utilizar la transicin que desees. La imagen de fondo de la applicacin siempre permanece en el scene graph, y es visible todo el tiempo. Para movernos a una nueva pantalla, la primera transicion 'fade' tiene lugar, haciendo desaparecer los componentes gracos de la pantalla actual. El framework utiliza un EventHandler, el cual ser noticado cuando esta transicin 'fade' termine. Cuando esto sucede, pasamos a retirar los components de la pantalla que estaba siendo desplegada y que en este momento ya son invisibles. Luego adicionamos los componentes grphicos de la nueva pantalla (pantalla a ser desplegada) que por defecto son invisibles, pasando luego a ejecutar 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 vera afectada el buen rendimiento de la aplicacin. Aqui estan los pasos a seguir:

Mostrar la pantalla principal

El usuario selecciona un juego

La pantalla actual empieza a desaparecer (transicin). Al terminar, esta es retirada el scene graph y la nueva pantalla comienza a hacerce visible.

4 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

Hasta que nalmente la nueva pantalla es completamente visible.

El StackPane termina tan slo con una pantalla en su scene graph. Con este mtodo, se puede especicar cualquier transicion deseada entre pantallas. Estas pueden entrar de arriba hacia abajo, or entrar horizontalmente por uno de los lados: puedes implementar la animacin que desees.

Ahora miremos el cdigo: 1. Primero, todas las pantallas necesitan saber sobre su padre, en nuestro caso fue la pantalla main, ya que necesitamos poder regresar al menu principal una vez el usuario termine de jugar, o simplemente porque el usuario desee seleccionar un nuevo juego. Para esto necesitaremos una interfaz comn (ControlledScreen), con un mtodo para la injeccin del padre(setScreenParent).

public interface ControlledScreen { //This method will allow the injection of the Parent ScreenPane public void setScreenParent(ScreensController screenPage); }

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

5 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

controladora, como lo mensionamos al principio de este blog. Cada controlador debe implementar ControlledScreen, para que todos ellos compartan el mismo tipo, 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 pasar a denir los mtodos que realizarn la navegacin. Por ejemplo, si deseamos regresar a la pantalla principal de uno de los juegos, debemos ejecutar el siguiente mtodo:

@FXML private void goToMain(ActionEvent event){ myController.setScreen(ScreensFramework.MAIN_SCREEN); }

3. Necesitamos una nueva clase (ScreensController) para majenar las pantallas: Esta clase de heredar StackPane, ya que parece ser la opcin mas adecuada para nuestro escenario.

public class ScreensController extends StackPane {

ScreensController contiene un HashMap llamado screens. Esta colleccin

contiene parejas construdas por el identicador de la pantalla junto al nodo

6 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

que representa la raiz de su scene graph.

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

Esta clase debe denir mtodos para addicionar, cargar y mostrar la pantalla adecuada:
addScreen(String id, Node screen) adiciona una pareja (id, screen) al HashMap screens.

public void addScreen(String name, Node screen) { screens.put(name, screen); }

loadScreen(String id, String resource) Este mtodo carga el archivo fxml especicado por resource, y obtiene el nodo raiz para you pantalla.

Tambin podemos obtener el controlador asociado con la pantalla, esto nos permitir congurar el padre. Esto es posible ya que todos los controladores comparten el mismo tipo ControlledScreen. Finalmente, la pantalla es adicionada al hash map llamado screens. Como se puede observar en el cdigo, el archivo fxml que se ha cargado, aun no se ha adicionado al scene graph, osea que aun no es desplegado 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; } }

7 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

setScreen(String screenName). Este especicada con el identicador dado.

mtodo

muestra

la

pantalla por ese

Primero vericamos si la panatalla reconocida identicador ha sido cargada previamente.

Tambin tenemos que chequear si hay ya una pantalla desplegada (necesitamos entonces hacer transiciones entre pantallas), o si esta es la primera pantalla a ser mostrada (simplemente se muestra la pantalla). Si ya existe una pantalla, ejecutamos la transicion y denimos el eventHandler para que se haga cargo de la ejecucin, una vez termine esta transicin. Una vez la antigua pantalla se hace invisible, se remueve del scene graph, y se adiciona la nueva. De nuevo, una animacin es realizada 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(); }

8 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

}, 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 mtodo unloadScreen(String name). Este simplemente remueve la pantalla de nuestra hash map, reportando el status de esta operacin.

public boolean unloadScreen(String name) { if(screens.remove(name) == null) { System.out.println("Screen didn't exist"); return false; } else { return true; } }

4. Ahora lo nico que necesitamos es comenzar a utilizar el framework. Aqui esta una pequea parte de cdigo 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 =

9 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

"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 creacin de mi aplicacin y espero que tambin sea de utilidad para usteded. Pueden encontrar la implementacin de este framework, junto con tres clases para vericar 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

10 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

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
About

Post

Angela Caicedo
Search

Enter search term:

11 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

Search only this blog


Recent Posts

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

css fxml hol java javafx javaone


Categories

Oracle Personal
Archives

February 2014 Sun Mon Tue Wed Thu Fri Sat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Today
Bookmarks

Events

12 de 13

20/02/14 20:05

Manejando Multiples Pantallas en JavaFX (Parte I...

https://blogs.oracle.com/acaicedo/entry/manejan...

Oracle Technology Network Oracle Technology Network Blog Recent Articles Technology Newsletters
Menu

Blogs Home Weblog Login


Feeds

RSS All /Oracle /Personal Comments Atom All /Oracle /Personal Comments The views expressed on this blog are those of the author and do not necessarily reect the views of Oracle. Terms of Use | Your Privacy Rights | Cookie Preferences

13 de 13

20/02/14 20:05

Vous aimerez peut-être aussi