20250401 SerializarObjetos_EjemploFacturas - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
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
sí
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
Is
00:13:41
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
j
00:15:43
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
si
00:16:34
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
sí
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
y
00:19:21
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
Si
00:22:12
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
o
00:24:00
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
no
00:29:36
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
Y
00:30:28
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
En
00:33:06
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
A
00:33:22
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
y
00:34:26
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
Sí
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
tú
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
sí
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
Y
01:04:42
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