Mostrando entradas con la etiqueta Java. Mostrar todas las entradas
Mostrando entradas con la etiqueta Java. Mostrar todas las entradas

sábado, 12 de diciembre de 2020

Como crear Ventanas con Ejemplo de Persistencia, grabando datos con Java, usando Oracle Express como base de datos

Como crear Ventanas con Ejemplo de Persistencia, grabando datos con Java, usando Oracle Express como base de datos

En este tutorial se  mostrará como guardar los campos de un formulario de una ventana JFrame,  grabando los mismos en una base de datos Oracle Express.

Mostraré un programa muy sencillo,  sin muchos campos. La ventana tendrá los datos de dos campos y luego un objeto que también se guardará en la base de datos, pero con los datos escritos manualmente. La objetivo es hacer el proceso completo a modo de prueba a ver si todo funciona como se espera.

Para este ejercicio se debe tener instalada la Base de Datos Oracle Express 11g edition. Si no la tienes instalada aqui tienes un enlace para hacerlo, en Ubuntu 16.04 LTS:

Instalar y configurar Oracle Expess 11g R2

Aunque no es estrictamente necesario, pero si una gran ayuda, es aconsejable tener instalado el Oracle SQL Developer. Con vamos a crear la table y los tipo objeto que van a contener los datos que pasemos desde el programa.


Vamos de una vez al código y ponernos a trabajar.

Creamos un proyecto con el nombre que mejor nos parezca. Sino no sabes como hacerlo puedes seguir este enlace



Ya tenemos hechas parcialmente las ventanas que vamos a utilizar, en otro proyecto, y puedes copiar el código desde este enlace:

Crear Ventanas en Java rápida y fácilmente.



Empezaremos accediendo a la base de datos, nosotros vamos a utilizar Oracle SQL Developer. Iniciamos el Developer y una vez dentro pulsamos en SQL como vemos en la imagen y vamos a escribir las sentencias SQL indicadas, en el mismo orden


CREATE OR REPLACE TYPE TIPO_DATOS AS OBJECT
       (
         EMAIL VARCHAR2(30),
         TELEFONO VARCHAR2(12)
      );
 
 
CREATE TABLE AGENDA
     (

       NOMBRE VARCHAR2(30),
       APELLIDOS VARCHAR2(30),
       DATOS TIPO_DATOS
     );




Es obligatorio primero la creación del tipo de  datos como objeto y luego la creación de la tabla. Como podemos ver estamos programando para aprender a como insertar dato de tipo objeto en la base de datos de Oracle.

Ahora estamos en capacidad de hacer la grabación de los datos, pero lo ideal es probar que nuestra base de datos, funciona ejecutando la sentencia SQL que luego vamos a utilizar en el programa.

Evidentemente, hemos hecho eso por adelantado y de aquí que la clase grabarBD, ya tenga una sentencia SQL que funciona, pero la misma fue probada previamente como vamos a verlo en este momento.

Volvemos al Área de trabajo Generador de consultas del Developer y allí probamos la sentencia que deseemos.

Primero vamos acceder a la tabla que recién creamos, la tabla AGENDA



Pulsamos sobre la tabla y esta se abre en una nueva pestaña, y en la división columnas vemos los campos de los que esta compuesto el registro. Vemos que nombre y apellidos tiene un tipo de campo VARCHAR2 y que tiene una longitud de 30 cada uno. Vemos así mismo que un campo llamado DATOS cuyo tipo de campo es TIPO_DATOS, pero no nos dice mas nada.






Para ver que contiene TIPO_DATOS, pues vamos a tipos en la columna izquierda que esta debajo de las tablas



Ya tenemos la tabla y tipo objeto creados, en la base de datos.

Vamos ahora muestro IDE (NetBeans, Eclipse...) a crear una clase imprescindible para la conexión a la base de datos oracle. Debemos recordar que cada base de datos funciona de forma distinta, con lo cual debemos tener cada versión las base de datos en una o varias clases. Lo mas apropiado es usar una sola clase, pero ese depende del estilo de programación que consideremos mas adecuado cada uno.

Con el proyecto creado y código de las ventanas copiado, tendremos algo igual o similar a la siguiente:



Lo mejor es ver que todo funciona, aunque hay algunas cosas que falta por implementar. Eso lo haremos aquí, porque son datos que necesitamos con respecto al ejemplo que vamos a realizar.

Para probar el código nos ubicamos en la clase Inicio y con el botón derecho pulsamos sobre la opción Run File, para correr el programa.


Debemos obtener un resultado igual o similar a lo siguiente:



Si pulsamos sobre registrar debe saltar la siguiente ventana:


Si compruebas veras que los botones Salir y Cancelar no hace nada y que Guardar simplemente lanza un mensaje por consola que te informa de un proceso que se debe realizar de grabación de datos. Este último es el que vamos a implementar.

Ahora si vamos a codificar nuestra clase OracleDB, que no es otra cosa sino la preparación del servidor Oracle para conectarse con nuestro programa en Java.

Para ello vamos a crear un nuevo paquete que llamaremos persistencia, nos ubicamos en la carpeta Source Packages del proyecto, pulsamos botón derecho, seleccionamos New y luego pulsamos sobre la opción Java Package.


Nos abre la siguiente ventana en donde escribimos como nombre del package persistencia y pulsamos sobre Finish.


Luego sobre el nuevo paquete persistencia recién creado que estará de un color gris oscuro, pulsamos nuevamente el botón derecho del ratón, seleccionamos New y luego pulsamos sobre la opción Java Class


Escribimos como nombre de la clase OracleDB y pulsamos Finish.


Se nos abre la siguiente pantalla:



Aquí es donde vamos a escribir el siguiente código, para la clase OracleDB, pero antes de que lo escribamos, quiero señalar que la sentencia import oracle.jdbc.pool.OracleDataSource va a generar un error, que no va a desaparecer sino hasta cuando importemos el driver correspondiente desde Oracle, luego lo veremos, por ahora este es el código a escribir:
 

Ahora este código debe estar generando un error o mas errores si estás utilizando un IDE (NetBeans,Eclipse...) que sea capaz de detectar errores y deficiencias en el código escrito de JAVA. La razón como dije antes es la falta de la librería correspondiente al driver de Oracle. Tu código debe tener un aspecto igual o similar a las dos siguientes:

