Estructura básica del código

Continuando con el ejemplo anterior, podemos eliminar todas las líneas de código que no necesitamos para el proyecto que deseamos desarrollar. Por ejemplo, no necesitamos el código correspondiente a la creación del botón ni el código asociado al clic de dicho botón. Por tanto el código se podría dejar únicamente con las siguientes líneas:

Screen Shot 2018 01 09 at 23.24.24 3052b

En este tutorial se evitará mostrar el código en modo texto, mostrándolo en su lugar como imágenes con el fin de que te acostumbres a escribir el código, aprendas a resolver errores inesperados y fijes mejor la atención en el código que estás escribiendo.

Deja el código como se muestra en la imagen y comprueba que el funcionamiento es correcto. Al ejecutar la aplicación debe aparecer una ventana vacía como la siguiente:

Screen Shot 2018 01 09 at 21.52.40 6caf9

A continuación se explicará el significado del código anterior en líneas generales.

Paquete de la clase

La primera línea del código, la que contiene la sentencia package, indica el paquete en el que se encuentra el archivo actual. Los paquetes son la manera en la que Java organiza los archivos de código fuente, de manera similar a una estructura de carpetas. Realmente, si usas un explorador de archivos para ver el contenido del proyecto, podrás ver que se ha creado una estructura de carpetas similar al nombre del paquete que se indica, dentro de la carpeta src.

Screen Shot 2018 01 09 at 22.06.06 d01a2 Screen Shot 2018 01 09 at 22.09.00 f5bb4

Un paquete puede contener todos los archivos con código fuente Java que desees, e incluso archivos de otros tipos como imágenes, sonidos, archivos de datos, etc. Puedes crear todos los paquetes que te hagan falta con el fin de que los archivos que formen parte de un mismo proyecto estén organizados de mejor manera.

Importaciones de clases

El siguiente bloque de código, aquel cuyas líneas de código comienzan con la palabra import, contiene una referencia a las clases Java que se están utilizando actualmente en este código fuente.

El lenguaje de programación Java se basa en la utilización de clases. Por defecto, se pueden utilizar una serie de clases propias del lenguaje Java, sin que haga falta importar dichas clases. Es el caso de la clase String, que se utiliza para realizar acciones con cadenas de texto, o la clase Math, que se utiliza para realizar algunas operaciones matemáticas, aunque en el código que tenemos hasta el momento en este tutorial no se utilizan dichas clases.

Los nombres de las clases en Java siempre empiezan en mayúsculas.

En el código que tenemos actualmente, puedes ver que se utilizan las siguientes clases: Application, Stage, StackPane y Scene. Ninguna de esas clases son importadas por defecto en los proyectos Java, por lo que hay que especificar el import correspondiente a cada una de esas clases. Si no se indicara alguno de ellos, se obtendría un error de compilación.

Prueba a eliminar la línea correspondiente al import de la clase Scene. Comprobarás que inmediatamente aparecerá subrayada en rojo cada vez que se utiliza dicha clase en el código. Posiciona el ratón (sin hacer clic) sobre alguno de los términos que aparecen subrayados y podrás ver el mensaje de error que se obtiene: cannot find symbol. Es decir, no conoce la palabra Scene.

Screen Shot 2018 01 09 at 22.41.43 40c0d

Para arreglar este error, dispones de varias opciones:

  • La más complicada sería escribir manualmente toda la sentencia del import, con el inconveniente de que hay que conocer exactamente en qué paquete de java se encuentra definida esa clase. En este caso ya sabíamos que la línea completa era como la siguiente porque la había generado automáticamente el asistente utilizado al crear el proyecto JavaFX:
import javafx.scene.Scene;
  • Por suerte, NetBeans facilita esta tarea. Posiciona el cursor sobre la palabra que contiene el error, y pulsa la combinación de teclas que se indica en el mensaje de error (Alt-Enter  show hits), es decir, que se muestren sugerencias al pulsar las teclas Alt-Enter. Verás que una de las opciones es añadir el import correpondiente: Add import for javafx.scene.Scene.

