Saltar navegación

GUI Ejemplo - Contenido educativo

Ajuste de pantalla

El ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:

Subido el 13 de abril de 2026 por Stefano C.

1 visualizaciones

Descargar la transcripción

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
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
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

Del mismo autor…

Ver más del mismo autor


EducaMadrid, Plataforma Educativa de la Comunidad de Madrid

Plataforma Educativa EducaMadrid