El punto rojo en la linea del import, señala el error y si pulsamos sobre el con el ratón no indica nada, al contrario de lo que sucede con este otro tipo de error que al pulsar sobre el si indica como solucionar el error:
 

Pero cuidado, este ultimo error está relacionado con el primero. Aquí debemos saber de antemano que todas las base de datos poseen un driver propietario y el cual es el recomendado de descargar y luego instalar en el paquete Librerías del proyecto. Vamos a ver cómo se hace.

En nuestro caso escribimos en Google: driver oracle express, que es la base de datos que estamos utilizando y pulsamos sobre la versión de Oracle que estemos utilizando. En este caso la base de datos que tenemos instalada es la 11g, que es la primera opción que nos da el buscador, así que pulsamos sobre esa opción.

Google nos debería mostrar una página igual o similar a la siguiente. Con el tiempo esto puede cambiar, lo cual aquí lo que aplica es el sentido común. De momento al día de hoy 02 de abril del 2017, lo que sigue es parte lo que se muestra en la página:


En ella como vemos tenemos que aceptar el License Agreement y luego pulsar sobre el driver ojdbc6.jar como indican las flechas.

Lo anterior provoca que la web pida que se valide el usuario que va a descargar el driver, así que pedirá que se le indique el nombre del usuario inscrito en Oracle y la contraseña. Si no tienes cuenta en Oracle debes inscribirte.

Una vez validado el usuario saltará la siguiente pantalla que pide donde descargar el driver o simplemente se iniciara la descarga que normalmente será descargada en la carpeta de Descargas del sistema operativo sea Windows o Linux.



Una vez descargado el driver procedemos a instalarlo en nuestro proyecto y para ello  vamos al IDE (NetBeans, Eclipse...), nos ubicamos con el ratón sobre Libraries como indica la imagen y pulsamos el botón del derecho del mismo. Esto abre el menú contextual y cual vamos a escoger la opción Add JAR/Folder pulsando sobre ella con el ratón.


Vemos aquí en la imagen cuando se añade el driver, como desaparecen los errores, antes indicados.


Ahora podemos explicar un poco mejor que es lo que hace el método conectarDB(),  que hemos escrito hasta ahora para entender un poco el porque es tan importante.

OracleDataSource es una clase que está definida en la librería que se descarga desde Oracle y dentro de esa clase está todo el código necesario para que Java se pueda conectar a la base de datos de Oracle, y lo único que necesita para funcionar es que le suministremos algunos datos, para poder ubicar el servidor de la base de datos y conectarse al servidor. Los datos necesarios son la URL, el usuario y la contraseña, que ya debemos tener previamente porque ya debe estar instalado el servidor Oracle y tener una base definida con un usuario y una contraseña.

Al crear el objeto ods, podemos utilizar los métodos set necesarios para insertar estos datos en el objeto que son básicamente setURL, setUser y setPassword.

El URL es importante ya que indica donde esta instalado el servidor y en que puerto. Veamos su estructura:

"jdbc:oracle:thin:@//127.0.0.1:"+1521+"/"+"xe" 


La parte jdbc:oracle:thin:@// es siempre la misma, no va ha cambiar.

La siguiente parte es simplemente la ip del PC donde está instalado el servidor. Vemos aqui 127.0.0.1 porque es la ip por defecto el servidor y significa que está instalado en el mismo equipo donde está JAVA instalado.

La siguiente parte es el número de puerto asignado al servidor, que en nuestro caso es el utilizado por defecto por Oracle al instalarlo. Si cambias este número al instalar el servidor Oracle Express, deberas usar ese número en lugar del 1521.

Por ultimo, la parte final es el espacio de nombres en donde se trabajara la base datos. En Oracle Express si utiliza por defecto "xe".


Si quieres ver los métodos que tiene la clase, escribe el objeto y luego un punto y esperas.

Ejemplo ods. y la ayuda del IDE (NetBeans, Eclipse), mostrará todos los métodos que puedes utilizar de la clase.
 

Continuemos ahora con la siguiente clase que ya nos mete en materia, o sea, grabar en la base de datos.

Vamos a crear la clase grabarBD, para ello vamos al paquete persistencia y volvemos a pulsar el botón derecho del ratón sobre el mismo, y cuando aparezca el menú contextual, ponemos el puntero del ratón sobre New, y luego seleccionamos la opción Java Class y pulsamos sobre ella:


Se abre un a ventana en la cual escribimos grabarBD en la casilla Class Name y pulsamos sobre el botón Finish




Se nos abre una pestaña en el área de trabajo del IDE (NetBeans, Eclipse..) con el nombre de la clase, como la siguiente:



Ahora escribimos el siguiente código dentro en la clase:



Aquí básicamente importamos las librerías PreparedStatement y SQLException. PreparedStatement es la clase que combinada con la nuestra Clase OracleDB mediante el objeto db (que inicia la conexión con la base de datos) se creará el objeto ps mostrado en el código y que va a contener la sentencia sql,  a la cual va añadir los valores de los campos utilizando los métodos los métodos set según el tipo de datos del campo, que formaran el registro que va ser insertado luego en la base de datos.

La ejecución de la inserción se logra mediante el método ps.executeUpdate. Luego tenemos la clausula finally en el try catch, para cerrar el objeto ps  mediante ps.close() y db.cerrarDB() que cierra la conexión con la base de datos.


SQLException, maneja los errores de excepción que pueda generar el SQL.

Ya con esto estamos listos para añadir a nuestro código que crean las ventanas, aquellas sentencias necesarias para poder guardar los datos que contengan sus formularios.

Como sabemos nuestras ventanas son muy modestas, porque en la realidad solo la ventana del Modulo Registros tiene un formulario y apenas hemos programado en ella dos campos.

Pero la idea es programar por partes, lo cual hace mas fácil de manejar y controlar que todo vaya funcionando como se espera e ir completando todo el proceso, de tal manera de probar todos los pasos hasta el final, para luego complicar el código con mas campos.