Untitled 8419c

  • En el caso concreto de errores debidos a la falta del import, también puedes usar la opción Fix imports del menú contextual que puedes abrir en cualquier lugar del código fuente haciendo clic con el botón derecho del ratón. Una ventaja que ofrece esta opción es que va a añadir todos los import que falten en el código fuente actual.

Screen Shot 2018 01 09 at 22.52.36 5abd6

Recuerda todas estas opciones y utiliza la que desees para volver a restaurar la línea del import que se había eliminado.

Declaración de la clase

La sentencia que contiene la palabra class se encarga de declarar el nombre que va a tener la clase Java que estás editando acualmente.

Cualquier conjunto de sentencias Java debe estar contenido en la declaración de una clase, es decir, no puedes escribir una sentencia que realice una determinada acción sin que se encuentre contenida dentro de la declaración de una clase.

La declaración de la clase se ha realizado de la siguiente manera:

public class Main extends Application {

}
  • public: Indica que el código contenido en esta clase podrá ser utilizado inicialmente desde otra clase Java.
  • class: Es la palabra reservada para indicar que se está declarando una clase cuyo nombre debe aparecer a continuación. En esta caso, la clase que hemos llamado Main.
  • extends Application: Hace referencia a que esta clase que se está declarando va a ser una extensión (se va a ampliar el funcionamiento) de la clase Application. La clase Application pertenece al conjunto de paquetes de JavaFX y permite la creación de aplicaciones que utlicen el entorno gráfico de JavaFX.

Puedes observar que la declaración de la clase lleva asociada una pareja de llaves { }. Su uso es obligatorio y deben encerrar todo el código correspondiente a la declaración de la clase.

La utilización de parejas de llaves { } es muy frecuente en Java y se utiliza para marcar el inicio y el fin de un bloque de sentencias.

Cuando vayas desarrollando aplicaciones con códigos más extensos será frecuente que olvides el uso de alguna de las llaves. Borra la última llave del código y observa el error que se produce:

Screen Shot 2018 01 09 at 23.33.21 76ade

Aparece el mensaje reached end of file while parsing, es decir, que se ha encontrado el final del fichero antes de tiempo. No se especifica concretamente que falta una llave. Poco a poco irás viendo que los mensajes de error no siempre son todo lo claro que uno desearía.

En estos casos además no hay un opción automática para resolver el problema como sí ocurría con los import. Vuelve a escribir la llave manualmente en lugar adecuado y resuleve así el error.

Declaración del método start

Todas las sentencias que vayan a realizar una determinada acción en una aplicación Java deben estar contenidas dentro de lo que se denomina un método. El código contenido en un método podrá ejecutarse en un determinado momento, cuando se realice una llamada a él.

En el código que estás manejando se encuentra la declaración del método start. Este método es invocado de manera automática cuando se inicia la aplicación. Por tanto, todo el código contenido dentro del método start se ejecutará cuando se inicie la aplicación.

En una clase Java puedes declarar todos los métodos que desees y con el contenido que sea necesario. Puedes asignarle cualquier nombre a los métodos teniendo en cuenta que se diferencian las mayúsculas y minúsculas, que deben empezar con letras, que no se admiten los caracteres especiales más comunes excepto el guión bajo (_) y el dólar ($) y que puedes usar dígitos numéricos siempre que no sea al inicio. Se pueden usar caracteres acentuados aunque no lo recomendaría, ya que puede ocasionar problemas si se exporta el código a equipos que utilicen otros conjuntos de caracteres en el sistema.

Se acostumbra a que los nombres de los métodos empiecen en minúscula y las demás palabras que formen parte del nombre se inician con mayúsculas, por ejemplo: esteEsUnEjemplo.

El caso del método start es especial, porque no podrás cambiar su nombre, ya que Java lo buscará con ese nombre para ejecutar su contenido al inicio de la aplicación.

