Saltar navegación

20250401 SerializarObjetos_EjemploFacturas - 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 2 de abril de 2025 por Raquel G.

38 visualizaciones

Descargar la transcripción

yo creo que más probable es la tuya 00:00:00
venga 00:00:02
no, porque vosotros 00:00:02
sois muy buenos, vale, habíamos puesto 00:00:06
recordáis para habilitar, para ponerlo 00:00:08
del radio button y usarlo, una nueva 00:00:10
característica en factura 00:00:12
que era, si era de empresa o de particular 00:00:14
eso lo podemos recoger 00:00:16
por ejemplo 00:00:18
en un int que tenga 01 00:00:19
así lo hacemos cambio, si lo complicamos 00:00:22
vale 00:00:24
tipo factura 00:00:26
ala, ya está, entonces vamos a añadir 00:00:28
un get y un set 00:00:30
y listo, y vamos a ponerlo aquí 00:00:31
a mano en el constructor porque sabemos 00:00:43
hacer las cosas a mano, no somos tontitos 00:00:45
porque a lo que no genere el eclipse 00:00:47
ya parece que no 00:00:53
¿Hubo eclipse el domingo? 00:00:54
Sí hubo eclipse 00:01:01
No me enteré 00:01:02
Vale, tipo factura 00:01:04
Bueno, nuestra aplicación de facturas. Antes de empezar a hacer nada, datos. Hemos dicho que un map, como la factura, tiene un elemento que claramente funciona como clave de las facturas, que es el número, estructura de datos más eficiente y más práctica a la hora de programar, un map. 00:01:07
¿dónde me vamos a meter los datos? 00:01:29
pues hombre, aquí ya tenemos un montón de 00:01:32
morraya, vamos a ponerlo en otra 00:01:34
clase, ¿no? vamos a hacernos 00:01:36
aquí, nuestra clase 00:01:40
con los datos y ya está 00:01:43
y aquí 00:01:45
nuestras facturas 00:01:49
¿cómo has metido lo del botón radio? 00:01:50
¿podemos verlos en un vídeo? 00:01:55
¿ahora mismo? 00:01:59
00:02:01
vamos a hacer una cosa, vamos a hacer la aplicación y luego ya 00:02:02
efectivamente como solo hay dos tipos 00:02:06
pero en un int 00:02:07
lo añadimos a funcionalidad 00:02:08
cuando ya 00:02:11
para no meterlo del object string 00:02:12
y el uno a la vez 00:02:15
map será 00:02:16
el número de facturas entero 00:02:20
pues integer 00:02:21
y la factura 00:02:23
facturas 00:02:28
joder 00:02:30
perdonad 00:02:35
venga 00:02:38
vamos a poner un trimap 00:02:42
para variar, para que repaséis todo. 00:02:43
No llores, Cristian. 00:02:49
Porque está grabada en el cerebro como una taladradora. 00:02:56
Vale. 00:03:02
Venga, pues ya está. 00:03:04
Vamos a directamente hacer el comportamiento de la aplicación. 00:03:05
Y se acabó. 00:03:09
vale, entonces 00:03:09
estos radiobutton, si habéis hecho 00:03:14
alguno de los ejercicios con radiobutton 00:03:16
pues están los pobres por libre 00:03:18
normalmente los radio 00:03:20
a ver, es un map 00:03:21
de integer, que es la clave 00:03:26
y factura 00:03:29
y un trimap en particular 00:03:29
vale, estos 00:03:33
radiobutton los hemos puesto por libre 00:03:34
pero normalmente 00:03:37
no funcionan así 00:03:39
claro, ahora mismo como están por libre 00:03:40
yo puedo marcar 00:03:59
los dos a la vez, el marcar uno no desmarca 00:04:01
el otro automáticamente 00:04:03
van por libre, no es el funcionamiento 00:04:04
habitual de los radiobutton, podríamos 00:04:07
dejarlos así y es un radiobutton del cual yo puedo 00:04:09
extraer la información de si está seleccionado 00:04:11
o si no lo está y trabajar con él 00:04:13
pero no es una interfaz muy amigable 00:04:15
entonces 00:04:17
para que vayan asociados 00:04:19
y cuando activemos uno se desactive el otro 00:04:21
tenemos que meterlos en un grupo de botones 00:04:23
tenemos que meterlos en un grupo de botones 00:04:26
eso os he dicho en el ejercicio 00:04:28
y lo habéis buscado 00:04:29
pues lo habéis encontrado 00:04:30
entonces 00:04:31
estos dos radio botón de aquí 00:04:34
vamos a meterlo en un grupo de botones 00:04:37
que era 00:04:40
no sé si era con 00:04:42
vale 00:04:46
corregidme o si no 00:04:53
miramos la chuleta porque no sé si era 00:04:56
button group o j button group 00:04:58
button group 00:05:00
era 00:05:04
vale 00:05:04
button group 00:05:08
vale 00:05:11
y ahora a ver 00:05:12
los que tienen j son para 00:05:14
distinguirlo de la versión antigua porque todos 00:05:16
estos componentes el j button el j label 00:05:18
de Swing, existían 00:05:20
también en el paquete antiguo, que es 00:05:23
el AWT, como 00:05:25
Button, Label, entonces 00:05:27
el paquete AWT no se ha eliminado 00:05:28
porque sigue teniendo la gestión 00:05:31
de eventos. Entonces, para que 00:05:33
los nuevos componentes de Swing no se confundan 00:05:35
pues se les ha puesto J delante 00:05:37
y ya está. Entonces, Button Group no tiene 00:05:38
su equivalente en AWT, por eso no se le ha 00:05:41
puesto la J, aunque es de Swing también. 00:05:43
A lo mejor es que al revés, porque 00:05:44
no tenía su equivalente en AWT, por lo tanto 00:05:46
se han ahorrado la J. 00:05:48
Justo lo acabo de decir 00:05:50
No, no, este es de swing 00:05:51
Entonces como este no tenía 00:05:54
Su equivalente no le han puesto la j 00:05:55
Entonces al grupo le podemos añadir 00:05:57
Ya nuestros botones 00:06:00
Que como no les he cambiado el nombre 00:06:01
En la aplicación tiene un nombre horroroso 00:06:02
Pero bueno, como nos gusta ir rápidos 00:06:04
Las cosas bonitas ya las hacéis vosotros 00:06:06
Entonces añadimos el botón 1 00:06:08
Y el botón 2 00:06:12
Bueno, no, 1 es el que no tiene nada 00:06:13
Es el 1 y el sin nada 00:06:16
y ahora ya 00:06:18
se supone que 00:06:21
ahora ya sí 00:06:23
que esto ya nos gusta más 00:06:25
esto es simplemente una cuestión de funcionamiento de la interfaz 00:06:27
nada más 00:06:29
vale 00:06:30
pues ahora ya, evento de insertar factura 00:06:31
pues muy fácil 00:06:39
insertar factura 00:06:40
¿qué tiene que hacer? crear una factura nueva 00:06:48
con los datos y ya está 00:06:50
pero crear una factura nueva 00:06:52
implicará crear también 00:06:54
el número de factura 00:06:56
claro, y el 00:06:59
no, aquí no, porque cada factura tiene el suyo 00:07:01
claro, entonces 00:07:03
pero cuando lo creemos, claro 00:07:07
entonces, esto no se 00:07:08
mete desde la aplicación, el número de factura 00:07:11
lo genera, o sea, no lo mete el usuario 00:07:13
lo genera la aplicación, entonces tenemos que pensar 00:07:15
un mecanismo para generarlo 00:07:17
pues ya lo hemos hecho algunas veces, vamos a poner 00:07:18
en algún sitio donde pegue 00:07:21
y donde pega, pues aquí donde tengo 00:07:23
los datos en algún sitio donde 00:07:25
pegue, pues 00:07:27
vamos a poner una variable 00:07:29
que nos sirva como secuencia. 00:07:31
Secuencia 00:07:35
para numFactura. 00:07:36
¿Vale? Las secuencias 00:07:40
se usan en muchos contextos, 00:07:41
en el contexto de las bases de datos también, 00:07:43
porque como las claves primarias 00:07:45
necesitamos que sean distintas, tú te haces 00:07:46
una secuencia en SQL. ¿Habéis hecho 00:07:49
ya secuencias en SQL? 00:07:51
pues es un procedimiento 00:07:52
en SQL que te genera un número 00:07:54
cuando tú se lo pides 00:07:56
directamente desde SQL, entonces para hacer las claves 00:07:58
primarias viene muy bien 00:08:00
tú llamas a la secuencia y ya te mete 00:08:03
un identificador único 00:08:04
entonces inicialmente 00:08:07
lo podemos poner pues a 1 00:08:08
la primera factura que sea la 1 00:08:10
y ahora ya 00:08:12
el evento este de aquí 00:08:15
pues ya está, es crear una 00:08:18
factura 00:08:20
Claro, pero estás incrementando este 00:08:21
Bueno, es que la que vamos a incrementar es esta 00:08:35
Entonces, como no tengo el constructor sin parámetros 00:08:38
Que vamos a ponerlo 00:08:44
Porque a mí me es más cómodo que el otro 00:08:46
Que lo tengo que meter 00:08:49
Prefiero hacerlo set después 00:08:49
Pues vamos a ponerle 00:08:51
El constructor 00:08:53
ala, y ahora ya 00:08:55
le ponemos los datos 00:09:01
venga 00:09:03
el número de factura 00:09:06
pues está claro que va a ser 00:09:08
datos 00:09:10
punto 00:09:13
secuencia en un factura 00:09:14
y vamos a dejarla ya incrementada 00:09:16
para la siguiente 00:09:18
y ahora factura 00:09:19
pues la cantidad va a ser lo que haya 00:09:24
en el área de texto 00:09:26
de factura, que vete a saber 00:09:27
cómo se llama ese textfield 00:09:30
la cantidad 00:09:32
textfield 00:09:33
barra baja 1 00:09:37
bueno, no me cuesta nada 00:09:37
cambiarlo, ni a vosotros tampoco 00:09:41
cantidad y ya está 00:09:42
y ya de paso cambiamos el de arriba 00:09:44
a dirección 00:09:47
bueno, pues entonces el área de texto 00:09:49
tiene 00:09:57
cantidad.gettest 00:09:58
y aquí con double parse double 00:10:04
claro, de nuevo 00:10:08
no le estamos haciendo nada robusta 00:10:12
aquí idealmente habría que 00:10:14
mirar que antes de hacer esto 00:10:16
de hacer el set 00:10:18
que este área de texto tenga algo dentro 00:10:19
y si no lo tiene 00:10:21
sacarle un jOptionPane 00:10:23
introduzca un valor para la cantidad 00:10:25
¿vale? 00:10:27
pero todos esos detallitos son hacer lo mismo 00:10:29
una y otra vez que se pueden incorporar 00:10:31
cantidad.vectest 00:10:33
double parse double y ¿qué pasa? que me falta 00:10:36
un paréntesis 00:10:37
la dirección 00:10:38
y luego el tipo 00:10:43
y ahora el tipo 00:10:44
cero si es particular, uno si es empresa 00:10:58
por ejemplo, cero si particular 00:11:01
uno si es empresa 00:11:03
¿por qué la he puesto yo de Abel? 00:11:04
porque me admito céntimos 00:11:08
¿qué otra cosa podría ser? 00:11:10
al precio 00:11:16
cantidad de producto 00:11:17
Bueno, podía ser un producto y medio 00:11:20
Pero no, no sería 00:11:25
Bueno, pues aquí, claro 00:11:27
Vamos a ver qué botón está seleccionado 00:11:29
Vamos a ver qué botón está seleccionado 00:11:32
El radiobutón este 00:11:37
Espera, no 00:11:39
Tenía un nombre horrible, vamos a cambiarle de nombre 00:11:40
boot empresa 00:11:43
le estoy llamando y a este boot particular 00:11:53
porque es que si no 00:11:56
queda horrible, boot particular 00:11:58
vale 00:12:00
pues entonces si este está activado 00:12:01
le pondremos a cero y si no 00:12:04
le pondremos a uno 00:12:05
bueno, vamos aquí otra vez 00:12:06
entonces 00:12:09
boot punto 00:12:10
boot empresa 00:12:13
punto 00:12:15
como está abajo 00:12:17
no lo reconoce, ¿vale? 00:12:19
ya con estas cosas, como se han unido otra vez 00:12:21
luego en el examen, que es, repito 00:12:23
la única herramienta que tenemos 00:12:25
oficial para evaluaros, pues como estas cosas 00:12:26
se han unido otra vez, que nos quiten tiempo 00:12:29
¿por qué no me lo detecta? 00:12:31
pues porque está abajo, y el compilador funciona 00:12:33
como un pseudo intérprete, va línea por línea 00:12:35
lo más rápido, pasarlo 00:12:37
fuera, de variable de 00:12:39
ah, claro, si no tiene error de 00:12:41
compilación el designer no te lo abre bien. Entonces vamos a quitar el error de compilación 00:12:43
para que se abre el designer y ahora a este botón le vamos a pasar de variable local a variable de 00:12:51
clase y a este le vamos a pasar a variable de clase también. Así ya es accesible desde cualquier lado 00:13:02
aunque esté instanciado 00:13:08
abajo 00:13:10
ahora ya sí 00:13:10
en el evento en el que estábamos 00:13:13
que era este 00:13:15
ahora ya sí que lo debería reconocer 00:13:16
y me da 00:13:24
y tendrá un método para ver si está seleccionado 00:13:26
o no 00:13:28
que 00:13:30
is selected 00:13:30
a ver el que lo haya hecho que me lo diga 00:13:35
y no me estoy aquí todo el rato 00:13:37
is selected 00:13:39
Selected, efectivamente 00:13:43
¿Está seleccionado? 00:13:51
Pues entonces 00:13:55
A tipo le daremos el 0 00:13:56
Ahora lo que no 00:14:08
Pues le daremos el 1 00:14:15
Uy, dos puntos 00:14:16
Y ahora ya hacemos el set 00:14:19
¿Vale? 00:14:21
Venga 00:14:25
Y ahora ya 00:14:26
como están en un grupo, sí 00:14:28
a menos que sea al arrancar 00:14:37
claro, a menos que sea al arrancar 00:14:40
por eso, es otra 00:14:41
es otra cosa en la que es 00:14:43
poco robusta, igual que no está verificando 00:14:46
que tú hayas puesto realmente en los campos 00:14:48
dirección o cantidad, lo está tomando sin más 00:14:50
y habría que verificarlo para decirle 00:14:52
pues aquí habría que verificar 00:14:53
que alguno de los dos está 00:14:55
para así no avisarle 00:14:57
nosotros asumimos que él ha dado a todo 00:15:00
entonces al haber dado a todo 00:15:03
si este no está, es que está el otro 00:15:04
pero efectivamente 00:15:06
nos va a dar errores de ejecución 00:15:09
si le damos a añadir factura 00:15:11
y no ha metido los datos 00:15:13
entonces habría que hacer 00:15:16
una validación antes para ver si todo está relleno 00:15:17
pero esa validación es comprobar 00:15:19
claro, entonces 00:15:21
aquí lo ideal sería 00:15:23
hacer un método 00:15:25
adicional 00:15:26
que fuera 00:15:29
validar, así 00:15:30
algo así 00:15:33
que la validación 00:15:38
de dado falso, pues le decimos simplemente 00:15:40
option pane punto 00:15:44
introduzca 00:15:46
todos los datos 00:15:49
así nos vamos uno por uno 00:15:50
ah no, es que he cogido una versión 00:15:52
en la que esta sería el padre 00:15:58
pero no hace falta poner el padre 00:16:00
porque solo hay un padre que es el frame 00:16:03
entonces voy a poner directamente el mensaje 00:16:04
es que tiene varias 00:16:06
introduzca todos los datos 00:16:07
vale 00:16:12
y el show message dialogue 00:16:16
creo que si te obliga 00:16:17
a poner el padre 00:16:20
eso, este si te obliga 00:16:21
a poner al que está asociado 00:16:24
pero es el que pone null que es el por defecto 00:16:26
y me vais a permitir 00:16:28
de nuevo con 00:16:32
porque vais a estar 00:16:35
calladitos y no lo vais a decir 00:16:38
me vais a permitir 00:16:40
poner un retorno 00:16:42
porque vosotros ya sabéis 00:16:44
ya sabéis que un código estructurado 00:16:47
se intenta 00:16:49
que salga solo por un sitio 00:16:50
y no salga solo por varios 00:16:52
pero también tenemos que sobrevivir 00:16:54
y no estar aquí escribiendo 00:16:57
no retorno porque salimos del método 00:16:58
si no están todos los datos, tú ya sales 00:17:00
no haces factura ni nada, entonces él verá el mensajito 00:17:02
marcará los datos 00:17:05
y volverá a dar insertar factura 00:17:06
entonces otra vez volveremos a entrar 00:17:08
entonces validar lo vamos a dejar en blanco 00:17:10
pero aquí 00:17:12
validar 00:17:14
y este método validar ahora mismo 00:17:16
que nos dé true todo el rato, que valide siempre 00:17:18
pero sería interesante 00:17:21
que validara que todos los campos 00:17:22
están rellenos, lo que hace Javascript 00:17:24
en una aplicación web 00:17:26
lo que hace javascript 00:17:28
esa validación 00:17:30
una de las cosas 00:17:31
para las que usamos javascript 00:17:35
porque programar una validación 00:17:36
en el lado servidor de la aplicación 00:17:38
es una locura 00:17:40
porque hay un tránsito de datos por la red todo el rato 00:17:40
entonces las validaciones se programan 00:17:43
en el lado cliente 00:17:45
que es en el propio navegador 00:17:46
y para eso está javascript 00:17:47
que está ahí en tu cliente validando 00:17:49
vale pues entonces ahora ya si 00:17:51
le ponemos el tipo s 00:17:53
y ya está 00:17:56
y metemos la factura en el map 00:18:00
imagino que en el lado del servidor 00:18:01
también va a salir algún tipo de validación 00:18:05
si necesitas que sean 00:18:06
contra la base de datos 00:18:09
00:18:11
esa palabra no me gusta nada 00:18:11
pero es la que se usa 00:18:15
porque para la base de datos 00:18:17
solo tiene acceso 00:18:19
el servidor 00:18:20
entonces si esas validaciones 00:18:22
necesitas campos de la base de datos 00:18:23
las tienes que mandar al servidor 00:18:24
y el servidor ya accede a la base de datos 00:18:26
Bueno, al menos que estés usando 00:18:27
librerías de Javascript 00:18:30
o que le estés pasando tú 00:18:33
la información a Validad 00:18:35
A ver, lo puedes hacer de muchas maneras 00:18:36
Nadie usa Javascript 00:18:37
parece que se usa mucho JQuery 00:18:40
Sí, bueno, JQuery son librerías para Javascript 00:18:41
Claro 00:18:45
Bueno, a ver, cuando yo digo Javascript básico 00:18:45
no me refiero al básico, en realidad hablo de 00:18:49
Javascript y todo el acceso a todos esos 00:18:50
paquetes de librerías que tienen, entre ellos Javacuery 00:18:52
o AJAX o todas esas cosas 00:18:54
venga, pues ahora ya en facturas 00:18:56
ya le ponemos, no en facturas, no, en datos 00:18:59
punto 00:19:02
facturas 00:19:03
ahora ya sí 00:19:05
le ponemos a este 00:19:07
punto put 00:19:09
el número de factura 00:19:14
el número de factura 00:19:22
que es factura 00:19:24
punto 00:19:26
getNumFactura y la factura en sí 00:19:27
y fact 00:19:31
vale, de nuevo 00:19:37
no estamos haciendo ninguna validación 00:19:42
si la factura está, si no está 00:19:43
todas esas comprobaciones, validaciones 00:19:45
para avisar de posibles 00:19:48
errores, pues bueno 00:19:50
sería interesante hacerlas pero no tenemos tiempo 00:19:51
vale, entonces la aplicación ya tiene 00:19:54
datos, ¿qué pasa si yo ahora cierro la 00:19:56
aplicación? pues si cierro la aplicación 00:19:58
la factura que he metido se va 00:20:00
a la basura y cuando arranco la aplicación 00:20:02
no tengo facturas, jolín, yo quiero 00:20:04
poder cerrar la aplicación, irme 00:20:06
a dormir y cuando la arranque 00:20:08
ver en mi desplegable las facturas que tenía ayer. 00:20:10
Y no solo eso, sino que la secuencia en un factura 00:20:12
se vuelve a 1. 00:20:14
Efectivamente, 00:20:18
muy bien pensado. 00:20:18
Claro, aquí además de volcar los datos, 00:20:20
tendríamos que volcar el último 00:20:22
número de factura generado 00:20:24
para inicializar con el en un factura. 00:20:25
Efectivamente. Vale, entonces 00:20:28
aquí, en cuanto ya vemos que tenemos 00:20:30
datos, decimos, a ver, si esta aplicación es 00:20:32
persistente cuando yo la cierre quiero que pase algo que quiero que pase guardar los objetos 00:20:34
entonces vamos a ver cuándo vamos a cerrar la aplicación en nuestro caso cuando le demos a la 00:20:42
equis está vale nosotros como ya le hemos puesto el close window no sé que cuando le damos a la 00:20:49
equis sale cierra sin más pues pero no es eso lo único que queremos entonces vamos a hacer otra 00:20:57
cosa. Vamos a capturar 00:21:03
el evento de darle a la X. 00:21:05
Porque si capturamos el evento de darle a la X, 00:21:07
yo en ese evento puedo meter lo que me dé la 00:21:09
gana. Entre esas 00:21:11
cosas podré meter llevar todas las 00:21:13
facturas a un fichero de objetos. 00:21:15
Vale, pues ¿cómo podamos 00:21:18
capturar ese evento? Bueno, pues el frame 00:21:19
igual que cualquier otro 00:21:21
componente, se le 00:21:23
pueden asociar listener. 00:21:25
Se le pueden asociar listener. 00:21:27
En el caso del frame son, no se 00:21:29
llaman listener, se llaman adapters. 00:21:31
¿vale? entonces 00:21:32
vamos a hacerlo 00:21:34
vamos a aquí 00:21:35
vamos a crearnos una clase 00:21:37
interna 00:21:40
para no hacer tantas clases 00:21:41
este método se cierra aquí 00:21:44
vamos a 00:21:46
crearnos 00:21:50
class 00:21:51
listener del frame 00:21:53
este es el que escucha el frame porque la 00:21:58
x está en el frame 00:22:00
vale 00:22:01
que este va a heredar de 00:22:04
A ver si me acuerdo sin mirar la chuleta 00:22:06
De window adapter 00:22:08
A ver 00:22:11
Vale, window adapter 00:22:17
De event 00:22:20
¿Veis que dice ahí? 00:22:20
Vale 00:22:24
Venga, pues window adapter 00:22:25
Es de Java, WT, igual que los listener 00:22:27
Y que todos, window adapter 00:22:30
Vale 00:22:32
¿Eh? 00:22:32
¿Lo puedes repetir? 00:22:35
A ver, ¿cómo funciona 00:22:36
la captura de un evento sobre un componente? 00:22:40
Tú te haces una clase listener donde 00:22:42
en los métodos que tiene dentro 00:22:43
pones la 00:22:45
respuesta al evento que tú estás 00:22:47
capturando. En nuestro caso, aquí lo que queremos 00:22:49
capturar es un evento 00:22:51
pero ¿sobre quién? Sobre el frame. 00:22:53
No sobre un botón ni sobre nada. 00:22:55
Una clase listener hay que hacer 00:22:58
igualmente. Pero 00:22:59
las clases que escuchan al frame 00:23:01
son adapter y 00:23:03
Y en particular es esta, es decir, no vamos a implementar ActionListener, sino que vamos a heredar de WindowAdapter. 00:23:05
Pero es lo mismo, esto es una clase que es capaz de estar conectada escuchando el frame. 00:23:14
Lo que pasa es que en lugar de ser una clase que implemente ActionListener, pues es una clase que hereda de WindowAdapter. 00:23:19
ya está, pero eso la convierte 00:23:25
también en clase escuchadora 00:23:27
en clase listener, que es capaz 00:23:29
de responder 00:23:31
de despertarse cuando pase 00:23:33
lo que digamos, pero claro, hay que asociarla 00:23:35
al frame, vale 00:23:37
pues el frame nuestro, que lo estamos construyendo 00:23:39
aquí, ya le quitamos esto 00:23:41
le vamos a quitar esto, cuando le demos a la x 00:23:43
ya no queremos exit, tal cual, no queremos exit 00:23:47
le vamos a 00:23:50
decir a nuestro frame 00:23:51
que es a dis 00:23:53
vamos a añadirle 00:23:55
un window adapter 00:23:58
un window listener 00:24:01
¿vale? 00:24:04
y le vamos a 00:24:05
un new 00:24:07
creo que sí 00:24:09
si no lo cambiamos a window listener 00:24:13
a listener frame 00:24:15
vamos a ponerle un new 00:24:16
listener frame 00:24:18
¿vale? 00:24:20
es decir, window adapter está en la jerarquía de window 00:24:30
listener, entonces 00:24:33
ahora ya, cuando yo le dé a la 00:24:34
x, lo que se va a ejecutar 00:24:37
es lo que yo ponga en el 00:24:39
método que sobrescriba aquí dentro 00:24:41
como veis, window adapter tiene métodos 00:24:42
pero como estoy heredando y no estoy sobrescribiendo 00:24:45
no me obliga 00:24:47
si estuviéramos implementando window listener 00:24:48
sí, entonces igual así no lo pones más fácil 00:24:51
porque si no me lo tengo que aprender de memoria que creo que era 00:24:53
window closet 00:24:55
pero no estoy muy segura 00:24:56
public void 00:24:58
y aquí sería 00:25:00
window 00:25:09
action event o window event 00:25:11
claro, vamos a ponerlo 00:25:13
a listener que así me va a obligar 00:25:17
ya y va a ser más fácil 00:25:19
porque si no tenemos que preguntárselo a HGPT o mirar la documentación 00:25:21
y da pereza 00:25:23
Vale, entonces quitamos esto, importamos, efectivamente ahora me dice como estás implementando 00:25:24
una interfaz tienes que sobreescribir los métodos que, este se ha quedado tan ancho 00:25:39
lógicamente como era de esperar, yo le puedo añadir tanto un window listener como un window 00:25:45
adapter, está en la misma jerarquía 00:25:49
pero nos hemos ahorrado trabajo 00:25:50
este, se llamaba window close 00:25:52
ah, pues iba bien 00:25:58
porque lo tengo que instanciar 00:25:59
claro 00:26:06
vale, pues entonces 00:26:08
esto es 00:26:12
lo que va a pasar cuando el frame 00:26:13
se abra 00:26:16
cuando el frame 00:26:16
ya esté cerrado 00:26:19
y cuando el frame se esté cerrando 00:26:20
no acabo de entender muy bien el matiz 00:26:22
pero un matiz de diferencia habrá 00:26:24
entonces, en nuestro caso, cuando demos a la X 00:26:25
se despertará 00:26:29
este, asumo 00:26:31
y aquí es cuando 00:26:32
queremos guardar los objetos 00:26:34
¿vale? queremos guardar los objetos 00:26:36
y además que la aplicación termine 00:26:38
que la aplicación termine es muy fácil 00:26:40
porque para eso tenemos 00:26:43
este, no, el de antes 00:26:44
esta propia sentencia 00:26:46
SystemExit 00:26:48
que cierra la aplicación 00:26:50
SystemExit te cierra la aplicación 00:26:52
y además le devuelve el valor 00:26:55
de retorno al sistema operativo 00:26:57
el sistema operativo 00:26:58
como sabéis pues guarda un registro 00:26:59
de los procesos que se han cerrado 00:27:03
un entero de retorno 00:27:04
si te ha devuelto un cero se supone que se ha cerrado por la vía correcta 00:27:05
si no te devuelve un cero 00:27:09
se ha cerrado raro 00:27:10
vale pues entonces esto lo va a hacer 00:27:11
Pero antes de eso, va a guardar los objetos en un fichero. 00:27:14
Pues, ¿cómo se guardan objetos en un fichero? 00:27:19
La clase Object Output String. 00:27:21
Estas para escribir objetos en un fichero. 00:27:28
Tenemos que instanciarlos. 00:27:31
Vale, Object Output String, ¿a quién se asocia? 00:27:40
No al fichero directamente, sino a un File Output String que ya sí que esté asociado al fichero. 00:27:43
file output stream es el flujo básico 00:27:48
y object output stream se monta 00:27:52
por encima, entonces para que no me quede una línea 00:27:54
larguísima 00:27:55
no, no puedes poner 00:27:56
un file a secas, tienes que poner un file output stream 00:28:00
y sobre él ya el object output stream 00:28:02
entonces podría poner la misma línea 00:28:03
new file output stream del fichero 00:28:05
pero para que no me quede una línea enorme 00:28:07
voy a hacerlo aparte 00:28:09
solo para que 00:28:12
no me quede la línea enorme, no por nada más 00:28:14
vamos a 00:28:16
hacer un file output string 00:28:18
f cualquiera 00:28:19
asociado al 00:28:21
fichero de objetos. 00:28:23
Vamos a 00:28:30
un nombre, a nivel interno 00:28:31
ya está. A ver, podríamos 00:28:33
hacer que la aplicación cuando arranque te diga 00:28:35
en qué fichero tiene las facturas. 00:28:37
Pero bueno, que sea transparente para el usuario. 00:28:40
Que él tenga su fichero interno, lo habla, lo cierra y el usuario 00:28:41
ni se entere de que está abriendo y cerrando un fichero. 00:28:43
Pues venga. 00:28:46
Facturas.dat por ponerle una 00:28:47
extensión o cualquier cosa. 00:28:49
file output string, hay que importarlo 00:28:54
lógicamente de java.io 00:28:56
y ya está. 00:28:58
¿Vale? Entonces, 00:29:01
si el fichero no existe, lo va a crear 00:29:02
nuevo, como file writer. 00:29:04
Este es el equivalente a file writer, pero para mandar bytes. 00:29:06
Si el fichero no existe, lo crea nuevo. 00:29:09
Y si existiera, 00:29:10
en función de si después 00:29:13
hemos puesto true o false, 00:29:14
o añade o sobrescribe. 00:29:16
Pero a este file output string sí le puedes 00:29:18
pasar un file, un objeto file. 00:29:20
justo, a file output string 00:29:22
o bien le paso el string 00:29:24
o bien le paso un objeto file 00:29:25
asociado a ese 00:29:27
créate 00:29:30
yo creo que te coge la hecho 00:29:37
sí, sí, pero tenemos las dos posibilidades 00:29:41
entonces lo que 00:29:45
es que me da una rabia cuando no me hace lo de los 00:29:46
import 00:29:49
pero no pasa nada 00:29:50
hacemos aquí un 00:29:54
¿Dónde está él? 00:30:02
Al lado del file output stream 00:30:08
Para 00:30:09
Bueno, las de ficheros 00:30:10
Son todas de javaio 00:30:15
Pero esas ya son 00:30:17
Vale, file 00:30:18
Ya lo tenemos ahí, el window adapter ya 00:30:20
Nos sobra 00:30:23
Javaio 00:30:24
Ya está ahí 00:30:27
Entonces, o bien le pasamos el file 00:30:30
o este, en este caso 00:30:33
es más corto pasar el nombre del fichero 00:30:34
lo que pasa es que normalmente a este 00:30:36
método podríamos haber llegado habiéndole 00:30:39
pasado un parámetro o que lo coge 00:30:41
el de otro sitio 00:30:43
y cuando un fichero se pasa por parámetros eso le pasa 00:30:44
al objeto file, no a la cadena 00:30:47
pero bueno, entonces file output string 00:30:48
me dirá, oye cuidado 00:30:50
que puede que haya una excepción 00:30:52
como veis, ni se plantea 00:30:54
ofrecerme el throws, porque yo no 00:30:57
puedo poner el throws aquí, porque si lo pusiera aquí 00:30:59
estaría cambiando la cabecera del método 00:31:01
Y este es un método sobrescrito, entonces no puedo tocar la cabecera, entonces ni me lo ofrece. En algunas cosas sí es relativamente listo Eclipse. Vale, FileOutputString, ahora ya sí, vamos a meterlo todo en el mismo try-catch, ahora ya sí que podemos asociar el ObjectOutputString a este, al F. 00:31:02
e importamos 00:31:30
object output string 00:31:34
de java.io 00:31:36
y ahora 00:31:37
y de nuevo la excepción 00:31:39
pero añadimos un catch 00:31:41
ahora ya tiene dos catch 00:31:43
y ahora ya 00:31:44
hay que escribir el archivo 00:31:48
hay que escribir las facturas 00:31:50
todas, entonces en este caso 00:31:52
estamos poniendo que si el archivo 00:31:54
ya existía de antes 00:31:56
lo elimine y empiece de nuevo 00:31:57
vale, pero es que esa opción nos vale 00:31:59
porque cuando la aplicación ha arrancado ha cargado 00:32:02
ya todas las que había, luego en el map están todas 00:32:04
entonces yo quiero volver a escribirlas todas 00:32:06
y lo que había antes en el fichero lo elimino 00:32:08
entonces 00:32:10
en este caso no pondríamos el 00:32:11
true después, vale, ahora ya simplemente 00:32:14
recorremos el map 00:32:16
e incluso 00:32:17
podríamos 00:32:20
tratar el map, es un objeto a su vez 00:32:21
pues podríamos escribir el 00:32:24
map de golpe, no hace falta que vayamos 00:32:26
objeto por objeto del map y escribir 00:32:28
uno por uno, podríamos, podríamos mandar 00:32:30
el propio map, ¿vale? pero vamos a escribir 00:32:32
los objetos uno por uno para 00:32:34
que veamos una cosa 00:32:35
podría, ¿vale? 00:32:37
pero vamos a enviar los objetos uno por uno 00:32:40
entonces, así, vamos a recorrer 00:32:41
el map, te estás durmiendo, Pablo 00:32:44
¿cómo recorremos el map? vamos a 00:32:45
ir sencillo, vamos a sacar 00:32:53
vamos a sacar 00:32:56
un set 00:32:58
con las claves 00:33:00
Vamos a sacar un set con las claves 00:33:01
Y ya está 00:33:05
Datos.facturas.keyset 00:33:10
¿Vale? 00:33:17
Este es un set con las claves 00:33:18
Pues vamos clave por clave 00:33:20
Y añadimos 00:33:21
Objet.outputString 00:33:23
Tiene un método 00:33:25
Estupendo 00:33:26
Que es el método 00:33:27
WriteObject 00:33:28
Para mandar el objeto a mogollón 00:33:29
¿Y qué objeto queremos enviar? 00:33:31
Pues de datos.facturas 00:33:33
queremos enviar el get 00:33:35
numfactura. 00:33:37
Ese es el que queremos enviar. 00:33:40
Numfact, efectivamente. 00:33:43
¡Hala! Ya hemos guardado 00:33:46
todas las facturas una por una 00:33:47
y ahora ya lo único que tenemos que hacer es 00:33:49
como tenemos 00:33:51
los dos flujos, uno por 00:33:53
abiertos, pues vamos a cerrar los dos 00:33:55
y ya está. 00:33:57
Entonces se van a ver quedados 00:34:03
todos guardados y salimos de la aplicación. 00:34:04
y el propio map como es un objeto 00:34:06
te lo guarda todo a mogollón 00:34:13
eso luego nos va a facilitar la lectura 00:34:14
porque haríamos un solo real 00:34:16
pero vamos a dejarlo así 00:34:17
entonces vamos a ejecutar a ver si al cerrar 00:34:19
realmente nos aparece un archivo 00:34:22
que no vamos a poder leer porque tiene información rara 00:34:24
adiós 00:34:28
hasta luego 00:34:32
pero si estás disfrutando 00:34:38
Pablo, que lo sé yo 00:34:41
vale, vamos a ver 00:34:42
cuántas cosas hemos hecho mal 00:34:46
venga 00:34:48
dirección 00:34:49
pues dónde va a estar la factura 00:34:51
en Madrid 00:34:54
¿cuánto? 300 euros 00:34:55
va a ser una factura 00:34:58
a la empresa, porque 300 euros es mucha pasta 00:35:00
venga 00:35:03
insertamos factura 00:35:04
a ver qué pasa 00:35:06
No ha salido nada rojo 00:35:08
Eso no significa nada 00:35:10
Claro, nos falta 00:35:12
En el evento de insertar factura 00:35:13
Deberíamos añadir esto 00:35:16
Pero ahora lo hacemos, no pasa nada 00:35:17
Venga, vamos a insertar otra 00:35:19
Claro 00:35:21
Vale, eso 00:35:23
Vamos a insertar una particular a Barcelona 00:35:25
Insertar factura 00:35:28
Vale 00:35:29
Ahí están, pero como no tenemos todavía 00:35:31
Lo de recuperar, pues nada 00:35:34
Ahora vamos a cerrar 00:35:35
cerramos 00:35:36
ha salido un error 00:35:38
a ver 00:35:41
al evento ha tenido que llamar 00:35:42
porque si no ha llamado al evento habría cerrado 00:35:44
tan ricamente 00:35:46
al evento ha llamado y que nos ha dicho 00:35:47
cuidado que factura 00:35:50
no es un objeto serializable 00:35:52
como pretende serializarlo 00:35:54
un archivo si no es serializable 00:35:57
por dios 00:35:58
eso muy bien 00:35:59
veis como ya vais dando las respuestas 00:36:02
ya vais dando 00:36:04
los pensamientos informáticos 00:36:07
que es que si este tío te dice 00:36:09
no eres serializable 00:36:10
que tiene que hacer una clase, no pasa nada 00:36:12
me convierto en alguien serializable 00:36:14
como acaba enable 00:36:17
automáticamente hacemos la conexión 00:36:19
de que va a ser una interfaz 00:36:21
al acabar enable 00:36:22
hacemos la, vale, pues ya está 00:36:24
decimos, ah, vale 00:36:27
no pasa nada 00:36:29
¿cómo te conviertes en serializable? 00:36:30
Implementando la interfaz que te dé ese comportamiento 00:36:32
Pues ya está 00:36:35
Implement serializable 00:36:37
Y serializable 00:36:41
Pues lo importamos de javallo también 00:36:43
Ah, la ya es serializable 00:36:45
00:36:47
No, ya van a estar serializados 00:36:49
Sí, sí 00:36:55
Vale, entonces vamos a volver a 00:36:56
Pero a ver 00:36:58
ya es serializable 00:37:01
con lo cual ya la puedo serializar 00:37:04
bajo el criterio de soy serializable 00:37:06
con lo cual eres capaz de coger todas mis propiedades 00:37:13
ponerlas en fillete y meterlas en el fichero 00:37:15
no hace falta más 00:37:17
claro 00:37:18
porque para que un objeto 00:37:22
pueda ser sacado de una tubería 00:37:25
os acordáis que la tubería la he dibujado así 00:37:27
eso significa que las cosas tienen que entrar en fila 00:37:29
entonces, entrar en fila 00:37:32
es un bit detrás de otro serializa 00:37:34
eso es serializar 00:37:36
entonces un objeto no está serializado 00:37:37
pero la interfaz serializable 00:37:40
no te obliga a informar 00:37:42
no necesita más informar 00:37:43
no, no, no, no, el hecho de que 00:37:45
algo implemente serializable 00:37:48
ya coge dentro de sí para implementarlo 00:37:49
todo lo que serializable tiene 00:37:52
y todo lo que serializable ya tiene 00:37:53
que tú has heredado por implementar 00:37:55
ya es lo único que necesita 00:37:57
el output stream para serializarte 00:38:00
no necesita que tú implementes ningún 00:38:02
método, necesita nada más 00:38:04
claro, depende de la interfaz 00:38:05
y para qué sirva, esta no te obliga a nada 00:38:10
tú ya coges lo que tengas 00:38:11
serializable y el output stream no le hace 00:38:13
falta nada, lo que tenías serializable es suficiente 00:38:15
venga, hemos insertado una 00:38:17
ya nos vamos 00:38:19
ya no, no nos vamos 00:38:20
no, cerramos la 00:38:24
uy, estoy a punto de quedarme 00:38:25
sin batería 00:38:27
y no lo sé 00:38:29
que repetimos 00:38:30
vale, a ver 00:38:34
claro, o sea, entiendes 00:38:38
que ahora el frame 00:38:41
también recibe eventos 00:38:43
entre ellos, pues esto es un evento 00:38:45
esto es un evento 00:38:47
y darle a que es un evento 00:38:49
hasta ahora no hemos querido 00:38:52
capturar ninguno 00:38:54
porque poniendo 00:38:55
el window on closing con esto 00:38:56
era un atajo para que 00:38:58
al darle a la X se hiciera un 00:39:00
system exit, no teníamos que hacer 00:39:02
un listener específico, es un atajo para que sea 00:39:04
un system exit, pero es que ahora no nos vale solo el 00:39:06
system exit, ahora queremos que además 00:39:08
se lea un map, se pasa, con lo cual tenemos 00:39:10
que capturar el evento, los eventos de 00:39:12
frame no se capturan con action listener 00:39:14
sino con window listener, pues 00:39:16
por eso hemos hecho una clase interna 00:39:18
window listener 00:39:20
aquí, que podía haber sido 00:39:22
windowAdapter también 00:39:24
porque una herida de la otra 00:39:25
pues por eso hemos hecho una clase interna 00:39:28
windowListener que tiene unos métodos 00:39:30
y en particular el método 00:39:32
windowClosing es el que se ejecuta 00:39:34
cuando tú le das a la X 00:39:36
pues entonces hemos metido en este método 00:39:38
lo que queríamos, escribir el objeto 00:39:40
¿había otro método que tenía el closing? 00:39:42
sí, no sé muy bien cuál es la diferencia 00:39:44
la tendrá evidentemente 00:39:46
esto es algo que pasa 00:39:49
una vez que está cerrado, a lo mejor esto es cuando 00:39:50
le das a la X y esto es 00:39:52
si has tenido éxito y has podido soltar 00:39:54
y se ha cerrado 00:39:56
no lo sé, se podría comprobar 00:39:57
entonces claro 00:39:59
nos falta asociarle 00:40:02
al frame un objeto 00:40:04
de estos, que es lo que hemos hecho con esta línea 00:40:06
el frame 00:40:08
que es this, el objeto this es el propio frame 00:40:10
pues le hemos añadido un window 00:40:12
laser que es un objeto de la clase interna que hemos hecho 00:40:14
entonces 00:40:16
nos habrá tenido que aparecer 00:40:17
aquí un objeto 00:40:20
pues justo, nos ha aparecido 00:40:22
facturas.dat 00:40:25
que es el que tiene los archivos 00:40:26
pero claro, este no es un fichero de texto 00:40:28
es un fichero de bits serializados 00:40:30
entonces si le dais a noble click 00:40:32
pues aquí no veis nada 00:40:35
porque que hace el editor del eclipse 00:40:37
lo interpreta como haste 00:40:39
y se va uno por uno y como haste le sale 00:40:41
esta cosa 00:40:43
pero esto no vale para nada 00:40:44
¿vale? 00:40:47
a ver, los stream 00:40:49
los ha traducido bien, pero el resto 00:40:50
no lo ha traducido bien. 00:40:52
Entonces, ¿para qué sirve este archivo 00:40:54
facturas.dat? Sirve 00:40:56
única y exclusivamente 00:40:58
para que una aplicación lo abra. 00:41:00
¿Vale? 00:41:03
Luego, luego, 00:41:04
¿cómo podríamos ya 00:41:07
modificar esta aplicación? Pues 00:41:08
en el momento de arrancar, 00:41:10
mirar si existe un fichero que se llama facturas.dat. 00:41:12
Y si el fichero existe, 00:41:14
cargarlo. 00:41:16
Vale, efectivamente 00:41:17
Entonces, aquí cuando estamos arrancando 00:41:20
La aplicación de mi constructor 00:41:23
Pues vamos a hacer aquí, por ejemplo 00:41:24
Antes que nada, esa parte 00:41:26
Vamos a ver si existe un fichero así 00:41:28
Pues vamos primero a crearnos un objeto 00:41:30
File 00:41:33
Que sea un new file 00:41:33
Con facturas 00:41:36
Punto dat 00:41:39
Vale 00:41:40
Vale, vamos a ver 00:41:42
No, no, es que esto no es para escribir 00:41:44
Esto es solamente un objeto file 00:41:49
Que nos permite extraer información 00:41:51
Pero no su contenido 00:41:52
En particular queremos la información de si existe o no existe 00:41:53
Vale, pues si este fichero file 00:41:57
Existe 00:41:59
Si existe 00:42:01
Entonces 00:42:02
Vamos a tener que cargar los datos 00:42:04
En lugar de meterlo aquí, que esto ya nos está quedando 00:42:06
Un constructor horrible 00:42:08
Vamos a hacernos un método 00:42:09
Que sea cargar los datos 00:42:11
y ya está 00:42:14
pues vamos a hacernos un método privado 00:42:14
auxiliar, cargar datos 00:42:18
porque esto es solamente 00:42:19
para leer del fichero y pasar al map 00:42:23
lo demás se hace sí o sí 00:42:25
como file new file 00:42:27
no hombre, porque yo necesito 00:42:32
hacer el exist y para eso necesito que le exista 00:42:34
no te entiendo 00:42:36
vale 00:42:37
solo te falta decir, porque tengo que esperar que me la soluciones 00:42:44
00:42:46
Vale, pues vamos a hacer el cargar datos 00:42:47
Venga, creamos el método cargar datos 00:42:51
Y aquí ya sí que aplica 00:42:54
Cargar datos está aquí abajo 00:42:55
Recordad que validar 00:42:58
Se os ha quedado a vosotros si lo queréis 00:43:00
Cargar datos ahora ya sí que 00:43:01
Ah, ya entiendo lo que dices 00:43:04
Que por acá te haces un cargar datos 00:43:06
Y dentro haces, si el fichero existe 00:43:08
Lo cargas, si no, no 00:43:10
Usadlo como quieras, ¿por qué no? 00:43:11
Pues 00:43:14
o sea 00:43:15
la máquina virtual va a ejecutar el mismo 00:43:17
código sí o sí 00:43:19
venga, cargar datos 00:43:20
ahora vamos a leer 00:43:27
aquí ya asumimos que el fichero existe 00:43:28
Ana no lo asume, con lo cual Ana se habrá hecho 00:43:30
aquí su file y si 00:43:32
no existe habrá hecho un retun 00:43:34
¿verdad? 00:43:36
vale, y entonces ya 00:43:38
la cosa se empieza 00:43:40
a poner fea, no le enseñéis 00:43:42
a Rosa nuestras aplicaciones 00:43:44
No, si con preguntarle una duda 00:43:46
ya se cabrea 00:43:48
Objet 00:43:49
¿Eh? 00:43:52
¿Pero qué hacéis? 00:43:55
¿Qué hacéis? Por Dios 00:43:56
Pues no te dejes copiar 00:43:57
Eso es de primero de estudiante 00:44:04
No te dejes copiar porque 00:44:06
la copia tienen culpa los dos 00:44:08
El que copia y el copiado 00:44:10
¿Cómo que no es culpa tuya? 00:44:11
Tú no dejes copiarte 00:44:15
vale, pues el 00:44:15
object input string es para llevar objetos 00:44:18
del fichero al map, que es lo que queremos 00:44:20
object input string 00:44:22
hay que pasarle un file input string 00:44:24
lo voy a poner ya 00:44:28
en línea 00:44:30
lo voy a poner ya en línea, un new file input string 00:44:30
asociado 00:44:37
cargar datos, vamos a pasarle el 00:44:38
file 00:44:40
de antes 00:44:41
vamos a pasarle el file a cargar datos 00:44:43
ahora es cuando subo y bajo 00:44:46
y os agobiáis 00:44:49
pues no os agobiéis 00:44:49
cargar datos necesita 00:44:51
el fichero sobre el que cargarlos 00:44:54
entonces se lo voy a pasar como parámetro 00:44:56
el fichero que tengo aquí 00:44:58
Ana no lo necesita, pero nosotros sí 00:44:59
bueno, sí, porque toda esta línea 00:45:02
ves ahí un cargar datos 00:45:06
¿por qué puede tener esto? 00:45:07
¿qué sentido podría tener si se lo queremos 00:45:10
buscar? que el que lo está mirando 00:45:12
contempla 00:45:14
interioriza, que no es una tontería 00:45:17
que podría no haber datos de partida 00:45:18
¿vale? podría no haber datos 00:45:20
de partida, el que esté arreglando este código 00:45:23
está haciendo cosas 00:45:24
pero ya está, y no se tiene que meter a cargar datos 00:45:25
a ver que pinta eso 00:45:28
es el único sentido que podría tener 00:45:30
venga, pues, sí 00:45:32
que sí, que ya me voy 00:45:34
vale, entonces, cargar datos, le pasamos el fichero 00:45:36
nos vamos a cargar datos 00:45:38
y ahora ya 00:45:39
asociamos el file input string a este 00:45:41
que hemos pasado. 00:45:44
No hay ninguna rayada. 00:45:48
Obvio, input string necesita un objeto 00:45:50
file input string que a su vez 00:45:52
necesita el file o el 00:45:54
nombre del fichero. Da igual. 00:45:56
Una cosa o la otra. Le pasamos el file. 00:45:58
Ya nos ponemos a importar a saco. 00:46:01
Importamos a saco 00:46:07
y capturamos 00:46:08
con el try. 00:46:09
Multicatch porque hay varias excepciones. 00:46:12
vale, ya hemos abierto 00:46:14
para leer, ahora 00:46:16
leer no es tan fácil como escribir 00:46:18
porque cuando uno escribe, escribe y se despreocupa 00:46:20
de lo demás, porque ya el fichero 00:46:22
se irá haciendo grande, pero irá albergando 00:46:24
leer no sabemos 00:46:26
hasta cuando tenemos que leer, entonces hay que hacer 00:46:28
un bucle de lectura, que es lee 00:46:30
mientras no hayas llegado al final, lee mientras no hayas 00:46:32
llegado al final, claro 00:46:34
hay un hash 00:46:35
next, pero 00:46:38
si hay una bailable 00:46:39
que te dice sí 00:46:44
pero bueno, vamos a hacerlo 00:46:46
mucho más general, que nos valga 00:46:48
para cualquier flujo 00:46:50
de asociado a un fichero, para cualquiera 00:46:52
porque el 00:46:54
método bailable hay veces que 00:46:58
no funciona muy bien y no 00:47:00
bueno, en cualquier caso 00:47:02
vamos a una solución más general, para cualquier 00:47:04
flujo, ¿qué pasa cuando 00:47:06
leemos 00:47:09
de un archivo 00:47:10
habiéndonos salido ya fuera 00:47:12
que sale 00:47:15
una excepción de tipo 00:47:17
en odd file 00:47:18
exception, se va a lanzar 00:47:20
esta excepción, en odd file 00:47:23
esa misma 00:47:24
entonces vamos a capturarla 00:47:27
y vamos, lee 00:47:29
mientras no haya saltado 00:47:31
esa excepción, es decir 00:47:33
vamos a hacer algo así 00:47:35
vamos a hacernos un boolean 00:47:36
que sea fin archivo 00:47:40
por ejemplo, inicialmente no hemos llegado a fin archivo 00:47:43
inicialmente no hemos llegado a fin archivo 00:47:46
ahora, mientras no hayas llegado 00:47:49
a fin archivo 00:47:53
mientras no hayas llegado a fin de archivo 00:47:54
¿qué tienes que hacer mientras no hayas llegado a fin archivo? 00:47:59
intenta hacer la lectura de un objeto, inténtalo 00:48:02
y en el caso de que te salga la excepción 00:48:04
en not file exception, captúramela 00:48:10
si te sale not file exception 00:48:12
me la capturas 00:48:14
y en el momento 00:48:17
de capturarmela porque ha salido 00:48:19
me pones fin archivo a true 00:48:21
entonces esto es más general 00:48:22
no dependemos de conocer 00:48:27
ningún método 00:48:29
y ahora ya cuando sale la excepción 00:48:30
he llegado al fin del flujo, esto se ha puesto a true 00:48:32
el while ya no va a intentar hacer más 00:48:35
vale, importamos 00:48:37
en not file exception 00:48:39
y ahora aquí que tenemos que hacer 00:48:41
mientras no hayamos llegado a fin archivo 00:48:43
hacemos la lectura del flujo 00:48:44
pues el OIS este tiene un método 00:48:46
como no podía ser de otra manera 00:48:48
readObject 00:48:51
que te va leyendo los objetos 00:48:52
secuencialmente desde el primero 00:48:55
luego se queda presionado y se viene así 00:48:56
readObject te devuelve 00:48:57
un objeto 00:49:01
como él no sabe lo que hay ahí 00:49:02
te lo devuelve como object 00:49:04
pero nosotros sabemos que hay facturas 00:49:05
entonces no pasaría nada 00:49:07
no lo puedes parametrizar 00:49:08
Entonces, lo hacemos un casting a factura y no pasaría nada, pero la idea es que queremos hacer con este, pues lo queremos meter en el map. Entonces, en nuestro map de datos, que como acabamos de arrancar la aplicación, está limpito y vacío, en nuestro map de datos, pues vamos a meter, bueno, vamos a, como tenemos que meter el número de la factura primero y luego eso, pues nos leemos primero la factura. 00:49:11
esto de nuevo es una excepción 00:49:40
que lo añadimos en una 00:49:42
en una 00:49:44
en una catch añadido 00:49:45
vale 00:49:48
y ahora 00:49:48
que pasa 00:49:51
vale y ahora ya si que podemos 00:49:55
poner en el map 00:49:56
datos.facturas.put 00:49:57
la factura que acabamos de leer 00:50:03
.get no factura 00:50:07
y la factura enterita 00:50:09
vale, entonces los leemos todos y los metemos 00:50:11
y ahora hay que actualizar 00:50:15
claro, y ahora 00:50:17
cuando ya hemos terminado de leer el archivo 00:50:19
aquí, vamos a coger el último 00:50:21
número de factura, le sumamos uno 00:50:23
y actualizamos datos en un factura 00:50:25
entonces 00:50:27
el último, para sacar 00:50:28
el último, no tenemos la clave de lul 00:50:33
no, pero vas actualizando con cada uno 00:50:35
como ya vas a recordarlo 00:50:37
sí, pero lo que podemos hacer es 00:50:39
sacar 00:50:42
factura, declararlo fuera 00:50:44
la pregunta, ¿cuándo está en orden? 00:50:46
¿se guarda en orden bien? 00:50:47
la última puede salir 00:50:49
a ver, con el orden de iteración del map 00:50:50
recordad que es un trimap 00:50:54
con lo cual el orden de 00:50:55
interacción es el orden del integer 00:50:58
porque la clave es integer 00:51:00
y el integer tiene 00:51:01
un comparable con el orden natural 00:51:04
entonces se va a guardar con el orden de los enteros 00:51:05
Sí, en este caso sí, pero... 00:51:08
Claro, pero es una pregunta que tiene sentido, 00:51:09
porque recordad que las facturas están en un trimap. 00:51:11
¿Eso qué significa? 00:51:13
Que, claro, da igual los puts que yo haga. 00:51:15
Si hago primero el put de 7, luego el put de 5, da igual. 00:51:18
Cuando yo itere, por el map, cuando itere, 00:51:21
el orden de iteración va a ser el orden que marca la clave. 00:51:24
Y la clave tiene que ser comparable, como ya sabemos, 00:51:29
porque es un trimap, e integer lo es, 00:51:32
porque por definición lo es, 00:51:34
y su comparable en particular 00:51:35
sigue el orden natural de los enteros 00:51:37
entonces cuando iteremos por el map 00:51:39
da igual que hayamos guardado primero la factura 7 00:51:42
y luego la 5, que se van a guardar 00:51:44
todas en el fichero por orden 00:51:46
entonces eso nos facilita 00:51:47
el último, porque si no tendríamos que sacar el máximo 00:51:49
podríamos, si no 00:51:52
si esto fuera un haset, con lo cual 00:51:53
no iría por el orden natural 00:51:56
no tiene por qué, haríamos el máximo 00:51:57
no es tan complicado 00:52:00
hacer el máximo de todas las claves 00:52:01
haríamos un algoritmo para sacar el máximo y ya está 00:52:03
pero en este caso lo tenemos muy fácil 00:52:06
porque lo va a guardar por orden de entero 00:52:07
entonces nos vamos a quedar con el último 00:52:09
entonces el último para facilitarnos 00:52:11
la vida, vamos a declarar 00:52:14
factura afuera 00:52:16
y la última factura 00:52:16
leída, la última factura 00:52:22
leída es la última 00:52:23
del fichero, la última 00:52:26
factura leída 00:52:27
como la tengo aquí ya declarada afuera 00:52:28
se guarda dentro del while, entonces ahora ya 00:52:31
podemos poner en datos 00:52:33
punto secuencia 00:52:36
en un factura, pues la 00:52:38
última factura que hemos leído de estas 00:52:40
le sacamos el número 00:52:42
factura y 00:52:43
más uno. 00:52:45
Vale. 00:52:49
¿Qué hago yo aquí poniéndole 00:52:50
entre paréntesis? Así. 00:52:52
¿Vale? Pues ya está, 00:52:59
ya están volcados. Lo que pasa es que no podemos comprobar 00:53:00
si nos los ha volcado o no porque no tenemos hecho el método 00:53:02
consultar. Por lo menos vamos a comprobar 00:53:04
si sale alguna excepción. 00:53:06
Porque hayamos usado algún método mal. 00:53:08
¿Perdón? 00:53:11
A ver, nosotros aquí estamos 00:53:15
leyendo todas las facturas una por una del fichero. 00:53:18
Todas las que hay. 00:53:21
Entonces, en ese fichero se van a ver guardado 00:53:22
por orden de número de factura. 00:53:25
La 1, la 2, la 3, la 4, la 5. 00:53:27
Y, repito, aunque no se hubieran guardado 00:53:30
por número de factura, 00:53:33
porque cuando yo las he metido aquí en mi aplicación 00:53:34
he metido 00:53:36
que no puedo porque se va incrementando 00:53:38
primero la 7, luego he metido la 8 00:53:40
luego la 1, aunque las hubiera metido así 00:53:42
que en mi aplicación no puedo 00:53:44
porque él los va generando solitos 00:53:46
aunque las hubiera metido así 00:53:48
en el map 00:53:49
al ser el map un trimap 00:53:51
eso significa 00:53:54
que las claves se guardan en un triset 00:53:56
eso significa un trimap 00:53:58
que las claves se guardan en un triset 00:54:00
igual que un hash map significa 00:54:02
que las claves se guardan en un hash set 00:54:04
Bueno, pues al guardarse las claves que son numeritos en un triset, significa que da igual en qué orden vaya metiendo yo esas claves. Cuando luego las recorra, va a ver siempre en el orden del comparable de integer y el comparable de integer es por el orden natural. 00:54:06
luego, cuando yo estoy aquí leyendo 00:54:25
las facturas 00:54:28
la primera, la segunda, la tercera 00:54:29
para irlas metiendo 00:54:32
sé que la última que he leído 00:54:33
es la que tiene el último número de factura 00:54:35
es la que tiene el último 00:54:38
porque están todas ahí colocadas y yo voy leyendo 00:54:39
la primera, la segunda, la tercera 00:54:41
las voy metiendo en el map 00:54:43
la última que leí es la que tiene el número de factura más alto 00:54:44
vale, pues la secuencia 00:54:48
entonces la tengo que inicializar 00:54:49
a una unidad superior 00:54:52
al número de factura más alto para que la siguiente 00:54:54
factura 00:54:56
sea la que tenga un número de factura 00:54:57
una medida superior, para que no se repita 00:55:00
claro, vale 00:55:02
pues entonces podemos ejecutar 00:55:04
a ver si hay error de ejecución, pero comprobar 00:55:06
si las ha leído bien es imposible 00:55:08
porque 00:55:09
vale, de hecho 00:55:10
la aplicación, ahora 00:55:15
cuando yo la he arrancado no podemos comprobarlo 00:55:17
me habrá leído 00:55:20
datos, porque yo ya tenía un fichero 00:55:22
me los habrá leído y estarán en la aplicación 00:55:23
pero 00:55:25
no puedo 00:55:27
comprobarlo, vale, vamos a poner otra más 00:55:28
una de 00:55:32
Sevilla, por ejemplo 00:55:33
de 100, a ver si nos 00:55:36
sale errores de ejecución, pero lo hemos hecho mal 00:55:38
particular, la insertamos 00:55:39
vale, vamos a cerrar 00:55:42
me debería haber guardado 00:55:44
las dos que tenía de antes 00:55:46
que las ha volcado 00:55:47
más esta, cuando yo cierre 00:55:48
vamos a ver 00:55:51
en el fichero 00:55:53
facturas.dat 00:55:56
no me da ningún error, está Madrid 00:55:57
Sevilla 00:56:04
o sea, me ha añadido la nueva 00:56:04
a las que ya había 00:56:11
lo que pasa es que verlo aquí es complicado 00:56:12
lo ideal sería 00:56:16
visualizarlo en la aplicación 00:56:17
claro, pero tiene toda la pinta 00:56:20
de que lo estamos haciendo bien. 00:56:22
¿Vale? 00:56:24
Vale. 00:56:27
Pero, ¿qué nos ha faltado aquí? 00:56:31
Nos ha faltado aquí en el evento de insertar factura 00:56:38
que la factura se ponga aquí. 00:56:41
Pero no solo. 00:56:44
Nos ha faltado cuando cargamos las facturas, 00:56:45
deberíamos además de cargarlas y llevarlas al map, 00:56:48
añadirlas al combo box. 00:56:50
Eso nos ha faltado. 00:56:52
Pues vámonos al método de cargar datos que está aquí. 00:56:53
y vamos a añadirlo del combo box 00:56:58
entonces el combo box 00:57:00
vamos, si no está fuera, vamos a sacarlo fuera 00:57:01
para que sea más fácil 00:57:04
no estaba fuera 00:57:05
efectivamente, en la propia que recorremos 00:57:06
efectivamente 00:57:10
vamos a, a la vez que vamos metiéndolas 00:57:11
en el map 00:57:14
el combo box estaba sin parametrizar 00:57:14
pero vamos a 00:57:18
parametrizarlo a entero, para que sea a integer 00:57:19
para que nos dé 00:57:22
en número directamente y no tengamos que 00:57:24
convertir y ya está 00:57:26
entonces el combo box que está declarado aquí arriba 00:57:27
el combo box 00:57:30
vamos a 00:57:32
parametrizarlo a ínteger 00:57:34
para irle metiendo numeritos solamente 00:57:36
y eso 00:57:38
significa que luego cuando lo instancio 00:57:40
por ahí abajo 00:57:42
que lo instancio aquí para que se me quite 00:57:43
el aviso amarillo, le ponemos esto 00:57:46
y ya está 00:57:47
ahora ya al combo box solo le podemos 00:57:49
meter números, solo 00:57:52
y que números le queremos meter, los números de las facturas 00:57:53
que estamos cargando 00:57:56
luego aquí según vamos 00:57:57
era cargar datos 00:58:00
que estaba aquí 00:58:02
ahí 00:58:04
ahí 00:58:06
después de meterlo en el map por ejemplo 00:58:07
pues ya nos vamos al 00:58:12
combo box 00:58:13
y le añadimos 00:58:16
la factura 00:58:20
que acabamos de leer 00:58:24
.getNumFactura 00:58:25
vale, addItem, perdón 00:58:27
addItem 00:58:32
y ya está 00:58:34
¿cómo? 00:58:37
vale, aquí solo me va a dejar meter 00:58:42
un entero, que es lo que quiero 00:58:45
entonces vamos a ver 00:58:46
vamos a 00:58:48
esto 00:58:49
vamos a abrir la aplicación 00:58:50
algo falla y esto es lo bonito 00:58:53
nullPointerException 00:58:58
No puede 00:58:59
GetNumFactura porque FAT es 00:59:00
Null, vale 00:59:03
¿En qué momento es null? En el momento 00:59:04
El fichero, vamos a empezar con un fichero limpio 00:59:06
A ver qué ocurre 00:59:09
Delete, venga 00:59:11
Vamos a empezar de cero 00:59:14
A ver, insertamos la factura 00:59:18
De Madrid 00:59:21
De 200 00:59:22
En una empresa 00:59:24
Está en el map, se supone 00:59:26
deberíamos haber puesto en el evento este 00:59:29
lo de que aparezca aquí, pero bueno, da igual 00:59:31
y vamos a insertar 00:59:33
una en Sevilla 00:59:35
de 300 00:59:37
de particular 00:59:39
lo que sea, ahora se supone 00:59:41
que hay dos en el map, suponemos 00:59:43
cerramos 00:59:45
vale, en facturas 00:59:46
no sé si ha salido algo rojo aquí 00:59:49
en facturas 00:59:51
00:59:53
refresh 00:59:54
En facturas 00:59:59
tiene pinta de que aquí hay 01:00:00
Madrid, Sevilla. 01:00:03
Vale. 01:00:06
Todo esto es una cabecera que él mete. 01:00:07
Y ahora la lectura 01:00:09
es lo que parece que no la está haciendo bien 01:00:11
porque no acaba de leer el objeto factura. 01:00:12
Algo hemos hecho mal ahí. 01:00:15
Vale, vamos a volver a arrancar la aplicación. 01:00:17
Arrancamos la aplicación 01:00:19
y algo en la lectura 01:00:20
está mal. 01:00:25
Vale. 01:00:26
This combo box is null. 01:00:28
ah no, es en el combo box 01:00:29
porque this combo box 01:00:33
es null, no está instanciado el combo box 01:00:35
no tiene sentido, o sea el null pointer 01:00:36
que me ha salido 01:00:38
antes de que le inicialices estás haciendo lo de rellenar 01:00:39
tienes toda la razón 01:00:42
está inicializado abajo, claro, claro 01:00:46
es que está inicializado abajo 01:00:48
está declarado arriba pero inicializado abajo 01:00:49
vale, entonces 01:00:52
el combo box es null 01:00:53
obviamente como tiene todo el sentido del mundo 01:00:55
y ahora vamos a 01:00:58
el combo box 01:01:00
que está inicializado aquí abajo 01:01:02
pues ya está 01:01:04
esto mismo 01:01:06
lo ponemos 01:01:07
antes de cargar los datos mismo 01:01:10
ala, ahí está 01:01:12
combo box 01:01:15
vamos a volver a arrancar esto 01:01:18
vale 01:01:20
otro null pointer exception 01:01:24
this content pane is null 01:01:26
efectivamente content pan está inicializado 01:01:30
antes, la de garaje lo de cargar datos tenemos que 01:01:32
haberlo puesto abajo del todo, hubiera sido 01:01:34
más fácil, porque ahora vamos a tener que subirlo 01:01:36
todo para arriba 01:01:38
venga, vamos a 01:01:38
esto de aquí directamente 01:01:43
vamos a ponerlo abajo y punto pelota 01:01:45
porque tampoco están 01:01:48
a facturas 01:01:50
venga 01:01:52
ahí abajo 01:01:55
pues porque como lo estamos haciendo sobre la marcha 01:01:57
que os está ocurriendo, que vamos parcheando 01:02:00
y queda una aplicación muy fea 01:02:02
es un ejemplo 01:02:03
en vivo de que no se arranca 01:02:06
a programar sin tener 01:02:08
un diseño claro 01:02:10
es un ejemplo en vivo de que uno cuando arranca a programar 01:02:10
debería tener ya un diseño claro 01:02:14
de lo que quiere hacer, porque si no como vamos 01:02:15
por la marcha, pero 01:02:18
se os está moviendo el cerebro, ¿a que sí? 01:02:19
vamos a ver que dice 01:02:23
que eso es lo que más nos gusta ahora 01:02:24
ver 01:02:25
los errores que nos va dando 01:02:27
Venga, ahora ya 01:02:29
Me sigue saliendo 01:02:31
Que content pan es null 01:02:33
Ah, claro, porque el problema era aquí en el combo box 01:02:35
Claro, es que yo tenía esto que haberlo dejado 01:02:38
Donde estaba, vale 01:02:39
Control X 01:02:41
Lo voy a dejar donde estaba 01:02:42
Que está 01:02:45
Venga, aquí mismo 01:02:47
Vale 01:02:49
Ala, siguiente 01:02:50
Intento 01:02:53
Ya está, vale 01:02:54
Efectivamente ha leído perfectamente 01:02:56
Los dos que tenía 01:02:59
Vamos a ponerle uno más 01:03:00
Que esta es la parte que me ha parecido a mí rara 01:03:02
Vamos a ponerle otra factura más 01:03:05
Que 01:03:06
Ya está, pues venga 01:03:08
Esta factura en Barcelona 01:03:10
De 400, 4000 01:03:13
Empresa, muy cara Barcelona 01:03:16
Insertamos factura 01:03:19
Deberíamos haber añadido aquí lo añade 01:03:20
Pero bueno, da igual, cerramos 01:03:23
El fichero 01:03:24
Antes cuando lo hemos visto 01:03:27
A mí me ha parecido que no 01:03:29
Tenía la información como la tenía que tener 01:03:31
Vamos a ver 01:03:33
Madrid, Sevilla y Barcelona 01:03:34
La tiene como la tiene que tener 01:03:36
Vale, y entonces 01:03:38
Ahora vamos a abrirla, a ver si nos aparece con el 3 01:03:40
Magnífico 01:03:42
Ha creado Barcelona con el 3 01:03:46
Porque al cargarlo ha visto que la última era la 2 01:03:48
La ha incrementado en 1, etc 01:03:50
Genial, nos funciona muy bien 01:03:51
¿Qué nos falta? El evento del combo box 01:03:54
Para que cuando yo seleccione, saque del map 01:03:56
una línea, un get con el map 01:03:58
y poner ahí 01:04:01
y nos falta en insertar factura 01:04:01
en este de aquí 01:04:05
que nos los añada al combo box 01:04:05
¿el qué? 01:04:08
cargar datos 01:04:14
cargar datos, que está ahí 01:04:15
¿qué error te sale? 01:04:17
si es que te sale algún error 01:04:33
Que FAT está a nul 01:04:34
Aquí 01:04:43
Cuando haces esto 01:04:45
Cuando haces eso FAT está a nul 01:04:46
Y tienes FAT declarada afuera 01:04:49
Lógicamente 01:04:53
Y luego esto lo tienes fuera del while 01:04:53
Pues no sé decirte 01:04:55
Habría que verlo efectivamente 01:05:02
Ya lo has visto 01:05:04
¿Qué era? 01:05:06
Ah, vale. 01:05:09
Materias:
Programación
Niveles educativos:
▼ Mostrar / ocultar niveles
  • Formación Profesional
    • Ciclo formativo de grado superior
      • Primer Curso
Subido por:
Raquel G.
Licencia:
Todos los derechos reservados
Visualizaciones:
38
Fecha:
2 de abril de 2025 - 12:29
Visibilidad:
Clave
Centro:
IES ROSA CHACEL
Duración:
1h′ 05′ 20″
Relación de aspecto:
1.78:1
Resolución:
1920x1080 píxeles
Tamaño:
317.00 MBytes

Del mismo autor…

Ver más del mismo autor


EducaMadrid, Plataforma Educativa de la Comunidad de Madrid

Plataforma Educativa EducaMadrid