cual es el objetivo? Muy sencillo, hacer todo el camino que van a seguir los datos desde que se inicia el programa con el menú hasta que se pulsa el botón grabar y cerrar luego el programa.

Vamos a ver como para entender mejor lo que buscamos hacer.

Ahora pongamos la atención en el código de la ventana Registro. Si vamos hasta el final del código, veremos algo similar a lo siguiente:



Como vemos, el método que captura el momento en que se pulsa sobre el botón Guardar, ejecuta la sentencia que lanza un mensaje a la consola y luego simplemente se cierra la ventana de Registro y se devuelve el control a la ventana Menu.

Pues justamente aquí vamos a insertar el siguiente código:

 
             OracleDB conn=new OracleDB();
         
            if(conn!=null){
          
                System.out.println("Base datos conectada "+conn);
                String dat1=txtNombres.getText();
                String dat2=txtApellidos.getText();
                String dat3="correo@email.com";
                String dat4="+34912680071";
              
                if(grabarBD.grabandoBD(dat1,dat2,dat3,dat4)){
              
                    System.out.println("\nGrabación echa ok");
                 }
          
            }


Lo escribimos y nuestra sección debe quedar similar a la siguiente (la zona azul simplemente se resaltó para diferenciar lo que se agregó):


Si nos fijamos, tenemos que estamos guardando los datos de los campos del formulario txtNombres y txtApellidos, pero que adicionalmente hemos añadido nos datos más adicionales y que hemos escrito el contenido como String.

Estos lo hacemos porque vamos a probar adicionalmente que nuestra sentencia SQL que vamos a enviar a la base de datos funciona.

Evidentemente, es prácticamente obligatorio probar antes cualquier en el Servidor de la base de datos, ya sea con el Oracle SQL Developer (por algo se llama así), así como a modo de practica vayamos al SQL Developer y escribamos la sentencia:


insert into AGENDA values('Perico','DelosPalotes', TIPO_DATOS('perico@enterprise.com','+34658457890'));



Para comprobar los datos pasados, vamos a la tabla AGENDA y luego pulsamos sobre datos y luego refrescar, para que nos muestre lo que se grabó.


Nótese que TIPO_DATOS, no muestra su contenido. Eso lo solucionamos pulsando dos veces botón derecho del ratón sobre el campo y inmediatamente nos salta una ventana y el campo también muestra algo de la data que contiene.


Vemos en la ventana como el campo esta representado como objeto, es decir, el nombre del objeto y entre paréntesis, los atributos separados por comas. Fíjese así mismo como el campo muestra parcialmente el ultimo datos y al lado esta un lápiz simbolizando que esta en modo de edición. Si estiramos el campo hacia la derecha veremos como entonce aparece la data completa en el campo y entonces para que salte el ventana tendremos que pulsar sobre el lápiz.


Ahora vamos a ver la sentencia SQL que en realidad hemos escrito, para pasar los datos desde JAVA.


Vemos que los datos han sido sustituidos por interrogantes.La explicación para mi es muy sencilla, los tipos de datos son manejados internamente de forma diferente por JAVA y por Oracle. Hay que recordar que para JAVA el tipo de datos String es en realidad tratado como un objeto y no una cadenas de caracteres como lo hacen otros lenguajes.

Si tratamos de usar directamente el dato en lugar de usar los interrogantes, la ejecución de la sentencia por medio de ps.executeUpdate(), se produce un error de excepción. Esto lo podemos probar si así lo deseamos.

Eso explica el porque existe la clase PreparedStatement, ya que con su objeto ps vamos añadiendo los datos pasados, en un orden especifico que coincide con el orden en nuestra base de datos y que ademas debe de usar el tipo correspondiente para hacer la transformación que sea necesaria.

En el ejemplo, solo usamos el tipo de dato String y Object, pero podemos escribir ps.(recordar que es el objeto creado) y veremos muchas mas como vemos en la siguiente imagen:

Vemos que tenemos métodos para tipos de datos Double, Date, Float, Int entre otros que también los maneja JAVA, además de unos especiales de Oracle.

También vemos que los datos que corresponden a un objeto definido en la base datos, estos deben ser indicados entre paréntesis, indicando de esta forma que esos datos forman parte del objeto.

Ahora es tiempo de correr el programa y probarlo para ver que sucede. Vamos a la clase inicio y pulsamos dentro del cuerpo de la clase el botón derecho del ratón y en el menú contextual pulsamos Run File.


Aparece la ventana Menu, pulsamos sobre la única opción Registrar

Y aparece la ventana de Registro. Aquí vamos a rellenar el formulario con nombre y apellidos que deseemos y luego pulsamos en Guardar.


Veremos como volvemos a la ventana Menu y que por consola el programas nos lanza los mensajes.


Ahora, si abrimos el  SQL Developer y vamos a la tabla AGENDA y ver los datos veremos lo siguiente:


Vemos como se ha añadió correctamente el registro que acabamos de hacer desde nuestro programa. Evidentemente la parte TIPO_DATOS tendrá los mismos datos que vimos antes, ya que no hemos cambiado nada.

Se sigues probando el programa notarás que solo algunos botones funcionan y otros no. Como se dijo al principio el programa no está ni mucho menos terminado.

Podemos decir que tenemos un prototipo y que ha superado la pruebas que le hemos hecho en su función principal, que es operar entre ventanas, rellenar un formulario y grabar datos en una base de datos Oracle.

Ahora podemos completar algunas cosas para que el programa funcione mas coherentemente, como es que todos los botones hagan algo y añadir nuevos campos y inclusive.

Pero eso es tema otro tutorial, el cual los trataremos en un enlace que se colocara aquí.

Si alguien tiene alguna duda, pregunta, etc... sobre lo que hemos visto hasta este momento, por favor, escriba el mismo en un comentario.



Como siempre si detectas algún error u omisión, o hacer una observación importante, por favor deja un comentario, para corregir, cambiar los conceptos que sean necesarios. Muchas Gracias por visitar mi blog.

sábado, 5 de diciembre de 2020

Como Declarar, inicializar y el manejo de Arreglos en java

Declarar, inicializar y manejo de Arreglos en java desde 0

Para entender bien que es Declaración, Inicialización y manejo de arreglos (arrays), primero tenemos que entender bien a que llamamos arreglo (array).