Este método se encuentra predefinido dentro de la clase Application (recuerda que la clase que estás creando es una extensión de Application). Por tanto, al declarar de nuevo ese método dentro de la clase Main que has creado, se está sobreescribiendo el contenido original de este mismo método que se contenía en la clase Application. Por este motivo, se utiliza la anotación @override antes de la declaración del método, es decir, para indicar que este método está sustituyendo al método que esta predefinido en la clase Application que estás extendiendo.

Elimina esa anotación y verás que no se produce ningún error severo de compilación, por lo que se puede ejecutar correctamente la aplicación. Observa que aparece un subrayado amarillo y un icono de advertencia como aviso.

Screen Shot 2018 01 10 at 00.35.47 cbb3d

Este error puede solucionarse escribiendo de nuevo manualmente la anotación, utilizando la reparación automática que se sugiere pulsando Alt-Enter, o desde el icono amarillo del lateral.

Observa que a continuación del nombre del método aparece entre paréntesis lo que se denomina la declación de un parámetro. En este caso aparece como Stage primaryStage. Es decir, se está declarando la variable primaryStage como perteneciente a la clase Stage. Poco irás conociendo más sobre las declaraciones de variables y parámetros en Java.

La variable primaryStage

La variable primaryStage, que como acabo de comentar está declarada como un parámetro del método start, se utiliza dentro del resto del código, por lo que debes conocer que esa variable hace referencia a todo el marco de la ventana que se va a utilizar para mostrar el resultado de la ejecución de la aplicación.

Se ha utilizado en las siguientes líneas:

Screen Shot 2018 01 10 at 00.49.35 6212b

La primera línea puede ser bastante clara. Especifica el texto del título que va a aparecen en la barra de título de la ventana.

Screen Shot 2018 01 10 at 00.52.38 75cd0

La palabra setTitle es el nombre de un método que se encuentra declarado dentro de la clase Stage de JavaFX. Recuerda que la variable primaryStage aparece declarada de tipo Stage, por tanto, la variable primaryStage se puede utilizar para invocar (o llamar) a cualquiera de los métodos declarados en la clase Stage. Para conocer todos los métodos de la clase Stage que se pueden utilizar, escribe en una nueva línea la variable primaryStage seguido de un punto y espera un instante. Aparecerá una lista de todos los métodos disponibles.

Screen Shot 2018 01 10 at 01.01.04 08276

Puedes ver que aparece el método setTitle que acabo de comentar, y observa que se muestra una pequeña ayuda para conocer cómo debe usarse. Al aparecer setTitle(String value) está queriendo decir que en la llamada a este método se debe indicar como parámetro (entre paréntesis) un String, es decir, una cadena de texto.

Los valores literales para las cadenas de texto en Java (String) se deben encerrar entre comillas dobles, por ejemplo, "Esto es un texto".

Por tanto, si en la llamada al método setTitle se le pasa como parámetro algo que no sea un String, o algo compatible con ello, se obtendrá un error de compilación. Prueba a pasar como parámetro un valor numérico.

Los valores literales para los números en Java se deben ir sin comillas de ningún tipo, si tiene parte decimal se separa con un punto, y no se puede utilizar ningún separador de millares, por ejemplo: 27354 o 72.386 o -727.

Screen Shot 2018 01 10 at 01.11.39 48f95

En el mensaje de error se especifica que int (valor numérico entero) no se puede convertir a String (cadena de texto).

Deja como título, entre comillas dobles, el texto que desees para la ventana de la aplicación.

La variable primaryStage también se utiliza en el código empleado para asignar un Scene con la llamada al método setScene. En el siguiente apartado se comentará para qué sirve el Scene.

La última acción que se realiza en el método start es la llamada al método show de Stage. Esta sentencia muestra en pantalla la ventana y todo el contenido que se le haya asignado.

