GUI Ejemplo - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
Voy a grabar esta clase, por lo tanto, si habláis, me dais vuestro consentimiento para que grabe vuestra voz.
00:00:00
Entonces, hoy vamos a ver un proyecto un poquito completo, ¿vale?
00:00:07
De una pequeña aplicación sencilla sobre gestión de alumnos.
00:00:13
Por ejemplo, añadir, quitar, vamos a ver si nos da tiempo.
00:00:19
Pero al menos añadir un alumno y mirar qué alumnos hemos metido, ¿vale?
00:00:23
El objetivo de esta aplicación es principalmente hacer el interfaz gráfico, el interfaz gráfico sencillo, repasaremos un poquito los ficheros quizás, un poquito las colecciones, pero muchas cosas que vamos a hacer aquí explícitamente las haré mal o de una forma muy sencilla para mantener la dificultad del ejercicio lo más baja posible.
00:00:28
algunos, el usuario me pone un nombre
00:00:54
y a lo mejor, o la edad del alumno, hago para decir, pues en vez de la edad
00:00:59
me pone una string de caracteres y explota
00:01:03
todo, pues a lo mejor eso no lo compruebo para evitar
00:01:07
que se añada un montón de código
00:01:11
un montón de comprobaciones que ya hemos visto en otro momento
00:01:14
y que no quiero que ahora vayan a ser de sobrecarga
00:01:18
con respecto a lo que tenemos que aprender ahora, ¿vale?
00:01:23
Eso no quita que en un programa hecho bien habría que hacer comprobaciones,
00:01:25
habría que recoger posibles excepciones, habría que hacer un poquito de control
00:01:29
para que esto funcione.
00:01:35
Eso no quita que luego en casa vosotros podáis rehacer este ejercicio
00:01:36
y hacerlo bien, hacerlo lo más bonito posible, hacerlo guay para vuestro contexto
00:01:40
de alumno que tienen que aprender a hacer estas cosas, ¿vale?
00:01:46
Entonces, algunas cosillas, si os ocurren, pero aquí deberíamos comprobar que no sé qué, pues lo podéis decir, queda grabado, he ido allí, si veo que hay una cosa interesante para ese contexto, digo sí, vale, hagámoslo, si veo que todavía no, pues digo, mirad, esto sí, habría que comprobarlo, como buena idea, pero no lo vamos a hacer en este contexto, ¿vale?
00:01:50
entonces vamos a crear un nuevo proyectito yo o vamos a elegir nuestro javascript project esto
00:02:11
aparece porque tenemos instalado el plugin fx clips vale si no no aparece este de aquí se puede
00:02:21
hacer si se puede hacer pero esto ya me da un poquito una mano porque me da una estructura ya
00:02:34
hecho. Si no os aparece esta parte de aquí, esta carpeta de JavaFX hay que tener que instalar ese
00:02:38
plugin. Lo llamamos GUI escuela, GUI alumnos o GUI escuela. Aquí tenemos nuestra estructura ya un
00:02:44
poquito hecha, donde sustancialmente nos pone una aplicación, nos pone un main y un CSS vacíos. El
00:02:59
El main no es el que nos interesa, es un main un poquito distinto.
00:03:07
Este main de aquí nos serviría para construir sustancialmente una aplicación desde cero
00:03:11
sin usar el SXML y sin usar el SimBuilder, que se puede hacer, ¿vale?
00:03:18
Es simplemente que cualquier opción, cualquier botón que creo lo debería crear aquí directamente
00:03:26
como en formato de texto, ¿vale? En formato de código.
00:03:33
y se puede hacer, yo puedo decirle
00:03:37
mira, tráeme un nuevo
00:03:39
combo box
00:03:40
y este combo box posicionamelo en este
00:03:42
punto y que sea grande este tamaño
00:03:45
todo por línea de comando
00:03:47
por comandos Java, vale
00:03:48
solo que pierdo un poco la visión de que
00:03:50
estoy haciendo, entonces con
00:03:52
el scene builder es mucho más sencillo
00:03:54
si, entonces
00:03:56
para eso en vez de utilizar
00:03:58
este main que me da, pues tengo que utilizar
00:04:00
un main donde sustancialmente carga
00:04:02
ese fichero, vale, ahora lo hacemos
00:04:04
entonces la primera cosa que veo que aquí faltan a estas clases estas clases no me la reconoce
00:04:06
dice dónde están no sé qué son porque me falta ponerle esas librerías donde dentro aparecen las
00:04:14
distintas clases que pertenecen a JavaScript entonces me voy a mi proyecto botón derecho
00:04:20
sobre el proyecto, me voy a propiedades, java build path, vale, y aquí dentro de librerías me voy a
00:04:28
módulo de path, módulo de path, le digo añadir jarra externos, esto lo tendréis que hacer muy
00:04:37
probablemente en el examen, vale, o esto o lo de maven que todavía no lo es, aquí busco la carpeta
00:04:44
que he bajado, esta de aquí, que está el CDK de Java CX, y dentro de la carpeta librerías me vienen estos JAR.
00:04:52
Estos son los JAR que tenemos que incluir a nuestro proyecto para que funcione, ¿vale?
00:05:02
Una vez añadidos, le doy a Play and Close, y entonces estas cosas de aquí ya se reconocen,
00:05:07
porque los importes que he hecho, pues ya funcionan, ¿sí?
00:05:14
Aquí luego utilizaremos otras cosas
00:05:18
Otras cosillas para aquí y para allá
00:05:21
Como información al procesador, al preprocesador
00:05:22
O otras clases
00:05:25
Cuando no las ve, pues tendré que decirle
00:05:26
Mira, impórtala, no creando una clase
00:05:28
Me va siempre importándola
00:05:30
Desde estas clases ya hechas
00:05:32
Porque quiero una cosa en concreto
00:05:35
¿Dudas?
00:05:36
Vale
00:05:39
Entonces, si yo la lanzo
00:05:39
Ahora ya me debería funcionar
00:05:42
Pero lo que me crea
00:05:44
Es una ventanita
00:05:46
vacía. ¿Vale?
00:05:47
Ese está aquí. Entonces, yo
00:05:50
aquí podría crear ahora un botón,
00:05:51
ponerlo en esta posición de aquí
00:05:54
y pillando el espacio
00:05:56
asumiendo que este es 0,0
00:05:57
como se hace en
00:05:59
HTML, ¿no? Que lo habéis
00:06:02
hecho por ahí, habéis
00:06:03
hecho algunas cosas con
00:06:05
JavaScript.
00:06:07
De mover algún objeto,
00:06:10
de posicionar algún botón,
00:06:11
no sé si lo habéis hecho.
00:06:14
Se puede hacer utilizando DOM,
00:06:16
pero nosotros queremos hacer esto de forma gráfica por lo tanto esto me interesa
00:06:17
vale para completar empezar a hacer la cosa necesito al menos otro fichero vale entonces
00:06:24
me voy al botón derecho y añado un file en realidad por aquí está esto yo quiero vale
00:06:30
el new fxml documento pero por alguna razón misteriosa funciona mal por lo tanto nosotros
00:06:40
lo hacemos como añadir un fichero nuevo que te digo yo que es y pongo aquí lo que me da la gana
00:06:46
vista.fxml interfaz.gui.fxml importante que cuando ahora cargáis este fichero de aquí este
00:06:53
fichero en el comando que carga el fichero pues tenga gui.fxml con un fichero para ir a
00:07:08
pillarlo. Si no lo pilláis, si no metéis eso, pues claramente no lo encontrará y te dirá que no puede.
00:07:16
También se enfada porque este de aquí debería ser un fichero xml y está vacío por lo tanto
00:07:21
te dirá que hay errores. También necesitaremos lo que es un controlador. Entonces ponemos aquí
00:07:29
un GoogleController, por ejemplo, que sustancialmente nos hará una clase donde pondremos todos los
00:07:35
métodos para que cuando doy un botón, muevo algo o tengo que hacer algo, pues aquí está
00:07:44
la aspirón que tengo que ejecutar. Luego tendré que sustancialmente de alguna forma conectar las
00:07:50
tres cosas o sea por un lado el xml por otro lado el controlador y por otro lado la lógica de mi de
00:07:58
mi programa de lo que hace vale entonces para lo que queremos hacer nosotros es gestión de alumnos
00:08:07
con un gestor pues no existe tenemos también otras clave otras clases que por ahora yo pongo todo
00:08:13
aquí dentro para que sea más sencillo pero estaría bien que quizás estuvieran en paquetes distintos
00:08:20
Uno que modeliza a los alumnos, por ejemplo, y otro que modeliza el gestor del alumno.
00:08:25
El que añade, que tiene la lista de alumnos, que puede añadir, puede remover, puede cambiar la cosa.
00:08:32
Sostancialmente, los ejercicios que hacíamos antes.
00:08:38
Lo que hemos hecho hasta ver la gráfica de UDF sería una clase como esta que vamos a hacer.
00:08:41
Queremos, justo para completarlo, tendremos una clase alumno y tendremos una clase.
00:08:47
gestor alumno gestor si estás hablando un poquito las clases que vamos a utilizar en esta en esta
00:08:56
en este proyecto sí botón derecho ni un philip botón derecho sobre la aplicación ni un philip
00:09:08
y luego allí con la extensión s xml vale cuidado que a veces ponéis xml
00:09:28
luego no funciona, sobre todo si no ponéis fxml cuando dais botón aquí no sale esto de abrir con
00:09:33
scenebuilder vale más o menos lo tenemos vamos a abrir el scenebuilder vale vamos a crear algo
00:09:39
entonces abro el botón derecho sobre el gui.fxml open with scenebuilder si lo he configurado bien
00:09:51
vale, os acordáis que tenía que decirle dónde está el Scene Builder, pues debería abrirse esto.
00:09:59
Vale, los cambios que hago aquí, al guardarlos, se guardarán dentro gubi.fxml. Estoy editando esto,
00:10:05
por ahora no hay nada. Dudas hasta aquí. Nuestro objetivo es que tengamos una interfaz gráfico que
00:10:12
tiene dos pestañitas, una pestañita que me permite añadir nuevos alumnos y otra pestañita que me
00:10:23
permite browser navegar sobre los alumnos que ya existen vale entonces tengo que elegir un
00:10:29
contenedor vale normalmente las cosas así están hechas con hay paneles hay corchos imaginaos
00:10:36
corcho del resto de la pared donde yo pongo controles botones cosas para escribir cosas
00:10:44
para leer cosas la combo box check box radio button lo que me hace falta vale en algunos
00:10:51
casos necesito uno solo en algunos casos necesito varios hay opciones para que pinche un botón y se
00:10:59
abre una ventana cosas y por ahora lo mantenemos sencillos y hacemos simplemente una única ventana
00:11:05
que tenga dos pestañas vale para esto nosotros la otra vez utilizamos como contenedor el pain
00:11:10
que es como un panel básico, pero además de esto usáis scroll pane, flow pane, border plane y cosas
00:11:17
por el estilo que mañana nos enseñáis vosotros cuando yo no trabajo y uno de ellos es el tab pane.
00:11:24
El tab pane es un panel pensado para que tú puedas ponerle dentro tabs. Las tabs son estas
00:11:30
pestañas. Entonces si tú usas un tab pane luego puedes añadir cuantas tabs te da la gana y en
00:11:36
cada tab montar una interfaz gráfica distinta. Entonces nosotros pillamos el campaign, el que
00:11:42
no es empty aunque luego son parecidos, lo pongo aquí y me sale esta cosa aquí. Ya está una
00:11:49
ventana que tiene aquí arriba dos pestañitas y yo crearé en una todo lo que me sirve para añadir
00:11:58
un nuevo alumno, en una me daré todo lo que me sirve para ver el contenido de un alumno, por ejemplo.
00:12:07
Empezamos con la primera, pues aquí ponemos crear alumno, por ejemplo.
00:12:14
Entonces, esta de aquí será la pestañita que cuando pincho pues me permite crear un alumno.
00:12:22
Para que crea un alumno tengo que saber qué es un alumno. Entonces, ¿qué nos interesa
00:12:29
interés de un alumno. Nombre. No nos compliquemos. Lo que quiero decir es que aquí cada alumno
00:12:35
debería tener un identificador, el identificador debería ser único, cuidado con eso, pero
00:12:55
pues mantengámoslo sencillo, lo hago todas estas cosas de las que ya hemos hablado y
00:12:59
que funcionaban en los ejercicios y ya hemos hecho, pues podéis aplicarlo aquí. Pero
00:13:03
no vayamos a, hagamos un alumno con 56 datos, que así cada vez que tenga que hacer una
00:13:07
prueba, tengo que poner 56 datos. No, algo muy básico. Pero vamos a ir, o double nota media.
00:13:12
Ya está. O sea, muy sencillo. Tanto, ahora veremos que hablaremos dos veces, haremos una cosa para
00:13:20
el nombre, una cosa para la media, pues si tengo que hacerlo 56 veces para los 56 datos, pues eso
00:13:26
es para vosotros que tenéis mucho tiempo libre. ¿Vale? Entonces, estos dos serían para crear una
00:13:32
luego claramente se podría complicar cuantos da la gana botón derecho surge a un constructor
00:13:38
me costó donde derecho surge a un tri vale para que si quiero poner un string con solo
00:13:46
Podría hasta toquetear el equals, el hashcode y todas estas cosas dependiendo de lo que quiero hacer con estas cosas.
00:13:58
Repito, lo mantengo lo más sencillo, si necesito algo volveré aquí a toquetear estas cosas.
00:14:11
Por ahora yo creo que con esto es suficiente, más o menos.
00:14:18
Podría esto escribirlo de otra forma, pero por ahora lo dejo así para que ya veremos cómo sale y si me gusta o lo quiero poner de otra forma.
00:14:22
Por ahora, muy básico.
00:14:33
Simplemente para que sepa que para crear un alumno necesito estos dos datos.
00:14:35
Por lo tanto, en mi interfaz necesito algo donde escribir el nombre, algo donde escribir la nota media
00:14:38
y algo donde poner un botón para decir lo que hay hasta todo guarda
00:14:48
voy a cambiar esto ahí no está final por qué por tonterías pero porque luego cuando llegaremos a
00:14:59
allí en vez de la toma usamos el punto para explotar programas que supuestamente pongamos
00:15:15
enteros, tanto es el primer ejemplo,
00:15:20
lo mantenemos lo más sencillo posible.
00:15:22
¿Vale? Ok.
00:15:24
¿Cómo lo hago? Pues necesito
00:15:26
algo donde pueda escribir el nombre.
00:15:28
¿Dónde se escribe? Para escribir
00:15:30
hay varias cosas, pero nos interesa
00:15:32
principalmente el textarea
00:15:34
o textfield. ¿Qué diferencia
00:15:36
hay entre textarea y textfield? ¿Lo sabéis?
00:15:38
¿Lo habéis visto en el input de...
00:15:40
Bueno, concretamente
00:15:43
en HTML el textarea
00:15:44
no es un input, pero existe.
00:15:46
¿Lo habéis visto?
00:15:48
nosotros usamos TextField
00:15:48
pongo un TextField aquí
00:15:52
pongo otro TextField
00:15:54
aquí
00:15:57
y luego
00:15:57
aquí pondré el nombre
00:16:01
aquí pondré la nota
00:16:03
final hemos dicho
00:16:05
y un botón aquí
00:16:07
para que cuando lo pinche
00:16:08
pues diga vale créame un alumno
00:16:11
y guarda
00:16:13
estas son las cosas digamos
00:16:14
fundamentales que necesito
00:16:17
Luego, para hacerlo un poquito más bonito, lo que puede hacer es usar también labels para decir, por ejemplo, que aquí me diga que este es el nombre y otro label que me diga que esta es la nota media, si no, no sé qué es, ¿vale? Y aquí lo pongo. Esto es nombre, dos puntos. Y lo hago un poquito más grande para que se vea.
00:16:19
nombre de los puntos y es todo lo nuevo aquí y aquí no está
00:16:38
un deseo porque debería trabajar en esto de hacerlo más bonito que quede bonito hacerlo
00:16:57
más así aquí a de botón más grande para que sea más fácil de pinchar y poner aquí añade al alumno
00:17:08
hasta un poco
00:17:25
si son tres cosas es feo es normal que quede feo vale os recuerdo también que para que esto sea
00:17:26
más bonito también a nivel gráfico puede utilizar css vale entonces lo que vamos a hacer nosotros
00:17:45
es por ahora lo vamos a hacer así luego cuando esto funcione pues le hacemos una foto a esta
00:17:52
cosa aquí le decimos a charly pt oye mira anunciarse para que esto haga más bonito y él
00:17:58
me creará un css para que se van parezca más profesionales más bonito y ese punto
00:18:04
copio ese css y vamos a ver si funciona muy bien entonces esta sería la primera pantalla vamos a
00:18:08
trabajar con esta es simplemente que pongo el nombre pongo la nota y le doy el intro y lo
00:18:18
¿Vale? Entonces, ¿qué necesito más aquí? Primero, voy a leer esto y esto. O sea, lo que está escrito aquí y aquí se tiene que leer cuando pincho esto.
00:18:23
Entonces, necesito identificarlos estos dos. Por ejemplo, esta cosa aquí no cambiará. Esta label de aquí no la voy a cambiar en la vida.
00:18:33
Entonces, no hace falta que la identifique. En ningún momento diré, oye, píllame esa label y cámbiale el color.
00:18:41
porque podría hacerlo, pero en mi programa no, ¿vale?
00:18:47
Pero sí en algún momento tendré que decir, lo que está dentro de este text field, píllamelo, ¿vale?
00:18:50
Para eso lo tengo que identificar, para identificarlo le tengo que dar un nombre, ¿vale?
00:18:57
Entonces, este de aquí lo pincho, me voy a code, y aquí donde está el fx dos puntos id,
00:19:02
le doy un identificador, por ejemplo
00:19:11
esta es nombre
00:19:13
y este de aquí
00:19:15
es nota
00:19:17
¿tengo que identificar
00:19:19
botón?
00:19:23
no, porque el botón me interesará
00:19:26
cuando lo pincho, hace algo
00:19:28
pero no cambia o no tengo
00:19:29
que ir a pillar ese control
00:19:32
para hacer algo sobre ese control, por lo tanto
00:19:34
no me interesa, si al pincharlo
00:19:36
quisiera cambiar el
00:19:38
lo que está escrito diciendo
00:19:40
muy bien, lo has hecho, o cosas por el estilo
00:19:42
pues entonces sí lo debería identificar, ¿vale?
00:19:44
No devuelve nada
00:19:49
este de aquí para allá. Podría poner aquí un label escondido que no ponga
00:19:52
nada para que cuando pinche añade alumno me ponga alumno añadido o algo
00:19:56
por el estilo. Pero esas son cosas avanzadas, por ahora son avanzadas.
00:20:00
Son cosas sencillas, pero no quiero sobrecargar, ¿vale? Entonces, vale,
00:20:03
muy bien, esto está pillando forma.
00:20:08
necesito ahora decir que cuando pinche aquí pues de alguna forma él sepa que haga algo
00:20:11
vale entonces como lo hago esto no lo he guardado todavía debería guardarlo más a menudo pero
00:20:21
entonces el controlador me creo una
00:20:33
y le digo que este de aquí pertenece a fxml vale esta cosa de aquí me está diciendo hoy mira
00:20:37
esto es algo especial no es un método cualquiera es un método que luego irá relacionado con fxml
00:20:56
por lo tanto, en los editores de fxml quiero poder ver esta opción de aquí, en un cierto sentido.
00:21:07
Fijaos que se enfada, dice no, no lo quiero, entonces tú le dices, mira, añádeme requires.fx al módulo jave.info, a este módulo de aquí, ¿vale?
00:21:14
Entonces, tú lo añades y con un poco de suerte te va a enfadar.
00:21:23
luego importas también esta cosa aquí y ya está soy feliz vale entonces aquí fijaos que no hace
00:21:31
nada pero es para que quede aquí este segundo vale entonces si ahora voy aquí y me voy a
00:21:40
controller abajo a la izquierda con un poco de suerte se pincho aquí me aparece la aplicación
00:21:48
está de aquí la clase es agua y controles porque él se da cuenta que al ponerle este arroba pues
00:21:59
hay algo que puede trabajar con esto aquí y lo añade diciendo y mira hasta allí la puedes
00:22:08
utilizar es una clase que puedes utilizar como controles sustancialmente le están diciendo esto
00:22:15
es la parte digamos visual y quien controla quien pilla los eventos y hace algo es esta clase de
00:22:19
aquí. Posiblemente podéis añadir más de un control, pero obviamente no.
00:22:28
Entonces, si os aparece, la seleccionáis y ya está.
00:22:34
Se queda conectado que esta interfaz gráfica de aquí, pues tiene como
00:22:39
controller, llamarán los métodos de esta clase de aquí.
00:22:45
Si lo habéis hecho bien, cuando pincháis aquí y vais a onAction, os aparecerá aquí la
00:22:48
posibilidad de elegir los métodos que están dentro de esa clase ahora que no
00:22:55
aparece lo que os aconsejo yo si no aparece es hacer esta clase porque
00:23:00
esta clase no está no no parece vale guardar lo que tenéis aquí cerrar el
00:23:07
sin builder y volver a abrirlo porque a veces necesita tener todo el controlador
00:23:15
entonces no lo ve y cuando añades el controlador
00:23:23
él todavía se queda con
00:23:25
lo que había cargado antes y entonces no ha cargado
00:23:27
que existe este controlador.
00:23:29
Si en vez aparece
00:23:32
lo ponéis aquí, le ponéis aquí
00:23:33
que su acción es
00:23:35
el añadir, así sabéis que
00:23:37
cuando pincháis este botón
00:23:39
lo que hace es añadir.
00:23:41
O sea, cuando pincharé este botón
00:23:44
se ejecutará este método de aquí.
00:23:45
Si queréis, para que
00:23:48
haga algo, le ponéis un ciso
00:23:49
de pulsado guardo aquí guarda acá guardo arriba guardo todo acordaos de que por ahora yo no he
00:23:51
guardado nada y por lo tanto si me voy a mi gui sigue vacío no ha hecho nada todavía vale esto
00:24:04
es hecho mal debería es guardar más a menudo pero hay que yo quiero que veáis que ahora es cuando
00:24:10
se guarda vale entonces en el momento en que este de aquí decidís guardarlo sabe esto se ha guardado
00:24:16
en FX y esto se debería actualizar. Si no se actualiza, lo actualizáis vosotros pulsando F5, ¿vale?
00:24:23
O pulsando Edit, ¿dónde está? File, Edit, Refresh, por aquí, File, File, File,
00:24:33
a estar aquí con derecho y reflejo
00:24:45
tened en cuenta esto hacerlo más a menudo porque a veces hace el cambio por aquí y
00:24:52
no se ve vale la forma de refrescar esto con lo que se ha hecho fuera es con f5 la forma de
00:24:59
refrescar esto con lo que se ha hecho fuera es no lo sé si queréis estar seguro pues lo que hacéis
00:25:08
guardáis todo cerráis y abrís otra vez de todas formas tened en cuenta que también
00:25:13
no se suele trabajar en paralelo hago algo aquí algo aquí algo aquí algo aquí algo aquí
00:25:21
no pues hago la interfaz gráfica cuando tengo la interfaz gráfica me paso a hacer el back end
00:25:25
si necesito algo vuelvo a tuquetear la parte gráfica pero no es que añado uno y voy a hacer
00:25:32
su código añado uno y voy a hacer su código antes uno piensa un poquito lo que tiene que hacer de
00:25:38
pensadlo vosotros si queréis empezar por el backend hacer la parte que funcione todo y cuando ya
00:25:42
funciona todo le pongo un interfaz gráfico porque sé que puedo pedir o si quiero hacer un interfaz
00:25:49
gráfico para ver que se puede pedir y luego hago que funcione entonces si esto está bien yo tengo
00:25:53
un error y no sé de qué es el alumno, por qué alumno tienes un error. Aquí, media.
00:26:01
Vale, veis que lo he guardado, voy a cerrarlo, si me lo voy a abrir, me peta todo el rato. Borra.
00:26:07
Probablemente has guardado algo malo y ahora al recargarlo no lo entiendo. Posiblemente tú
00:26:17
lo has guardado y luego has modificado algo malo y entonces al cargarlo no lo mira.
00:26:25
borrar la carpeta lo que es lo que puede ser aparte de algunos
00:26:31
problemillas así. Por favor, chicos.
00:26:52
La similar me ha dado
00:26:55
a mí también a veces de cosas
00:26:56
de arrastrar esto y tardar
00:26:58
un minuto en hacerlo. No sé por qué.
00:27:00
Lo más probable es que
00:27:03
estos programas
00:27:05
son relativamente delicados. En el sentido que
00:27:06
ellos tienen que interpretar
00:27:08
esta cosa de aquí y a partir de
00:27:10
esta cosa aquí transformarla en
00:27:12
esta cosa aquí. ¿Vale? Cuanto
00:27:14
más sea complejo esto, más es probable
00:27:16
que se guíe. ¿Sí? Normalmente
00:27:18
las cosas, si la ha hecho él, no debería dar este problema, ¿vale? Pero si, por ejemplo, ha metido hasta aquí
00:27:21
y yo, sin darme cuenta, he borrado algo aquí, he cambiado algo aquí, cuando él intenta interpretarlo,
00:27:28
como no es código que ha hecho él, pues se puede liar. O si vosotros decís, no, esto lo cambio a mano,
00:27:33
pues se ponga aquí 115 en vez de otra cosa, pues llega un momento que a lo mejor te quites algo
00:27:37
que cuando él intenta interpretarlo no se encuentra con lo que normalmente es y puede que se lie un poco, ¿vale?
00:27:41
Normalmente no debería hacerlo. Lo guardo, lo cierro y lo vuelvo a abrir.
00:27:49
Perfecto. ¿Qué os pasa? Si hacéis una cosa sencilla, rehacer esto son 20 segundos.
00:27:57
Pasará nada. Borro el fichero, lo limpio e intento hacerlo otra vez. Si estás haciendo un programa un
00:28:19
poquito más más complejo es hacer copias o sea una interfaz mientras que funciona hacéis una copia y
00:28:26
cuando hacéis la modificación de eso lo hacéis en un fichero distinto para que tengáis un backup que
00:28:33
funciona es el último que funcionaba y los cambios lo hacéis en un fichero nuevo cuando llega un
00:28:39
momento que el fichero nuevo explota pues tenéis siempre un paso anterior para decir no mira esto
00:28:44
me funciona vuelvo a ese de allí y vuelvo a hacer sólo lo último que he hecho no hagáis cambios
00:28:49
siempre sobre este aquí porque lleva un momento
00:28:55
que es un poco como cuando
00:28:57
yo os decía, cuando vosotros en un examen estáis
00:28:59
haciendo varios métodos y habéis
00:29:01
hecho un método y este método funciona
00:29:03
y ahora empezáis otro método
00:29:04
pues guardad lo que habéis
00:29:06
hecho hasta ahora porque si el nuevo método
00:29:09
no lo conseguís hacer y os sale
00:29:11
un asco y no
00:29:12
arranca ni siquiera el programa
00:29:14
siempre podéis, tenéis la opción de
00:29:16
entregar la última versión
00:29:19
que si arrancaba y es más bonito
00:29:20
que entregar algo que le da el player
00:29:23
no funciona. ¿Entiendes?
00:29:24
Entonces podéis gestionar. Ahora, no lo sé
00:29:28
qué habéis hecho vosotros, que son
00:29:30
tres clics y ya os habéis cargado
00:29:32
el programa. Pues, no lo sé.
00:29:34
No sé.
00:29:37
Era un tío.
00:29:38
Vale. Entonces,
00:29:42
si
00:29:44
todo esto funciona,
00:29:46
ahora mismo
00:29:49
yo lanzo esto
00:29:50
y ¿qué pasa?
00:29:52
nada sale otra vez la interfaz está aquí básica porque no hay modificador main vale en el main en
00:29:52
algún momento del main le tengo que decir oye mira yo quiero a que tú crees aquí un interfaz
00:30:02
gráfico que pero no es esto es un interfaz gráfico basado sobre este fichero de aquí
00:30:10
vete a este fichero de aquí y úsalo vale para eso tengo que decir cárgalo entonces esto que
00:30:18
probablemente muy probablemente en un ejercicio de examen os lo pasaré os lo pondré por algún
00:30:26
lado porque de memoria no me lo sé se basa sobre esta cosa aquí vale tú tienes un fxml loader que
00:30:33
es un objeto que lo que hace es pillar un fichero y luego le puedes decir cárgalo vale una vez
00:30:41
cargado pues setas la escena, setas cuál es el título de la ventana y
00:30:47
sustancialmente la haces ver. Esto debería ser el start nuestro, entonces me lo
00:30:53
copio y lo sustituyo.
00:31:00
Fijaos que aquí está usando stage, el primary stage, mientras aquí dentro usa stage, entonces o cambio esto por esto, o cambio esto por esto, ¿vale?
00:31:10
Pero bueno, esto se llama stage, ¿sí? Entonces, ¿qué hace esto aquí? Dice, mira, crea un objeto loader asociado con este fichero.
00:31:29
yo no lo tengo este fichero, mi fichero se llama así
00:31:39
entonces
00:31:41
ahora tengo un objeto
00:31:44
que puede cargar, vale
00:31:46
y le digo, oye mira
00:31:48
esta es la raíz
00:31:49
de toda mi estructura de
00:31:51
controles y paneles
00:31:54
y cosas por el estilo, vale
00:31:56
esta raíz es
00:31:58
cárgala desde este
00:32:00
cargador, entonces este de aquí se va
00:32:02
a este fichero, lo analiza
00:32:04
y me pilla
00:32:06
la raíz, quien será la raíz
00:32:07
de mi sistema, esto, vale, esta es la raíz de lo que he hecho yo, este TimePane, vale,
00:32:10
este TimePane será mi objeto padre, objeto progenitor, no sé cómo llamarlo, vale,
00:32:20
y sustancialmente luego creo una escena, esto es el tamaño de la ventana, vale,
00:32:33
Dice, esta nueva escena que tú creas tiene como base este objeto de aquí.
00:32:38
O sea, que lo que va al fondo es este TablePane con luego todas las cosas a partir de él, ¿vale?
00:32:43
Y que es grande 640 x 480 píxeles, ¿sí?
00:32:49
Si yo cambio esto, cambiará el tamaño inicial de mi ventana, ¿sí?
00:32:53
Luego esto seta el título arriba, ¿vale?
00:32:59
Esto lo llamaremos gestor alumno.
00:33:02
Luego, llave CX funciona como una alegría de un teatro.
00:33:09
Tú creas escenas y tienes un escenario.
00:33:17
Entonces, en un cierto momento le dices, ahora en el escenario va esta escena.
00:33:21
Tú has creado esta escena de aquí, cuya base es raíz, es este objeto que has cargado de aquí.
00:33:25
O sea, sustancialmente has cargado esta escena.
00:33:32
y ahora le dices en el escenario
00:33:34
la escena
00:33:37
que se va a hacer es esta escena
00:33:39
que me he creado y luego
00:33:41
enseña
00:33:43
¿si?
00:33:44
¿entiendes? si yo quisiera cambiar
00:33:47
lo que se ve aquí completamente
00:33:49
podría crear una escena distinta
00:33:51
y decirle oye mira
00:33:53
carga esta nueva escena y mandala en el escenario
00:33:55
¿si? entonces cambiaría
00:33:57
de una ventana a otra
00:33:59
nosotros esto lo hemos hecho con los tabs
00:34:00
Si todo esto funciona está bien, ahora al lanzar me debería cargar mi objeto, donde
00:34:03
aquí esto está, si le pongo el otro pues todavía no lo he hecho.
00:34:21
Esto debería funcionar, si lo pincho me debería decir, haz pulsado, cada vez que lo pincho
00:34:29
llama ese método. ¿Dudas? Vale, muy bien. Entonces tenemos esta aplicación que cuando pulsamos el botón
00:34:38
ejecutar. Entonces, ahora nuestra idea sería la siguiente. Yo quiero que una persona pueda poner
00:34:51
aquí un nombre, poner aquí una nota, darle año de alumno y que esta información se guarde por algún
00:35:02
lado entonces necesito encontrar una estructura para poder guardar estas cosas vale y esto será
00:35:08
mi gestor tenía creado esto esto en mi clase gestor es la que se encargará de mantener allí
00:35:15
dentro los alumnos vale entonces la clase gestor necesita una estructura de datos para poder guardar
00:35:27
alumnos. Lo hacemos sencillo. ArrayList, alumno, alumnos, y lo que hago es, un constructor,
00:35:35
public, gestor, que lo que hace es, alumnos es igual a new ArrayList de alumno, vacía,
00:35:55
para hacerlo bien esto debería ser privado al gestor y cualquier cosa que se haga pase por
00:36:15
el gestor vale para que el gestor tenga control sobre sus alumnos y sobre lo que estás haciendo
00:36:24
al alumno que tú no puede llegar un momento y cambiar completamente los alumnos a otra cosa
00:36:31
pues super estilo por ahora no dejo así y si tengo que hacer un acceso directo a un acceso directo
00:36:35
y cambio lo que me da la gana, ¿vale?
00:36:40
Pero todas las cosas que hemos visto anteriormente
00:36:42
de que debería proteger los datos
00:36:45
y mantener que la gente no pueda hacer lo que le da la gana
00:36:49
y añadir cosas que no son,
00:36:51
pues debería aplicarlo también aquí.
00:36:53
No sé si hacer...
00:36:58
Ahora dejámoslo así, ¿vale?
00:37:01
Muy sencillo.
00:37:04
Con esto, cuando crea un gestor,
00:37:06
En este pongámosle un public void add, alumno add, que lo que hace es alumnos.add.
00:37:08
Este es un método de gestor que yo le digo, oye, gestor, añádeme un alumno,
00:37:29
y lo que hace él dentro es añadirlo a su clase.
00:37:33
Vamos a mantenerlo así y así lo hacemos un poquito más seco, ¿vale? Entonces yo para añadir alumnos hago así, podría también sobrecargar add haciendo dame un string nombre int nota y añado un new alumno nombre not.
00:37:36
Entonces tengo la posibilidad
00:38:04
Mi gestor de añadirle a un alumno
00:38:07
Directamente que he creado yo
00:38:09
O añadirle solo los datos
00:38:10
Y que él dentro me crea un nuevo alumno
00:38:13
Y lo añado
00:38:15
Vale
00:38:16
Entonces, ¿cómo uso esto
00:38:21
Desde fuera?
00:38:25
¿Sí?
00:38:28
Lo que me interesa es el GuyController
00:38:28
Este de aquí
00:38:30
Tiene que dentro del add
00:38:32
Añadir aquí
00:38:34
Como es un controlador, yo aquí necesito el acceso a mi gestor.
00:38:36
Por algún lado aquí necesito este gestor.
00:38:44
Entonces tengo varias formas para hacerlas.
00:38:47
Uno es que el gestor yo lo cree estático en alguna clase y que luego accedes típicamente a esa clase.
00:38:51
Otra opción es que este gestor se crea aquí a la hora de inicializar este gestor, ¿vale?
00:38:59
Entonces, vamos a hacerlo con inicialización para que veáis, si me acuerdo cómo se llama.
00:39:08
Aquí yo puedo hacer que esto implemente inicializable.
00:39:15
Donde está clase inicializable es de JavaFX, FXML, ¿vale?
00:39:24
Esta cosa aquí me está diciendo, oye, mira, aquí voy a crear un nuevo método, que es el método de inicialice, ¿vale?
00:39:29
Que se llamará al inicializar este controlador.
00:39:38
Al principio, si tú eres inicializable, el sistema en automático lo que va a llamar es esta inicialización, ¿vale?
00:39:42
Si os fijáis, se queja porque dice, oye, mira, has dicho implementa inicializable, pero te falta un método.
00:39:52
Te falta este método de aquí.
00:39:57
Este método aquí se llamará a la hora de inicializar este sistema.
00:39:59
Estas serían las cosas que yo voy a hacer al principio para que funcione.
00:40:07
Para ver si funciona de verdad, si esto es verdad, ahora al lanzar esto debería hacer un inicialice, debería escribir esta cosa de aquí como primera cosa y luego abrir la ventana.
00:40:14
Vamos a ver si es verdad.
00:40:33
Entonces, al lanzar la ventana sin haber hecho nada, fijaos que tarda un ratito, yo lanzo y cuando se inicializa la ventana, pues entonces se lanza este eje.
00:40:33
Entonces, este es un método que se está ejecutando desde dentro de WeController y que se inicializará al principio de mi ventana.
00:40:57
enlazado la aplicación y se lanza esto. Entonces, a esta altura aquí es donde yo quiero crear un gestor.
00:41:09
Entonces, si me queda aquí un gestor y cuando se inicializa, yo haré G es igual y un gestor.
00:41:17
Entonces, al inicializarse, esta cosa aquí la pillo con G y ahora yo tengo este G que puedo utilizar
00:41:31
por cualquier lado, ¿vale? Por ejemplo, aquí ahora le podría decir que cuando pulso Add me dice g.sithe.
00:41:41
No, g.no puedo. Vamos a hacerlo. El gestor tendrá un método sitte, public void sitte, que me dice
00:41:49
cuántos alumnos tiene. O... return alumnos.c. Entonces, ahora puedo desde aquí decir
00:42:06
Escríbeme size. Como por ahora no he puesto nada, me espero que aquí salga cero, ¿vale?
00:42:29
Cuando pulse el botón Add, ¿eh? ¡Tac! Cero. Si yo en inicialización, por ejemplo,
00:42:40
g.add
00:42:55
añado un alumno
00:42:57
dato
00:42:58
pes
00:42:59
pues ahora al darle al botón
00:43:01
dice que hay uno
00:43:07
o sea que esto es
00:43:10
el gestor creado
00:43:12
¿vale? más adelante
00:43:15
por ahora es pronto
00:43:17
aquí es donde yo podría decir
00:43:18
oye mira, vete a mirar si tengo
00:43:21
alumnos ya guardados en un fichero
00:43:23
si los tienes
00:43:25
guardados en un fichero los alumnos
00:43:26
Cárgalos antes de nada
00:43:28
Al inicializar la aplicación
00:43:30
Ya cárganos los alumnos que ya había creado
00:43:33
En sesiones anteriores
00:43:35
Así los tienes ya a disposición
00:43:36
Sería en este
00:43:37
Metodito
00:43:40
¿Entiendes?
00:43:41
Y esto es el metodito que se llama
00:43:43
Antes de que empiece
00:43:45
La aplicación
00:43:47
Digamos así
00:43:49
Entonces ahora tengo este gestor G
00:43:50
Vamos a implementar
00:43:54
Add de verdad
00:43:56
¿Vale? Para implementar ADD yo tengo que tener acceso a dos cosas, ¿vale?
00:43:57
A esto y a esto, que había llamado nota y nombre, ¿sí?
00:44:03
Entonces, le voy a decir, le voy a decir, oye, mira, tu controlador tiene un control que es un text field que se llama nombre.
00:44:08
Y un text field que se llama nota.
00:44:21
¿Sí?
00:44:26
Y me dice, ¿y qué es este next field?
00:44:27
Y tú le dices, es un control de esto de JavaFX async.
00:44:29
Vale, perfecto.
00:44:34
Ahora, pero le dices que es, mientras esto es un objeto que he creado yo, que es mío,
00:44:36
estos, estos dos, no son objetos cualquiera que estoy creando a nivel de código,
00:44:43
mas son estas casillas de aquí.
00:44:51
entonces de alguna forma le tengo que decir
00:44:53
oye mira
00:44:56
estas dos variables
00:44:57
no son variables cualquiera
00:44:59
que ahora inicializaré
00:45:02
como me da la gana, sino que las encuentro
00:45:04
por algún lado ya creadas
00:45:06
¿dónde? ¿dónde se han creado
00:45:08
esas dos cosas?
00:45:12
en el fxml, entonces ¿cómo podré
00:45:13
decirle, oye mira tú
00:45:16
eres de fxml
00:45:17
muy bien
00:45:19
este es de aquí, que no es tan inicializado
00:45:22
por ningún lado
00:45:33
en realidad me está diciendo, mira, no son
00:45:34
variables que creas ahora
00:45:37
como esta de aquí, que luego tendrás que inicializar
00:45:39
tú, porque si no se me queda nul
00:45:41
son variables que están relacionadas
00:45:43
con fxml, entonces
00:45:45
su declaración, vete a buscar
00:45:46
en fxml, él irá
00:45:49
a buscar en el fxml
00:45:51
buscará por aquí, se encontrará
00:45:53
que, uy, existe uno
00:45:55
cuya idea es nombre, pues esto es
00:45:57
el nombre, y este de aquí
00:45:59
una nota, pues esta es la nota
00:46:01
entiende entonces si esto funciona con suerte controlador ahora yo aquí le puedo decir oye mira
00:46:02
me imprimes el contenido de nombre por ejemplo nombre punto text si esto funciona cuando pincho
00:46:15
el botón add vale me debería escribir el contenido del texto de nombre vamos a verlo yo tengo mi
00:46:29
ventana le escribo hola si funciona cuando pincho aquí aquí escribirá hola y aquí pongo gato
00:46:39
cuando pincho aquí me pone gato fijaos que en ningún lado yo he hecho un new text field no lo
00:46:51
he creado, pero con esta cosa
00:46:59
de aquí, él me ha hecho una asociación
00:47:01
entre esta variable que usaré
00:47:03
a nivel gráfico, a nivel
00:47:06
de código, con el entorno
00:47:07
gráfico que he creado
00:47:09
a través de la simbilla.
00:47:11
¿Sí?
00:47:15
Esto son
00:47:16
las típicas cosas que os van a crear
00:47:17
1200 problemas.
00:47:19
Porque os olvidáis
00:47:21
esta cosa de aquí, y entonces
00:47:23
estáis creando algo que no está asociado
00:47:25
con la casillita, escribís en la casillita
00:47:28
intentáis utilizarla y no va a funcionar
00:47:30
hay que poner
00:47:31
una etiqueta de esa por cada variable
00:47:33
vale
00:47:35
porque esta es una información de profundizador para esta
00:47:36
vale
00:47:43
dudas hasta aquí, vale, entonces
00:47:44
si esto funciona
00:47:47
cuando hago el add, pues que tendré que hacer
00:47:48
o simplemente decir
00:47:51
gestor
00:47:52
añade
00:47:55
lo que está en nombre
00:47:56
.gettext
00:47:59
coma lo que está en nota
00:48:00
punto de text.
00:48:04
Justo.
00:48:08
Lo que decíamos antes.
00:48:20
Habría que comprobar
00:48:27
si hay algo
00:48:29
aquí dentro y algo aquí dentro.
00:48:31
Claro. Pero esto ya no funciona.
00:48:32
Antes de este de aquí
00:48:36
le estoy pasando string string
00:48:37
pero no tengo ningún método que añade string string que es esto mint integer punto parche
00:48:39
inter de esta cosa aquí ahora sí y claro que si aquí dentro escrito con cubrirlo esto explota
00:48:49
debería ponerlo en contra que para evitar que explote sí pero es lo que decíamos antes lo
00:48:54
vamos a mantener lo más sencillo posible es asumamos que el ser humano que utiliza esta
00:49:00
cosa pues no está haciendo errores
00:49:06
entonces aquí vosotros aquí deberíais decir voy a mirar esto voy a que mirar
00:49:13
que dentro nula no será nunca pero sí que podría ser vacío
00:49:18
si no es esta vacío pues no lo haga voy a mirar si este alumno ya existe si este alumno
00:49:24
no lo añadas esto es un set en vez que una release todas estas cosas deberías
00:49:29
tenerla en mente. Pero no estamos viendo esto, estamos viendo nosotros una pequeña
00:49:33
interfaz que haga cosas. Que luego el programa esté hecho muy básico, sí, pero lo mantenemos
00:49:39
básico por eso, para no sobrecargar de información. Y por ejemplo me ponga aquí un ciso g.alumnos,
00:49:47
Para ver que cuando añade un elemento, pues aquí me de cuántos elementos están añadidos.
00:50:02
Entonces ya está. Yo tengo este fantástico programa ahora que funciona fenomenal y puedo
00:50:10
añadir el alumno Paco con un 5. ¿Veis que ha añadido uno? Luego añado Sara con un 7.
00:50:17
Si ahora escribo cosas raras, explota. Fijaos que explota pero la interfaz gráfica sigue allí.
00:50:28
yo esto lo debería decir ay mira que esto me hace algo vale pero esto si ahora añado stefano
00:51:04
con un 10 también no ha explotado la interfaz entera la interfaz en un cierto sentido se ha
00:51:12
protegido en la aplicación no ha acabado ha hecho algo raro aquí ha explotado esto no debería haber
00:51:22
pasado y aquí debería haber hecho algo debería haber metido aquí un mensaje de oye mira esto
00:51:27
no se ha podido insertar o cosas por el estilo vale pero lo probamos a hacer escribimos aquí
00:51:32
lo que se está haciendo vale cuando pincho aquí que aquí me esquiva se ha insertado el alumno no
00:51:44
sé qué o no se ha podido insertar más vamos a modificar lo que tenemos para que tiene cuenta
00:51:50
que se ahora de inicio pues todo lo que he hecho hasta ahora no se ha guardado un fichero ni nada
00:51:58
Entonces, empezaría desde cero otra vez, ¿vale?
00:52:02
Entonces, vamos a modificar esto para que aquí haya algo que yo pueda escribir.
00:52:06
Por ejemplo, un label.
00:52:10
Un label, pongo aquí, lo vacío.
00:52:13
Y como ahora tengo que escribir aquí algo, me voy a dar un identificador.
00:52:24
Lo voy a llamar resultado.
00:52:29
Res, ¿vale?
00:52:33
O res text.
00:52:37
Muy bien, lo guardo, me voy aquí, recargo, repico, y ahora para que lo pueda utilizar
00:52:38
de aquí, voy a hacer lo mismo. Arroba fxml un label que se llama res.txt. ¿Qué es el
00:53:02
label? Pues el label, importalo, tac. Entonces ahora tengo una asociación con eso. Cuando
00:53:13
hago el art pues aquí en vez de hacer estar aquí puedo poner
00:53:21
si eso no es punto de que esté punto 7
00:53:28
en que usado
00:53:44
punto
00:53:48
Realmente he importado lo que no es. He importado Java lang class by label que no es. Lo que tengo
00:53:49
a importar es el label de JavaFX. Ahora que he importado el correcto, cuando le hago esto punto,
00:54:15
me da los métodos del label de joyce x incluyendo el set de texto entonces insertado alumno
00:54:26
con esto me dice insertado alumno si quiero hacerlo un poco más bonito podría poner alumno
00:54:49
a es igual a new alumno de esta cosa aquí. Añado el alumno, insertado alumno y te digo
00:54:55
que alumno es. Entonces ahora yo tengo esta cosa aquí que me dice, Estefano con un 10,
00:55:13
al añadirlo me dice insertado alumno, alumno Estefano con un 10. Añado gato, parece que
00:55:29
Si lo pego ahora es un 7, aceptado dato con 7.
00:55:40
Si pongo una cosa así, pues explota no me dice nada, vamos a intentar que haga algo.
00:55:45
Entonces, yo lo intento este de aquí, ¿vale?
00:55:52
Si cuando llego, ahí es donde explotará, explota en un formato, por lo tanto sale aquí.
00:55:56
Hago un try, catch, excepción, error, insertar, alu.
00:56:04
Entonces, si intento hacer esta cosa, si mientras hago esta cosa sale cualquier excepción,
00:56:36
pues lo que te diré es, en ese campo de allí, te pondré, ha habido un error, insertar, alu.
00:56:42
Hasta podría intentar decirte qué ha pasado.
00:56:48
me lanzo, si pongo algo bien me lo añade, si pongo algo con un error, pues me dice error al insertar alumno, fijaos que aquí ya no explota, me dice este string de dos ss, pues no, no, esto ya es un punto más serio, ¿dudas?
00:56:57
el label que te sale abajo
00:57:28
cuando creas un alumno
00:57:32
como lo haces
00:57:33
en el style builder
00:57:35
en el style builder el label que has puesto
00:57:36
justo después del botón
00:57:39
he puesto un label que está por aquí
00:57:41
y le he puesto
00:57:43
un id
00:57:45
dudas
00:57:46
porque
00:57:55
¿cómo voy a participar
00:58:05
en lo de REST XT
00:58:07
porque no sale
00:58:09
Porque has importado el que no es. Tienes que importar esta cosa del level. Borras el level,
00:58:10
lo importas otra vez, pero importando el JavaScript. ¿Vale? ¿Dudas hasta aquí?
00:58:22
Vale, muy bien, esto funciona. Vamos a hacer la segunda parte. ¿Vale? Entonces,
00:58:28
si este de aquí me permite añadir alumnos, yo quiero que esto me permita ver los alumnos que
00:58:39
hay entonces la tabla 2 que es mostrar alumno vamos a hacer de esta forma pillamos dos botones
00:58:45
un botón lo ponemos aquí un botón lo ponemos aquí a la izquierda un botón lo ponemos aquí
00:58:57
a derecho, a este le ponemos allí, a este le ponemos así, y en el medio ponemos un textarea,
00:59:08
por ejemplo, así. Lo podemos hacer con textfield distintos y cosas así, pero al menos así utilizamos
00:59:29
otro comando, ¿vale? ¿Qué es esto? La idea es que cuando yo entra aquí y pulse a estos botones de
00:59:48
aquí me vaya recorriendo todos los alumnos que yo tengo y me escriba a los
00:59:55
alumnos aquí. Entonces tengo dos métodos aquí, cuando pincharé aquí haré al
01:00:00
siguiente alumno, cuando pincharé aquí será el anterior alumno.
01:00:09
Entonces me voy a... ¿esto lo puedo guardar?
01:00:14
En esto no tengo que cambiarlo, esto no tengo que cambiarlo, esto sí tengo que
01:00:20
cambiarlo, por lo tanto le tengo que dar un nombre. Esto será mi txtAlumno. Es un
01:00:24
textarea. Esto será txtAlumno. Cuarto y ya está.
01:00:33
Desde la perspectiva del controlador tendré dos métodos. Un método que
01:00:41
será public void anterior y otro método que será public void siguiente. Pon su etiqueta para decir
01:00:51
cuidado lo quiero utilizar en fxml. Entonces ahora si vuelvo aquí puedo hacer que este botón de aquí
01:01:11
al pulsarlo haga anterior y este botón de aquí al pulsarlo haga siguiente. Lo mismo que hemos
01:01:23
hecho antes, ¿vale? Ahora mi controlador tiene dos métodos más, tiene el método anterior y
01:01:34
siguiente que los ha añadido ahora, pues lo asocio a este botón onAction anterior,
01:01:40
este botón onAction siguiente. La parte gráfica ya la he hecho, ahora consiste,
01:01:45
ahora lo que tengo que hacer es que hagan algo y dudas hasta aquí y paramos aquí entonces estábamos
01:01:53
aquí hemos completado la parte de crear alumnos vamos a mostrar alumnos donde hemos creado esta
01:02:28
situación de aquí vale tenemos un texto que se llama texto alumno aquí en el medio que es un
01:02:33
campo un área de texto y dos botones vale hemos asociado al botón de la izquierda el botón de
01:02:39
la derecha siguiente anterior vale esto es lo que hemos hecho antes teniendo en cuenta que como esta
01:02:44
interfaz tiene este controlador todos los fichas de los métodos que yo pondré aquí etiquetados con
01:02:51
me aparecerán aquí para poder reutilizarlos en botones o campos o lo que sea.
01:02:59
Puedo hacer hasta que varios botones llamen el mismo método si quiero.
01:03:08
Pero esto no sé si lo he guardado, lo guardo, vuelvo para acá, recargo y ahora mi aplicación
01:03:13
aplicación debería tener en el lado así esto para crear nuevos alumnos y aquí
01:03:26
nada porque no la legalidad entonces voy aquí
01:03:33
debería ahora ahora
01:03:40
entonces vamos ahora a implementar esta parte de
01:03:50
Paso número 1. Vamos a ver qué tiene que verse. Estamos en el controller. La idea es que me
01:03:55
gustaría que el primer alumno se viera directamente, pero es que no sé cuántos alumnos hay. De hecho,
01:04:17
la primera vez que lo abro los alumnos están vacíos vale entonces por ahora está vacío pues
01:04:26
por ahora no hago nada en el inicialización luego después cuando ponemos los ficheros
01:04:31
pues haremos algo aquí también entonces al principio una vez creado o sea hacemos que
01:04:37
porque no lo quiero hacer por cada pues haremos que cuando cambio a esta pestaña de aquí pues no
01:04:50
se vea nada vale se cargue al dar la primera vez aquí al botón entonces voy a tener cuando pincho
01:04:58
el siguiente pensamos consiguiente tengo que cargar en esa área la información del siguiente
01:05:12
elemento, ¿vale?
01:05:19
El siguiente
01:05:20
alumno, ¿vale?
01:05:21
Entonces, primera cosa, me pregunto
01:05:26
si hay alumnos.
01:05:27
Si g.si
01:05:29
es mayor que cero,
01:05:31
entonces es igual.
01:05:36
¿Vale?
01:05:38
Si no hay alumnos,
01:05:38
no cargo nada.
01:05:40
Me tengo
01:05:43
que acordar
01:05:44
en qué alumno estoy
01:05:46
ahora mismo. Entonces,
01:05:48
voy a crear un int posición, que es al acero, ¿vale? Y que si hay un alumno,
01:05:49
lo que tengo que cargar es ese alumno allí. Si pincho en siguiente, pero lo que me gustaría
01:06:02
es que si hay alumnos vaya al siguiente alumno y lo cargue vale entonces la idea sería posición
01:06:17
más más y ahora cargue la información de la posición más más pero para que esto funcione
01:06:24
debería poner aquí menos 1 entonces posición más más media cero entonces lo que voy a hacer es
01:06:33
como hay elementos pues estaría en la posición cero voy a pillar el alumno cero para pillar
01:06:44
alumno cero tengo que acceder a la posición cero de esta array y no tengo nada para poder
01:06:49
pillar esta array list. Por lo tanto necesito hacer una cosa como public alumno getIntIndex
01:06:57
que me permita hacer
01:07:08
return
01:07:12
alumnos.get
01:07:12
index.
01:07:15
Entonces, le paso un índice
01:07:20
y me devuelve el índice. Si lo tengo,
01:07:22
me devuelve el alumno en ese índice.
01:07:24
Lo puedo hacer porque estoy utilizando
01:07:26
una revista. Si tuviera un set
01:07:28
o cosas por el estilo, sería un poco distinto.
01:07:30
Pero, este de aquí
01:07:33
hará
01:07:34
alumno
01:07:36
actual
01:07:37
es igual a
01:07:39
gestor.get
01:07:42
post. Ahora tengo
01:07:43
el alumno, ¿vale? Y este alumno lo
01:07:47
quiero imprimir
01:07:49
en
01:07:51
el área de texto.
01:07:53
¿Vale? Esta área de texto
01:07:56
aquí, que se
01:07:57
llama text-alumno.
01:07:59
Entonces, para que pueda acceder
01:08:02
a esa de allí, la tengo
01:08:03
que hacer algo de este estilo.
01:08:05
Es decir, oye, mira, xml.
01:08:07
Fxml.
01:08:10
vas a tener un textarea que se llama textalumno. ¿Y qué es este textarea? Pues importa el control.
01:08:11
¿Vale? Entonces, aquí, ahora lo que voy a hacer es textalumno.getSetText de actual.23.
01:08:27
Lo lanzo, creo un alumno, que es el alumno A con 22. Me voy a mostrar al alumno y pincho siguiente,
01:08:41
me aparece aquí el alumno. Está claro que si pincho otra vez siguiente explota.
01:08:59
¿Por qué explota? Porque esto sigue adelante, adelante, adelante, adelante y llega un momento
01:09:05
que se pasará del 6 y explota. Entonces hagamos aquí un pequeño controlito para evitar que
01:09:13
explote, si posición es mayor, es igual a g.sit,
01:09:19
quiere decir que me he pasado.
01:09:28
Si posición es 1 y yo tengo la posición 1, no existe.
01:09:32
Entonces lo que hago es dos opciones.
01:09:38
O lo dejo en el último o vuelvo al primero,
01:09:42
dependiendo de cómo quiero que funcione.
01:09:45
Si yo quiero que sea como circular
01:09:47
Si estoy en el último alumno
01:09:49
Y voy al siguiente, va al primero
01:09:51
Pues tengo que hacer una cosa
01:09:54
La otra opción es que si llego al último
01:09:56
Y no hay último, pues se quede en el último
01:09:58
Hagámoslo circular
01:10:00
Entonces, si la posición
01:10:03
Es el máximo
01:10:05
Quiere decir
01:10:07
Que posh vuelve a hacer
01:10:09
Si yo estoy en la posición 9
01:10:11
Que es el último alumno
01:10:14
y salgo a la posición 10 y no hay
01:10:15
el alumno 10, pues la posición es 0.
01:10:17
Entonces me pondrá el 0.
01:10:20
Tú das, y luego
01:10:24
pillas al alumno
01:10:26
y lo cagas.
01:10:28
Ya está. Ahora, ¿cómo
01:10:29
hago el anterior?
01:10:31
Parecido.
01:10:34
Si hay,
01:10:37
porque si no hay alumnos,
01:10:38
estos botones no tienen que hacer nada,
01:10:40
resto 1,
01:10:43
y si resulta
01:10:45
resulta que la posición es menor que cero,
01:10:45
esto hay menos uno, menos dos, menos tres,
01:10:51
pues entonces tengo que ir a la última posición,
01:10:53
que será G.7.
01:10:57
¿Sí o no?
01:11:02
Esto lo hemos hecho algunas veces de forma textual.
01:11:06
Y a este punto pillo esa posición en la imprimida.
01:11:11
De hecho, esta parte de aquí es igual en los dos, entonces lo que podría hacer es crearme un metodito, private void print area, en el que te paso un infos y lo que haces tú es esto.
01:11:14
Y aquí Arash.
01:11:47
¿Por qué? Porque así si ahora cambio cómo se ve el alumno, pues lo cambio aquí y en automático se me aplica tanto al botón derecho como al botón izquierdo.
01:12:01
Si yo este código lo duplico y luego cambio uno, lo tengo que cambiar igual también el
01:12:22
otro lado.
01:12:30
Ahora lo tengo centralizado en un solo sitio y siempre llamará esta cosa.
01:12:31
Ahora hacemos un ejemplo.
01:12:38
Tengo aquí, tengo el señor S, tengo el señor G, y tengo el señor U, y ahora me pongo aquí, y tengo S, tengo G, tengo U, y tengo S, G, U, S, G, U.
01:12:40
va por un lado y va por el otro. Y puedo ir mirando todos mis alumnos, ¿sí?
01:13:06
Ahora, si yo quisiera, no me gusta así, lo quiero de otro formato, por ejemplo,
01:13:17
escribir alumno, luego irte a una nueva...
01:13:26
no sé si es esta barra o la otra barra
01:13:34
la inversa
01:13:37
barra n
01:13:39
más
01:13:42
aquí escribo
01:13:44
nombre
01:13:46
dos puntos
01:13:48
y luego pongo
01:13:49
actual
01:13:51
punto nombre
01:13:53
más
01:13:55
barra n otra vez
01:13:59
nota dos puntos
01:14:02
más
01:14:04
actual punto nota
01:14:05
fijaos que
01:14:08
las notas no las he
01:14:24
no las he limitado desde la 10
01:14:26
o sea que faltaría
01:14:30
es que ahora me lo escribo así
01:14:32
y me da igual
01:14:34
el botón que pincho porque el formato
01:14:37
este aquí ya no depende, si había
01:14:38
dejado dos veces y lo había modificado en uno
01:14:40
cuando daba a la derecha me lo ponía
01:14:42
en esta cosa aquí y cuando daba a la izquierda
01:14:44
me lo volvía a poner con el otro
01:14:46
código
01:14:47
y si tenéis código duplicado y tenéis que modificarlo por un lado y por el otro cuando
01:14:48
cambiáis algo, pues maldición. Ya está, ya tengo mi fantástica aplicación de forma visual,
01:14:58
con interfaz gráfico en el que puedo añadir alumnos, todos los alumnos que me dé la gana.
01:15:11
Y puedo ir mirando mis alumnos.
01:15:25
¿Qué me faltaría poder hacer?
01:15:31
Pues, por ejemplo, guardarlos.
01:15:39
Guardarlos y cargarlos.
01:15:41
Entonces, lo que podríamos hacer es que se cargue el fichero.
01:15:44
hay un fichero que se cargue en automático cuando arranco esto vale pero para guardarlo
01:15:54
si yo puedo hacer cambios puede añadir alumnos pero no vaya una tercera pastañita aquí de guardar
01:16:00
en el que hay un botón para guardar en un fichero podría también hacer aquí una cosa que sea de
01:16:04
cargar y guardar o sea guardar y cargar para que haya dos botones de pilla este fichero
01:16:13
pero para hacer las dos cosas que una sea automática y una que sea por un botón pues
01:16:17
entonces hacemos sólo un botón aquí que actualiza la cosa yo puedo hacer cambios
01:16:27
pero estos cambios son provisionales hasta que lo guarde vale pero cada vez que arranca
01:16:31
pues intenta cargar un fichero explico lo que quiero hacer entonces que tengo que hacer
01:16:36
Pues me voy aquí, añado una tercera tab. ¿Cómo se añade una tercera tab? Pues en la hierarquía aquí,
01:16:43
hay un tab aquí, un tab aquí, pues necesito un tercer tab. Me voy a donde están los tabs,
01:16:51
están aquí al otro lado, en containers, me busco un tab pane, un tab, esto, dentro está un tab pane.
01:16:59
Vamos a ver si con esto me lo hace bien. Y lo añado aquí. Tengo otro tab. Dentro de este tab le pongo solo un botón grande de save.
01:17:08
Como quiero que cargue en automático, vale. Pues entonces el nombre del fichero que carga no lo puedo...
01:17:24
Le pongo un TextField, que será el nombre del fichero donde se guarda, y un botón para
01:17:43
guardarlo.
01:17:59
El botón pone Sabe o Guardar.
01:18:09
Este de aquí le pongo, si queréis, también un Label, para que ponga Nombre, Fichero.
01:18:17
Entonces yo escribo aquí el nombre del fichero y al pulsar guardar quiero que me guarde los alumnos que tengo ahora en ese fichero.
01:18:41
Luego haré que al arrancar busca un fichero con un determinado nombre que es standard.dat.
01:18:54
Si ese fichero está, me carga esos ficheros.
01:19:03
Entonces, si yo quiero que se carguen al principio, pues pongo aquí standard.dat y lo que escriba allí se cargará al fichero.
01:19:06
Y si en vez de que quiero una copia de beta, pues lo puedo hacer también.
01:19:12
Es una cosa maravillosa, pero me interesa. Es para pronto.
01:19:16
Entonces, necesito que cuando pincho este botón haga algo.
01:19:20
Me voy a mi controlador y me creo un nuevo método.
01:19:24
un nuevo método que es arroba fxml y será un bo, public, private o depende de donde lo quiera usar,
01:19:30
private void guardar y entonces quiero que al pinchar este guardar su onAction,
01:19:42
que no lo ha cargado
01:20:03
a ver si lo recarga, me voy al
01:20:05
controller y voy a seleccionar
01:20:10
otra vez esta
01:20:12
y a veces
01:20:13
sí que me lo recarga, ¿veis?
01:20:15
ahora está guardado
01:20:19
entonces al pinchar esto se guardará
01:20:19
cuando yo uso el guardar
01:20:24
quiero saber lo que está escrito aquí dentro
01:20:26
por lo tanto a este de aquí
01:20:28
le doy un nombre
01:20:30
pero
01:20:31
¿vale?
01:20:33
y aquí a bonito guarda con esto he acabado guardo y vuelvo aquí corre cargo por si acaso lo lanzo
01:20:36
ahí que exista, aquí. Vale, muy bien. Entonces, cuando pincharé ese botón, se lanza este guardar.
01:20:57
¿Qué tengo que hacer? Tengo que guardar un fichero, guardar todo lo que tengo en un fichero,
01:21:12
vale entonces vamos a intentar hacerlo
01:21:19
primero necesito el fichero vale file f es igual a new file
01:21:26
que le pongo aquí que le pongo aquí como llamado
01:21:36
primero tengo que referirme a él y lo he llamado fichero y entonces
01:21:59
ahora es fichero.getText. Con esto creo un fichero asociado con lo que he escrito allí.
01:22:08
Esto claramente es un java.io, se puede usar java.io que hemos visto con files y cosas por
01:22:18
el estilo. Eso ya lo dejamos a vosotros. Entonces ahora tengo que escribir en este fichero. Para
01:22:26
escribir en este fichero necesito un canal de escritura en ese fichero. ¿Qué uso? ¿Qué hago?
01:22:32
never in the light. ¿Por qué no? Si hago un File Writer, ¿para qué sirve el File Writer? ¿Escribir qué?
01:22:38
¿Texto? ¿Quiero escribir texto? ¿Quiero irme a recorrer todos mis alumnos y reescribirlos en texto
01:23:01
para que luego cuando lo vaya a leer tenga que reconstruirme todos los alumnos en formato texto?
01:23:10
de nuevo object output stream host es igual a new object output stream de new file output stream
01:23:15
que es esto, impórtalo, que es esto, impórtalo, me quejo, re quejo. Ahí. O esto lo creo dentro del...
01:23:41
Ahí. Entonces he creado este OS, ¿vale? Puedo escribir cosas. ¿Qué escribo? Pues yo lo que voy a hacer es escribir gestor.
01:24:05
at, va al gestor, le digo, escúchame gestor, eres realizable, perfecto, ya está, te puede escribir.
01:24:29
Entonces lo que va a hacer, en el que es controller, es escribir directamente os.freeTheObject de,
01:24:48
Cuando le das al save, lo que hace es escribir el gestor entero en el fichero.
01:25:06
Como el gestor tiene dentro una red de alumnos, pues escribe la red de alumnos.
01:25:29
Como la red de alumnos tiene dentro alumnos, pues escribirá a los alumnos.
01:25:34
Escríbelo tú, como te da la gana, como quieras. Escríbelo.
01:25:38
Sí.
01:25:41
¿Y en la que falta que el alumno sea serializable?
01:25:42
¿Qué lo sabe? ¿Tú qué dices?
01:25:44
¿Tú qué opinas? ¿Por qué me lo preguntas?
01:25:53
Porque normalmente con otra
01:25:57
salida de su propiedad que he hecho yo
01:25:59
no sabría. O sea, mi
01:26:00
individuo me ha sufrido por eso.
01:26:03
Pero no me lo preguntes.
01:26:05
No lo sé.
01:26:07
Afírmalo. ¿Cómo que no lo sabes?
01:26:09
Claro.
01:26:11
Lo puedo probar. Va a explotar.
01:26:13
¿Vale? Porque, claro, gestor
01:26:15
es serializable, puede, pero para que
01:26:17
sea serializable, ese puede ser
01:26:19
realizar, todos los objetos que usa tienen que ser serializables.
01:26:20
Entonces a la lista es realizable, pero al alumno no.
01:26:24
Entonces explotará a un cierto momento diciendo que cuando
01:26:27
intenta escribir al alumno dice que no es realizable.
01:26:29
Vale, perfecto, no pasa nada.
01:26:32
Cuando explotará, pues le pongo aquí implements serializable.
01:26:33
Correcto, ¿eh?
01:26:39
Bien.
01:26:40
Sí, ahora debería ser todo serializable,
01:26:44
esperando que a la lista sea realizable y que escriba sí.
01:26:47
¿Vale?
01:26:50
Perfecto, guardo todo así.
01:26:51
¿Podría hacer lo distinto de guardar alumno por alumno?
01:26:53
Sí.
01:26:57
¿En el examen qué me van a pedir?
01:26:57
Pues no lo sé, lo que te pidan.
01:26:58
¿Vale?
01:27:00
Está claro que si te pidan guarda alumno por alumno y tú guardas el arreglisto, pues
01:27:00
fracasó un cero.
01:27:07
¿Veis?
01:27:09
Tiqui, tiqui, tiqui, tiqui, tiqui.
01:27:12
Ahora, si esto funciona, y esto a lo mejor debería ser cuando aquí hay algo, ¿vale?
01:27:17
Entonces, si fichero.getText.length es mayor que cero.
01:27:27
Si hay algo escrito en ese campo, pues entonces me creas el fichero.
01:27:50
Si no hay nada, pues no intento guardar porque no sabía dónde guardar.
01:27:56
¿Sí?
01:28:02
Si esto funciona, ahora yo puedo lanzarlo, puedo escribir aquí el señor A y el señor B,
01:28:03
que se ven aquí, y cuando voy a guardar alumnos, lo puedo guardar en alumnos.dat,
01:28:15
le doy a guardar y con un poco de suerte por algún lado, se ha creado alumnus.dat y si
01:28:26
voy a mirar que hay dentro, no lo entiendo, pero con un poco de suerte por algún lado veo el señor A
01:28:46
Esto no es texto, es binario, es una representación de la tabla, pero este de aquí sería mi gestor.
01:28:54
Este es mi gestor. Si yo al arrancar importo este gestor, ya tengo dentro los alumnos listos.
01:29:06
Que es lo que va a intentar hacer ahora
01:29:15
Vale, vamos a ver
01:29:19
Pues vamos a ver que
01:29:20
Yo puedo guardar donde me da la gana
01:29:22
¿Vale? Pero mi sistema
01:29:25
Al arrancar
01:29:26
Va a buscar alumnos.dat
01:29:28
Y lo que está en alumnos.dat
01:29:32
Lo carga
01:29:34
Yo puedo
01:29:34
Guardar los ficheros donde me da la gana
01:29:36
Pero si sobreescribo este alumno.dat
01:29:39
Es el que se recargará
01:29:41
La próxima vez que arranque el programa
01:29:42
¿Vale?
01:29:44
Entonces, quiero que esto se haga de forma automática, por lo tanto lo voy a poner en inicialización.
01:29:45
Cuando inicializa, en vez de crear el gestor directamente, lo que va a ver es si existe este fichero.
01:29:52
Entonces, file f es igual a new file de alumnos.dat, uno en concreto.
01:30:03
porque es inicializado, no sé cuál es
01:30:12
entonces asumo que haya este fichero
01:30:15
por defecto que es de donde se cargan
01:30:17
los datos, si yo quiero que se carguen la próxima vez
01:30:19
simplemente los guardo aquí
01:30:21
¿vale?
01:30:24
si existe, pues entonces
01:30:24
cargaré el gestor desde allí
01:30:33
dentro, si no
01:30:37
me creo un gestor nuevo
01:30:38
¿ok?
01:30:44
¿y cómo lo hago? pues tengo que utilizar
01:30:47
un input
01:30:49
object.inputStream ois es igual a new object.inputStream de new filenputStream de f
01:30:51
esto de aquí lo pondré en un try, este de aquí lo importo, este de aquí lo importo, ya lo tengo, ¿vale?
01:31:13
¿Y qué hago? Pues g es igual a gestor de ois.readoption, ois.readoption me dice, ah, class not found,
01:31:51
pues añádelo aquí ahora si explota por esto por esto por cualquier otra causa podría hacerla así
01:32:09
si explota hasta así quiere decir que ha intentado pillar este objeto y por alguna razón no ha
01:32:22
funcionado pues entonces crema si no he conseguido cargarlo pues que era un gestor normal todo esto
01:32:38
fase de inicialización. Podría hasta hacerlo así, a lo mejor se queda más creando un gestor nuevo y
01:32:53
si consigo cargarlo lo sustituyo. Pero siempre gasto, me queda un gestor verde. Tampoco me
01:33:08
gasta mucho. Si es un gestor nuevo vacío, si existe el fichero intento cargarlo, si no lo
01:33:19
he cargado porque ha explotado por aquí, pues entonces no hará nada y entonces me lo dejará
01:33:26
como así. Con esto debería funcionar. Vamos a verlo. Lo lanzo. Fijaos que existe en este momento
01:33:30
alumnos.dat. Entonces, al lanzarlo, él debería intentar cargar ese fichero y si ahora me va a
01:33:45
mostrar alumno, ya están los alumnos que había hecho antes. Ahora puedo añadir. Añado Q y lo
01:33:56
puedo ver Q, pero si ahora cierro, al recargarlo, Q no existe. Solo hay B, porque no la he guardado.
01:34:07
Si añado Q, que ahora está, y lo guardo en alumnos.dat, al rearrancar, después de haberlo
01:34:27
cerrado, pues cuesta. Si añado p, que ahora está, y lo guardo, pero en gato.dat, cuando apago y
01:34:43
re-enciendo, no está. Porque ahora tengo dos ficheros, uno es alumno.dat y uno es gato.dat.
01:35:08
Aquí sí estaría p, pero no es el fichero que se carga al abancar. Por lo tanto, ¿para qué me
01:35:22
podría servir? Yo normalmente guardo siempre en alumno.dat, pero de vez en cuando hago una copia
01:35:35
que no sea alumno por si se me estropea, pues lo guardo en otro lado. Hasta podría hacerlo así,
01:35:42
hacer que por defecto me ponga alumno.dat. Está escrito. Pero si yo quiero guardarlo en otro lado,
01:35:47
pues lo puedo modificar
01:36:01
aquí tengo estos
01:36:03
aquí ya me lo pone
01:36:20
para que sustancialmente le dé a guardar
01:36:22
pero si luego quiero cambiarlo para poner un backup
01:36:25
o cosa por el estilo, lo puedo dar
01:36:27
¿sí?
01:36:28
pues ya está
01:36:31
tengo mi interfaz gráfica, puedo añadir alumnos
01:36:32
puedo mirarlos, puedo
01:36:35
guardar
01:36:36
¿vale? y esto como
01:36:38
primer
01:36:40
prototipo
01:36:41
- Materias:
- Programación
- Niveles educativos:
- ▼ Mostrar / ocultar niveles
- Formación Profesional
- Ciclo formativo de grado superior
- Primer Curso
- Autor/es:
- Stefano Chiesa
- Subido por:
- Stefano C.
- Licencia:
- Reconocimiento - No comercial
- Visualizaciones:
- 1
- Fecha:
- 13 de abril de 2026 - 12:41
- Visibilidad:
- Clave
- Centro:
- IES ROSA CHACEL
- Duración:
- 1h′ 36′ 50″
- Relación de aspecto:
- 1.78:1
- Resolución:
- 1920x1080 píxeles
- Tamaño:
- 812.35 MBytes