Tenemos que tener claro que en programación las variables definen un tipo de dato que contienen y un valor que es el contenido real de esa Como declarar-inicializar y manejo de arreglos en Javavariable.

Según el lenguaje de programación utilizado, el tipo de dato de la variable debe ser explicito o implícito. O sea, debe ser indicado (explicito) o pueder ser sobre entendido implícito.

En java, el tipo de dato es obligatoriamente explicito, en todos los casos a excepción de cierto tipo de variables llamadas colecciones, que en realidad variables de tipo objeto.

Y un objeto es un tipo de dato que a su vez posee datos de diferentes tipos, por lo que por favor no confundas, esto con un array normal, ya que en este caso los datos dentro de un objeto no son un array sino que son finitos y bien definidos igualmente como cualquier otra variable.

En programación los arreglos (arrays) no son mas que una forma especial de variable. Solo que en lugar de contener un solo valor, pueden albergar cierta cantidad de valores diferentes, de un mismo tipo de dato y con el mismo nombre de variable, pero un subíndice numérico distinto.

Digamos que un arreglo es una variable tipo arreglo cuya diferencia con una variable normal es que este tipo de variable comparte el mismo nombre y por lo general, y en java es estrictamente así, el mismo tipo de dato con otras variables del mismo nombre con la diferencia de que contiene un subíndice numérico entre paréntesis o corchetes que los diferencia unos de conjunto que tiene el mismo nombre.

Una variable normal seria, por ejemplo, la palabra dato.

Pero un arreglo seria dato[] o dato(), esto nos indica sin lugar a dudas de que estamos hablando de un array o arreglo de datos



Para entenderlo mejor pensemos en una variable normal, en la cual no tenemos que definir ningún número extra de casilleros, ya solo tiene un casillero y por tanto solo puede contener un solo valor.

Por ejemplo una variable para el nombre de una persona. Pues la variable valida y que nos indica a que dato nos referimos seria "nombre"

nombre ---- un casillero llamado "nombre" y dentro el valor "pepe" // variable tipo alfanumerico en java.

OJO, no olvides esta linea anterior, porque volverás a aquí de nuevo mas adelante a verificar la misma.

Ahora definiremos una variable para la edad. Pensaríamos en darle ese mismo nombre pero podemos escribir el que deseemos, siempre que conozcamos a que se refiere, y en este caso podemos poner numero
 
numero ---- un casillero llamado "numero" y dentro "13"    //  variable númerica en el caso de java

No porque la variable se llame nombre es alfabética, o sea solo letras.
Como tampoco numero indique que es numérica y acepta solo dígitos.

Este tipo de datos lo define el lenguaje que programación que utilicemos y en java debemos indicarlos explícitamente.

En Java es obligatorio declara el tipo de variable y su nombre, y esto es dificil de olvidar porque inmediatamente indica error si estas utilizando un IDE.

IDE (Integrated Development Environment) es el nombre dado a  los programas de Entorno de Desarrollo Integrados, que ayudan al programador a programar sus aplicaciones de forma mas amigable, indicándole en cada sentencia que escribe las mayoría de errores de sintaxis que se comenten a escribir programas.

Ahora, no nos distraigamos con otra cosa y sigamos estudiando lo de los arrays o arreglos

En un arreglo, tendríamos que usar un elemento de identificación del conjunto de casilleros que vamos a usar, que sería el nombre y le añadiremos unos corchetes"[ ]". Aunque existen lenguajes que usan los paréntesis"( )",en Java se usan los corchetes"[ ]".

Como se dijo antes esta variable tipo arreglo puede tener varios valores y no solo uno. Por lo tanto tendremos que buscar la cantidad de casilleros que necesitemos en función de la cantidad de valores numéricos o alfabéticos que vamos a guardar, según el tipo de datos que hubiéramos definido antes, sean estos alfabéticos o numéricos.

Supongamos por ejemplo que serán 4 los valores que pondremos y que los mismos serán alfabéticos.

Todos los casilleros tendrán el mismo nombre, pero además tendrán un número que los identifica individualmente, desde "0" hasta "3"

nombre[0] ---- "pepe";
nombre[1] ---- "ana";
nombre[2] ---- "nico";
nombre[3] ---- "eva";
 
Gráficamente tenemos esto:

Como declarar-inicializar y manejo de Arreglos en Java

Con el gráfico vemos que en una variable sin subíndice, no hay forma de poner sino un solo valor pepe, ana, nico o eva. En el ejemplo se puso pepe y no ha sido arbitrariamente.

Si volvemos atrás, vemos que hemos seguido una secuencia de un programa, y a la variable nombre en el renglón que definimos antes del OJO mas arriba marcado,  le habiamos asignamos el valor "pepe".

Que te dice esto?

Que la varialbe nombre sin subíndice es totalmente diferente a un arreglo llamado nombre[] o nombre() el cual deberá tener subíndices numéricos

Con lo visto llegamos a la conclusión, que básicamente la diferencia entre una variable normal y un arreglo, es que este ultimo maneja más valores bajo un mismo nombre con un subíndice, que representa un casillero para cada valor del array(arreglo) y que son diferentes a un variable del mismo nombre pero sin subíndice.

Las otras diferencias ya tiene que ver mas con el lenguaje que se utilice para manejar los arreglos, y uno de ellos es con que numero empiezan a identificar los casilleros.

Java los identifica desde "0", lo que significa que el primer elemento de un arreglo en Java será el casillero con el numero "0".

Vamos a ver un ejemplo de un arreglo donde en lugar de nombres tendrá números.

Como Declarar-incializar y el manejo de Arreglos en Java
            numero[0] = 1;
            numero[1] = 2;
            numero[2] = 3;
            numero[3] = 4;



Si hasta ahora no se tiene claro que es un arreglo, pues hay que volver atrás y volver a leer hasta que se comprenda.

La razón es porque de aquí en adelante vamos a referirnos a como manejar los arreglos con el lenguaje Java.

Debemos saber que en Java los arreglos son finitos. Es decir, tienen un número definido de casilleros y una vez definido ya no se pueden añadir mas casillas.