Prueba a eliminar esa línea y ejecuta el proyecto. No obtendrás ningún mensaje de error, no se mostrará nada, pero la aplicación se estará ejecutando. La mejor manera de parar la ejecución en esta situación es usar el botón X que aparece en la parte inferior de NetBeans, al final del texto running... Puedes usar este botón siempre que necesites cerrar una aplicación que haya ocasionado algún problema y no se pueda cerrar de la manera habitual.

Screen Shot 2018 01 10 at 01.20.48 9c6a8

Vuelve a dejar la línea como estaba para que pueda funcionar correctamente la aplicación.

La variable scene

En el código también se encuentra una variable scene de la clase Scene.

Observa que a las variables se les asigna nombres que empiezan en minúsculas mientras que los nombres de las clases empiezan en mayúsculas.

Scene scene = new Scene(root, 300, 250);

Las escenas o Scene en JavaFX hacen referencia al área donde se almacenará el contenido de la ventana de la aplicación, es decir, toda la parte blanca que ha aparecido al ejecutar hasta ahora la aplicación.

Screen Shot 2018 01 09 at 21.52.40 6caf9

La palabra reservada new de Java se utiliza para crear un objeto de una determinada clase. En este caso se está creando un objeto de la clase Scene al escribir new Scene(). Es decir, se está creando una escena, se está creando un área de contenido para una ventana.

Ese objeto Scene es conveniente almacenarlo en una variable de ese tipo. Por eso se declara la variable scene como: Scene scene.

Si unimos ambas cosas estaremos creando un objeto de la clase Scene y guardándolo en la variable sceneScene scene = new Scene().

Pero para crear un objeto Scene es necesario indicar una serie de parámetros. Si sitúas el cursor justo detrás de new Scene y pulsas la combinación de teclas Ctrl+Espacio, podrás ver las distintas posibilidades que ofrece la clase Scene para crear objetos indicando distintos tipos y cantidad de parámetros.

Screen Shot 2018 01 10 at 01.42.46 a2a7d

Puedes ver que hay 6 posibilidades diferentes para crear objetos Scene. En este código se ha empleado la tercera opción, porque es la que utiliza 3 parámetros:

  • Parent root: Hace referencia al contenedor principal que va a alojar todos los elementos gráficos que se incluyan en la ventana de la aplicación. En el siguiente apartado podrás conocer más sobre ello.
  • double width: Ancho (número de puntos) que va a tener la ventana. Se debe indicar un valor numérico que puede tener decimales.
  • double height: Altura (número de puntos) que va a tener la ventana. Se debe indicar un valor numérico que puede tener decimales.

En Java se utiliza el tipo de dato double para representar valores numéricos con decimales. También se puede utilizar el tipo float que consume menos espacio de memoria pero tiene menos precisión en los cálculos.

La variable root

Todos los elementos gráficos que se deseen incluir en la ventana (formas geométricas, textos, campos de texto, imágenes, etc), deben agruparse dentro de lo que podemos llamar contenedores (o layouts en Inglés).

En JavaFX podemos utilizar distintos tipos de contenedores, cada uno de ellos correspondiente a una clase determinada de JavaFX. En el artículo Working With Layouts in JavaFX o en Iniciando con JavaFX: Layouts - Ejemplos de uso puedes ver las diferentes clases de JavaFX que existen para crear contenedores.

En el código que estás utiizando se utiliza un contenedor de tipo StackPane. En la siguiente línea puedes ver cómo se ha creado un objeto de esa clase (new StackPane()) y se ha almacenado en la variable root de ese mismo tipo (StackPane root):

StackPane root = new StackPane();

Este tipo de contenedor (StackPane) tiene la característica de que todos los elementos que vaya a contener se organizan en forma de pila (stack), es decir, uno sobre otro. Para nuestro proyecto seguramente no será el tipo de contenedor más adecuado, ya que no queremos que la pala del juego se apile justo encima de la pelota ni ésta justo encima del marcador, etc. Vamos a necesitar que cada elemento se pueda colocar libremente en cualquier posición dentro del contenedor.

En el siguiente artículo empezaremos a ver cómo hacerlo.