Para preparar un arreglo en Java debemos primero declarar el arreglo, definir su tamaño (cuantos casilleros tendrá) y luego inicializarlo escribiendo en los casilleros el contenido de cada uno de ellos, incluyendo un valor vacío o null. 

Declarando un arreglo

Las formas de declarar arreglos en Java sería así:

// dos formas de declarar un arreglo (array) en Java
String[] nombre;   //tipo String

 
String nombre[];

int[] numero;    //tipo entero


int numero[];

Java es un lenguaje fuertemente tipado, lo que exige que toda variable, incluídos los arreglos (arrays) tengan un tipo definido de dato, al momento de declararse.

Hay una forma de declarar, asignar el tamaño, e inicializar un arreglo, en una sola sentencia, pero tenemos que tener los datos ya conocidos. Es la siguiente:

String[] nombre={"pepe","ana","nico","eva"};

Lo anterior, define el tamaño de cuatro casilleros del arreglo y coloca en cada casillero los strings "pepe","ana","nico","eva" en el siguiente orden 0 para "pepe", 1 para "ana", 2 para "nico" y 3 para "eva":

nombre[0] para "pepe" 
nombre[1] para "ana" 
nombre[2] para "nico" 
nombre[3] para "eva"


Cuando no tenemos los datos conocidos, lo que si debemos tener claro es cuantos casilleros necesitaremos, y como mínimo no quedarnos cortos, porque no importa que nos sobren uno o dos casilleros que queden vacíos, ya que el programa no se detendrá por eso, pero lo contrario si va darnos problemas.

Asignar el tamaño de un arreglo:

Tenemos las siguientes formas de asignar (crear) cuantos casilleros vamos a tener en un arreglo:

Previamente habiendo declarado el arreglo:

nombre = new String[4];  // Asigna cuatro casilleros de tipo string

numero = new int[10]; // Asigna diez casilleros de tipo int (entero)

Al momento de declarar el arreglo, podemos asignar el tamaño:

String[] nombre = new String[4];

int[] numero = new int[10]; 

La tercera forma vimos anteriormente y es la que engloba todo el proceso, declarar, asignar o definir el tamaño y añadir datos (contenido), en una sola sentencia, y vamos a repetir aquí de nuevo:

String[] nombre = {"pedro","pablo","vilma","betty"};

Añadiendo contenido a un arreglo

La forma de añadir contenido en un arreglo es igual a como se hace con cualquier variable:

nombre arreglo[numero-casillero] = valor a ser asignado

La parte tediosa de esto es que luego tenemos que ir asignando el valor correspondiente de cada casillero uno a uno, o sea, que para el arreglo nombre[] sería así:

nombre[0] = "pepe"; nombre[1] = "ana";
nombre[2] = "nico";
nombre[3] = "eva";

Otro forma es retomar los ejemplos que hemos dado anteriormente aquí , en donde la asignación del valor se hace a la hora de declarar el arreglo

Vamos a recordarlo otra vez:

String[] valores = {"10","20","30","40"};

Con lo anterior nos ahorramos unas cuantas lineas, y eso adecuado para cuando el arreglo que necesitemos, tenga una cantidad reducida de valores y que los mismos no cambien cambien su valor en el tiempo.

Pero que pasa si tenemos que añadir cien nombres? Ya no parece tan buena la sentencia anterior. Para esos casos ya tendríamos que pensar en un archivo que tenga guardado los nombres y luego utilizar un bucle for o while para recorrerlo e ir asignando uno a uno os valores al arreglo.

Vamos a ver un ejemplo pero no con un arreglo del tipo String, sino un arreglo del tipo int, con un bucle for.

Recordar, que hemos hecho antes la declaración y definición del tamaño del arreglo que llamaremos numeros.

int[] numeros=new numeros[100];

Ahora para asignar los valores del 1 al 100 usamos el bucle for.

Como declarar-inicializar y manejo de arreglos en Java




Obtendremos una lista de números como la que sigue:

numeros[0] = 1
numeros[1] = 2
numeros[2] = 3
numeros[3] = 4
numeros[4] = 5
.....
.....
.....
.....
numeros[96] = 97
numeros[97] = 98
numeros[98] = 99
numeros[99] = 100



Como siempre si detectas algún error u omisión, o hacer una observación importante, por favor deja un comentario, para corregir, cambiar los conceptos que sean necesarios. Muchas Gracias por visitar mi blog.

jueves, 3 de diciembre de 2020

Como Mejorar y completar el prototipo de Ventanas JFRAME Java con persistencia

Como Mejorar y completar el prototipo de Ventanas JFRAME Java con persistencia 

Este tutorial es una continuación de dos anteriores, relacionados con la creación de ventanas JFrame sencillas y rápidamente, metiendo directamente la mano en el código sin wizard (ayudantes de diseño).

Si has llegado aquí sin haber visto lo anterior,  seria conveniente que por lo menos se le diera un vistazo a estos dos siguientes enlaces.

Crear Ventana JAVA JFrame sin layout manualmente


Ventanas JFrame Java con ejemplo de persistencia usando base de Datos Oracle Express

Mejorando y completando el prototipo

Aquí vamos añadir funcionalidad algunos botones mas de las ventanas, que actualmente no hacen nada y añadiremos otro botón a modo de ejemplo. También vamos añadir una o mas funcionalidades según lo requiera el caso

Vamos a empezar por la ventana Menú. El botón Registrar funciona, y abre una ventana, pero el botón Salir no hace nada.
 

Vamos a la parte del código donde están el método que controla estas acciones. Este método es de obligado definición al implementar la interface ActionListener, la cual establece que el método actionPerformed va capturar los eventos de pulsado o click del ratón sobre cualquier elemento en la ventana. Es decir que cada vez que pulsemos sobre algún elemento dentro de la ventana este método se ejecutará y buscará entre las opciones if que definamos, si algúno de ellos coincide y entonces ejecutará la instrucciones que estén declaradas en el cuerpo del if.

Vemos como para el botón btnRegistro está definido y tiene las acciones a seguir en caso de ser pulsado. Vemos además que no hay ningún botón adicional definido.



Ahora vamos a darle funcionalidad el botón Salir, y para ello tenemos que hacer dos cosas, una de ellas es escribir en el método actionPerformed() la acción a realizar cuando sea pulsado el botón Salir y la otra es añadir el evento ActionListener al botón salir.

Vamos a realizar entonces inclusión las siguientes sentencias dentro del método actionPerformed().

if  (e.getSource().equals(btnSalir)){
                System.out.println("Estoy dentro de Salir");
          this.dispose();
 }

Lo anterior simplemente libera la memoria del equipo y termina el programa. También escribe por consola el mensaje de que esta dentro del cuerpo del if que ha determinado que efectivamente el botón pulsado ha sido Salir. Nuestro código quedaría así:




Ahora vamos añadir el evento ActionListener al botón Salir, que fue definido en el método componentes().

Veamos primero como está el método componentes sin hacerle la modificación necesaria:
 

Como sugieren las flechas, falta poner la sentencia:

btnSalir.addActionListener(this);

Escribimos la sentencia quedando el código así:


Ahora vamos a probar el código y vamos a la clase Inicio a ejecutarlo. Debes obtener el menú que luego de pulsar sobre Salir debe quedar igual o similar a la imagen siguiente:

Hemos comprobado que ya tiene funcionalidad el botón Salir y que además es correcto su funcionamiento, cierra la ventana y termina la ejecución del programa.

Ya con lo visto estamos en capacidad de añadir mas botones al menú y asociarles funcionalidad.

Podemos dar más funcionalidad al menú con el objeto de ayudar al usuario a realizar sus tareas, como por ejemplo cuando un botón reciba el foco, o sea, que el cursor del ratón se coloque encima, se active un mensaje que describa la acción que ejecuta.

Vamos hacerlo paso a paso, primero implementamos la interface MouseListener en la clase Menu:


Al añadirlo notamos que el IDE (NetBeans, Eclipse...), marca un error y si pulsamos con el ratón encima del mismo nos salta un pequeño rectángulo dando dos opciones a seguir, y de entre las cuales vamos a escoger Add import..., lo cual añade la librería necesaria.


Vemos que a pesar de que hemos importado la librería, sigue marcando un error y pulsando sobre el mismo vemos que hay dos opciones de solución. Como la interface MouseListener tiene métodos abstractos, estos deben definirse o marcar la clase como abstracta. Por supuesto, escogemos implements all abstract methods y pulsamos sobre esa opción. Veremos como los métodos son añadidos que justo en este caso lo hace debajo de los métodos que capturan los eventos ActionListener.

Como vemos el MouseListener, tiene mas métodos que ActionListener pero nosotros vamos a utilizar solamente dos para los que nos hemos planteado. Debemos saber además que está acción de incorporar los métodos, ha provocado que el IDE (NetBeans, Eclipse...), importara además la librería de eventos correspondiente, si vemos nuestra clase de nuevo al principio veremos:


Estos detalles se nos escapan cuando somos novatos, que no se nos escaparían tan fácilmente, si usamos un editor de texto sin ayuda de ningún tipo, ya que simplemente tendríamos que conocer de antemano todos estos detalles e ir compilando y mirando los errores e interpretarlos. Editores como NetBeans, Eclipse, VS Code y otros son una gran ayuda a la hora de escribir código JAVA, pero también hay ocasiones en donde debemos mirar muy bien que es lo que escogemos porque en ocasiones las alternativas son menos obvias y puede que no sea tan fácil interpretar que debemos escoger.

Vamos a dar a ahora el siguiente paso, que es definir la etiqueta que contendrá el mensaje que deseemos según sea el botón sobre el cual se posa el puntero del ratón. Añadimos la etiqueta labelMensaje:


A continuación tendremos que establecer en que lugar del código del menú queremos definir los datos que daremos a la etiqueta, vamos al método componentes(), y escribimos en el lugar elegido:


Hemos escrito al definición de la etiqueta justo encima de la definición del botón salir, creamos el objeto labelMensaje con new JLabel(), le especificamos en que lugar del menú va a salir el mensaje setBounds(x, y, ancho, alto), donde  x=distancia del borde izquierdo al principio del mensaje 40, y= distancia del borde superior del menú al cuerpo del mensaje, ancho del mensaje y altura de la fuente. Finalmente con add(), añadimos la etiqueta al JFrame.

Una vez que hemos escrito el código en el método componente, ya estamos preparados para mostrar los mensajes dependiendo sobre que botón pase el puntero del ratón.

Vamos entonces a programar dos métodos de los implementados por la interface MouseListener, mouseEntered() y mouseExited(). Empezamos por el método que captura el evento de pasar el puntero del razón sobre el botón, que es mouseEntered y luego seguimos con mouseExited.

En el método mouseEntered este será el código:

public void mouseEntered(MouseEvent e) {
    if(e.getSource().equals(btnRegistro)){
       
        labelMensaje.setText("Para insertar un nuevo registro en la tabla  agenda");
        labelMensaje.setVisible(true);
        }  
    }

En el método mouseExited este será el código:

public void mouseExited(MouseEvent e) {
         if(e.getSource().equals(btnRegistro)){
       
            labelMensaje.setText("");
            labelMensaje.setVisible(false);
        }      
    }



Si corremos el programa veremos como al pasar el puntero del ratón sobre el botón Registrar, se escribe el mensaje sobre el botón Salir.

Podemos apreciar que nuestro mensaje esta cortado. Este lo podemos corregir, ampliando el ancho en setBounds, pero vemos también que quedaría muy justo, así que habrá que ajustar también el eje X. Eso se lo dejamos de tarea para que se vayamos probando y acostumbrando a las medidas que deben usarse.

Vamos ahora a eliminar o comentar las sentencias, que se encuentran en los metodos que ha sido añadidos por las interfases:

throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.

Que tienen los métodos, ya que esto lo que hace es enviar un error, que no vamos a manejar y no viene al caos cuando el método no se utiliza.

En nuestro caso vamos a eliminarlos y así limpiamos el código.

Ahora rápidamente vamos a mostrar como añadir un botón más. Copiamos el botón registrar así, marcamos todo el bloque btnRegistro y una vez marcado pulsamos el botón derecho sobre el área resaltada y pulsamos sobre la opción Copy:


Ahora simplemente hacemos espacio entre el bloque btnRegistro y el bloque labelMensaje, de tal forma de dejar un espacio de tres lineas y nos colocamos en el medio pulsamos el botón derecho del ratón y luego pulsamos en la opción Paste:



Quedando algo igual o similar a lo siguiente:

Ahora simplemente lo que tenemos que hacer es cambiar el nombre del botón. Vamos a usar el siguiente btnModificar. Una vez hecho esto es lo que debe quedarnos:


Vemos como se muestran errores en todas la lineas y estos son debido a que todavía no hemos declarado btnModificar como una variable del tipo JButton. Es decir estamos tratando de instanciar el objeto btnModificar antes de declararlo. Pues justo lo que hace falta entonces es declararlo y ya tendremos nuestro botón. Vamos entonces al lugar donde estamos declarando estos botones y lo añadimos simplemente y vemos como desaparecen los errores:


Pero cuidado!!
El método setBounds() de los dos botones tiene los mismos valores, lo cual no puede ser ya que se solapan. Además el valor del método setText es el mismo también. Vamos a cambiar el setBounds simplemente escribiendo 80 en los que sería el eje Y, o sea setBounds(120, 80, 150, 20) y cambiamos el setText por setText("Modificar"), lo cual debe quedar así:


Si ahora corremos el programa, veremos algo como lo siguiente:


Como podemos apreciar de aquí en adelante todo es prácticamente un copiar y pegar y luego modificar y adaptar a la nueva situación. Eso quiere decir que estamos en capacidad de modificar tamaños, contenidos y funcionalidades. Sabemos ademas que uno de los objetivos que era grabar en una base de datos, funciona. Lo que queda es ir creciendo de forma paulatina y controlada.

Evidentemente nos vemos siempre en la necesidad de buscar soluciones para cuestiones específicas, ya que no es lo mismo insertar un nuevo registro que modificarlo. Modificar un registro se vuelve algo mucho mas complejo ya que hay que leer previamente el registro, luego mostrarlo en las casillas correspondientes del formulario, luego esperar que algo sea modificado o no y luego finalmente volver a grabar el registro con la nueva modificación.

Ahora vamos a ver que podemos mejorar en la clase Registro, que es la ventana que muestra un formulario de inserción de registros. Vamos a ver que tenemos en la ventana Registro:


Si pulsamos el botón Cancelar veremos que el mismo no funciona, cuando lo normal es que cierre la ventana y no grabe nada. De paso debemos indicar que existe un error lógico al momento de Guardar y es que si dejamos en blanco el formulario el mismo puede ser grabado, lo cual no tiene sentido.

Vamos a darle funcionalidad al botón Cancelar. Vamos a la clase Registro y los dirigimos al método actionPerformed(), que como ya debemos saber captura los eventos del pulsado del ratón asociado a un elemento tipo botón y vamos a añadir el código sombreado en azul.


Ahora vamos al método componentes() y buscamos donde está definido el botón btnCancelar, y verificamos que existe la sentencia btnCancelar.addActionListener(this), para generar el evento, si no existe la añadimos.


Ahora probamos lo que hemos hecho corriendo el programa y veremos que funciona, porque cierra el formulario y retorna a la ventana Menu. Fácil, no?

Si analizamos el código utilizado la acción que ejecuta el programa al pulsar Cancelar en la ventana Registro se limita a dos lineas, pero si observamos el btnGuardar vemos que hemos hecho un truco, con el único objeto de probar que el programa efectivamente podía guardar sin problemas datos. Hemos definido dentro de la ejecución la asignación de valores a dos campos que deberían obtener sus datos desde un formulario y de la lectura de un objeto.

Vemos como se va complicando el código y eso que apenas estamos tratando solo uno. Vamos a suponer que los datos se deben obtener del formulario, para los cual tendremos que crear dos nuevas casillas y sus etiquetas identificadoras, para el usuario pueda escribir los datos. Vamos a realizarlo y para ello vamos el método componentes() de nuevo.

Copiamos todo el bloque que conforma la casilla Apellidos tanto el txt como el label, y duplicamos dos veces, para luego modificarlos y cambiar las partes correspondiente para que uno sea el campo email y el otro sea el campo telefono que son los campos que reciben los datos en la base de datos.



Vemos claramente que hemos repetido por dos veces el código y hemos puesto comentarios para indicar que vamos a cambiarlo, después de lo cual, debe quedarnos algo similar a lo siguiente:


Ya sabemos por qué se generan errores y es debido a que debemos declarar las variables que referencian a los objetos email y telefono y eso debemos hacerlo al comienzo de la clase como vemos aquí:


Y con esto comprobaremos que los errores han desaparecido, pero aún debemos modificarlos que que tiene valores que no les corresponden, como por ejemplo nombres en el método setText y coordenadas ancho y alto en setBounds. Estaremos un rato cuadrando las nuevas casillas y cambiando los nombres del setText, pero al final debemos tener algo similar a lo siguiente en lo resaltado azul:


Evidentemente que hemos ido probando el código con cada modificación, para ir corrigiendo los errores e imprecisiones luego de lo cual no de quedar algo similar a lo siguiente:

Una vez que estemos satisfechos con el aspecto que deseemos darle, pasaremos ahora a que los campos nuevos agregados sean grabados en la base de datos. Esto lo hacemos ubicándonos en el método actionPerformed(), y dentro del if que captura el botón btnGuardar y localizando las variables que deben recibir los valores de las casillas que acabamos de agregar


Una vez que hagamos el cambio el código deber ser igual al siguiente:


Con esto ya tenemos todo correcto. Observemos que no hemos tenido que ir a la clase que graba los datos, simplemente hicimos el cambio aquí, con lo cual no debe haber problemas a la hora de grabar.

Vamos a probar ahora el programa, rellenando todos los campos y pulsamos sobre Guardar:

 Y vemos que el programa no lanza errores y nos muestra el mensaje de que la Grabación fue efectuada correctamente.


Solo nos queda comprobar en el Servidor Oracle Express para comprobar que los datos escritos en los campos fueron grabados en la tabla correctamente. Vamos acceder a la base de datos y vamos a observar el contenido de la tabla AGENDA.


Podemos comprobar que todo ha sido añadido correctamente.

Vamos hacer ahora otras dos mejoras más que nos ayuden a evitar que se guarden registros vacíos, ya que tal como esta el programa y como se configuró la base de datos, los registros nulos son aceptados sin limitación.

Hay evitar que se guarden los datos de los campos en blanco (algunos campos si pueden ir en blanco y simplemente se eliminan de ser comprobados), y podemos comprobarlo a la hora de pulsar el botón Guardar comprobando cada uno de los campos que se quieran comprobar y asegurarse que los campos obligados tengan datos.

Vamos a establecer que todos los campos menos el campo telefono, deben contener datos. Es decir, el único campo permitido que puede estar vacío a la ahora de guardar los datos en el campo telefono

Ademas vamos hacer la comprobación para que todos los elementos o botones que generen el evento actionPerformed(), que es le evento que se activa al pulsar el botón del ratón, tengan acceso a la misma al guardar el resultado en una variable boolean, que llamaremos vacio.

Vamos a ver el código que hay que añadir en el método actionPerformed(), y en el if que captura si el botón guardar fue pulsado, que es el siguiente:



Vemos  que se han añadido la declaracion boolean de la variable vacio y de una vez se le asigna un valor, que es retornado por el método .isEmpty() asociado al campo txtNombre.getText(). Aquí debemos recordar que el valor retornado por getText(), es un String y que JAVA  considera String un objeto. Si queremos comprobar esto solo tenemso que esbribir en el NetBeans lo siguiente:                 "     ".isEmpty(); y veremos como no lo marca como un error. De hecho todo en JAVA es un objeto.

Luego vemos que hacemos una comparación |= que significa (or igual), o sea que asignará a la variable vacio el resultado de comparar lógicamente el valor que tenga vacio con el valor que retorne el metodo .isEmpty(), el cual será true (verdadero) si el campo esta en blanco(vacío) y mantendrá ese valor mientras exista uno o más campos vacíos. Cuando todo los campos sometidos a evaluación tengan un valor, la variable vacio será igual a false (falso).

Luego dentro del cuerpo del if que evalúa si el botón que ha sido pulsado es Guardar, vemos que hemos escrito otro if que evalúa si la variable vacio, pero negándola, es decir que si la variable tiene un valor true el signo ! lo cambia a false y entonces NO se ejecutará el código contenido en el cuerpo del if. Luego se añade un else que será ejecutado en caso contrario. Dentro del cuerpo de este else se escribe un código para generar una ventana de mensaje al usuario, indicandole que hay campo obligatorios vacíos, no guardar nada y devuelve el control a la ventana Registro y continúa el programa.


Con estas simples modificaciones hemos agregado un control de campos que no deseamos que estén en blanco(vacíos) a la hora de guardar el regsitro.

Lo ideal ahora sería hacer la modificación del botón Cancelar, pero en ese caso para que se le advierta al usuario que ha pulsado Cancelar pero que hay campos con datos, pero lo dejaremos como tarea.

Ahora vamos añadir una ayuda visual al lector para indicarle que campos no pueden estar vacíos. Vamos a ver como.


Añadimos FocusListener en implements como vemos aquí abajo, y pulsamos sobre el error para importar la librería correspondiente.

Luego veremos que sigue mostrándose un error y pulsando otra vez sobre el error vemos que tenemos que definir métodos abstractos de la interface. Pulsamos sobre la opción y los métodos serán añadidos al final de la clase


Aquí vemos los métodos añadidos, llamados focusGained() y focusLost() que básicamente significan ganar y perder el foco respectivamente


Para el propósito de detectar si la casilla a quedado vacía, vamos hacer uso del método focusLost(). El funcionamiento se ejecuta cuando el usuario sale de la casilla, en ese momento se dispara el evento focusLost().

Cuando el programa abra la ventana de Registro, marcará con un color rosa, aquellos campos obligatorios de contener datos. Para obtener este comportamiento lo que tenemos que hacer el colorear el background de las casillas que queremos señalar. Así lo hacemos en nuestro código como podemos ver escribiendo el ḿetodo .setBackground(Color.pink); para cada uno de los campos implicados:


Solo cuando el campo tenga algún valor, su background se tornará blanco en cuanto salgamos de esa casilla,  indicando de esta forma que existe un dato. Esto lo debemos manejar en el ḿetodo focusLost(); que es llamado cuando la casilla pierde el foco.

Vamos entonces al método focusLost() de la clase Registro, y vamos añadir el codigo que vemos en la imagen de abajo:


Vamos analizar el primero que es el campo txtNombres, podemos ver que el primer if analiza que si el campo ha obtenido el foco mediante las sentencias e.getSource() concatenada mediante le punto con .equals(txtNombres), al ser verdadero indica que el cursor esta dentro de ese campo y está intentando salir del mismo. 

Es aquí que hacemos la evaluación de si el campo esta blanco o vacío, capturando el texto que tenga el campo mediante el método txtNombres.getText() concatenándolo con el método .isEmpty(), que enviará un verdadero si lo enviado por el getText() está vacío el campo o falso si el campo tiene algún contenido.

Al ser verdadero se vuelve a pintar de rosa el color de fondo de la casilla del campo vacío, indicando que no hay valores en el mismo, lo contrario la casilla tendrá un color de fondo blanco indicando que hay un valor.

Como podemos ver podemos es una forma sencilla de ayudar al usuario a rellanar campos. Podemos además incluir otras funciones, como son validar los valores. Es decir, detectar si el campo debe tener solo números, evitar caracteres especiales, usar Expresiones Regulares, etc.

Dejamos sin verificar el campo txtEmail, para que sea completado por el lector.

En otras entregadas vamos a ir incluyendo algo de los que hemos mencionado, para demostrar que es relativamente sencillo, crear de cero una Ventana JFrame y tener nosotros totalmente el control sobre ella, sin necesidad de usar un wizard

Como siempre si detectas algún error u omisión, o hacer una observación importante, por favor deja un comentario, para corregir, cambiar los conceptos que sean necesarios. Muchas Gracias por visitar mi blog.

Vistas de página en total