Prog GUI

De MediaWiki
Saltar a: navegación, buscar

Introducción

  • Los lenguajes de programación se fueron adaptando a las nuevas funcionalidades hardware de los fabricantes (monitores con más resoluciones y colores, CPU más potentes, tarjetas gráficas con mayores capacidades) permitiendo la utilización de nuevos recursos gráficos, dejando en un segundo plano los programas tipo 'consola', en la que la relación entre el programa y el usuario se hacía mediante texto.
  • Aparecieron sistemas operativos nuevos (como Windows o IOS) que disponía de una interface gráfica en el que la relación entre la máquina y el usuario se basaba en el uso de elementos gráficos, como ventanas, cajas de texto, botones,...una forma mucho más 'amigable' que el uso de programas de consola, facilitando mucho su uso. Los programas que se desarrollaron a partir de entonces, incluían este tipo de recursos.
  • El conjunto de elementos gráficos que permiten relacionar al usuario con un programa informático es lo que se conoce como Interface Gráfica de Usuario (en inglés Graphical User Interface o GUI).


  • En este tipo de programas, a diferencia de los de consola, la programación está basada en eventos.
En un programa de consola, el usuario elegía una de las opciones disponibles que mostraba el programa pulsando una tecla. Después aparecerían las opciones disponibles dentro de la elegida. Y así sucesivamente.
En un programa gráfico, con GUI, el usuario dispone de componentes sobre los que puede provocar eventos. Por ejemplo, al pulsar un botón, al pasar el ratón por encima de una etiqueta, al pulsa sobre un elemento de la lista.
Lo que hace el programador es 'registrar' tipos de eventos sobre los diferentes elementos gráficos, de tal forma que el S.O. cuando 'captura' un evento, lo va a enviar a aquellos componentes gráficos que puedan atender el tipo de evento capturado.



Librerías de Java GUI

  • En Java, las librerías que proporcionan los elementos gráficos que conforman la interface gráfica de usuario se encuentra en dos librerías:
Ambas forman parte de Java Foundation Classes que es un framework (conjunto de librerías que nos proporcionan recursos para ser utilizados de una forma 'común' en el desarrollo de aplicaciones, en este caso, de aplicaciones gráficas).
Prog gui 1.png


  • Lo que ofrece JFC:
  • Soporte de diferentes aspectos y comportamientos.
Ofrece a cualquier componente Swing una amplia selección de aspectos y comportamientos.
Por ejemplo, el mismo programa puede usar el Aspecto y Comportamiento Java (conocido como Metal), el Aspecto y Comportamiento Windows o el Aspecto y Comportamiento Unix (Motif).
Podéis consultar en este enlace varios ejemplos de aspectos diferentes.
  • API de Accesibilidad
Permite el uso de tecnologías como lectores de pantalla y display Braille para obtener información desde el interface de usuario.
  • Java 2D API (sólo JDK 1.2 )
Permite a los desarrolladores incorporar fácilmente gráficos 2D de alta calidad, texto, e imágenes en aplicaciones y applets Java.
  • Soporte de Drag and Drop (sólo JDK 1.2)
Proporciona la capacidad de arrastrar y soltar entre aplicaciones Java y aplicaciones nativas (del propio sistema operativo).



AWT

  • Podéis consultar en este enlace todos los componentes que conforman la librería AWT.
  • Los componentes gráficos que utilizan la librería AWT tienen las siguientes características:
  • Para dibujarse utilizan llamadas directamente a la API del S.O.
Esto lleva consigo que cuando dibujamos una ventana, esta tendrá el aspecto que el resto de ventanas del S.O. Por lo que si una misma aplicación la llevamos a dos ordenadores con dos sistemas operativos diferentes, tendrá cada una el aspecto propio de cada S.O.
  • Cada componente gráfico crea 'su propia ventana' para dibujarse por lo que el gasto en recursos es mayor. Es por esto que se les denomina componentes de peso pesado.


  • Algunos de los elementos son contenedores que contienen componentes gráficos u otros contenedores. Los eventos pueden producirse sobre un contenedor o sobre un componente.


  • Al depender fuertemente de los componentes nativos del sistema operativo el programador AWT estaba confinado a un mínimo denominador común entre ellos. Es decir que sólo se disponen en AWT de las funcionalidades comunes en todos los sistemas operativos. Por ejemplo, un S.O. podría ofrecer botones con imágenes en su interior, pero otro no, por lo que dicha funcionalidad no podría ofrecerse.
  • El comportamiento de los controles varía mucho de sistema a sistema y se vuelve muy difícil construir aplicaciones portables. Es decir, la forma de responder a determinados eventos puede ser diferente entre S.O. distintos.


Prog gui 2.jpg
Imagen obtenida de los apuntes de Jose Luis Comesaña



Swing

  • A diferencia de AWT, Swing utiliza AWT para crear una ventana del S.O. y después, sobre ella, se encarga de 'pintar' todos los componentes gráficos que se encuentran dentro de la misma así como de responder a los eventos.


  • Las clases Swing están escritas enteramente en Java, y esto permite que Swing sea 100% portable y que se pueda especificar una apariencia a los componentes gráficos y que esta se mantenga en todos los S.O.
  • Además el consumo de recursos es menor comparado con AWT donde cada componente requería su propia ventana creada a partir de una llamada a la API del sistema operativo.
Por eso a los componente Swing se les conoce como componentes de peso ligero.


  • Los nombres de los componentes Swing son los mismos que el de los componentes AWT anteponiendo la letra J. Por ejemplo: JButton, JCheckBox,...


  • A pesar de que los componentes Swing derivan de AWT y por tanto se podrían construir aplicaciones combinando ambos tipos, esto no se recomienda.
Prog gui 3.png
Imagen obtenida de este enlace


  • Para identificar de forma precisa cada componente gráfico vamos a añadirle un 'prefijo' a su nombre.
Podéis consultar la lista de prefijos en este enlace.
Después del prefijo irá el nombre del control, cada palabra empezará con una letra mayúscula.


  • Podemos ver gráficamente como son cada uno de los controles:
Prog gui 4.jpg


  • Disponéis en este enlace de una guía para aprender a utilizar los componentes Swing.


Creación de interfaces gráficas con Netbeans

  • La información que se facilita en este punto es un complemento al trabajo realizado en clase por los alumnos.
En este caso, la información está adaptada al ciclo de Desarrollo de Aplicaciones Web, en el que el tiempo asignado a esta parte es reducido, por lo que voy a indicar sólo los aspectos más importantes del uso de las interfaces gráficas.
No es un manual 'completo' para el desarrollo de aplicaciones gráficas.



Layouts

  • Los layouts son la forma en como se distribuyen los componentes gráficos dentro de un contenedor.
Lista de layouts disponibles en Java.
En NetBeans podemos acceder a ellos pulsando el botón derecho sobre un contenedor.
Prog gui 5.jpg


JFrame/JDialog

  • En Java disponemos de varias clases que representan diferentes tipos de ventanas y con las que podemos 'construír' aplicaciones diferentes.
Podéis consultar, por curiosidad:
  • En este enlace algunas de las clases disponibles.
  • En este otro como crear una aplicación MDI.
  • En este otro otra explicación de las aplicaciones MDI.


  • En nuestro caso vamos a identificar la clase JFrame como una ventana que va a representar una aplicación.
Por lo tanto vamos a tener una única JFrame y sobre ella crearemos un menú. Al pulsar los diferentes elementos de menú abriremos otras ventanas, concretamente haremos uso de la clase JDialog.


  • Para abrir un JDialog desde el JFrame, dentro del código del evento que queramos gestionar pondremos el siguiente código:
  1. DlgAlumnoAlta dlgAltaAlumno = new DlgAlumnoAlta(this,false);
  2. dlgAltaAlumno.setVisible(true);
  • Línea 1: DlgAlumnoAlta es como se llama la clase que gráficamente habremos creado anteriormente del tipo JDialog. El segundo parámetro del constructor indica si la ventana va a ser modal o no.
  • Línea 2: Una vez creado el objeto debemos llamar al método setVisble para que la visualice.


  • Si queremos cerrar un JDialog, dentro del código que gestiona el evento salir debemos escribir:
  1. dispose();



Menús

  • Para añadir un menú a una ventana debemos de arrastrar un control Barra de menú.
Al incorporarlo a una JFrame aparecen por defecto dos menús.
  • Una barra de menú está formada por Menús y dentro de cada uno de los menús elementos de menú que suelen ser los que el usuario escoge como opción.
Un menú puede contener otros menús en su interior.
Prog gui 6.jpg
Componentes gráficos para añadr un menú


En el siguiente ejemplo podemos ver como hemos añadido un menú a un JFrame, formado por dos menús (Alumnos/Salir) y dentro del menú Alumnos hemos añadido 4 elementos de menú.

Prog gui 7.jpg


  • Para gestionar los eventos debemos presionar el botón derecho del ratón sobre el elemento de menú y escoger la opción eventos.
En el caso de los elementos de menú el evento sería dentro de la categoría Action el método actionPerformed:
Prog gui 8.jpg


En el caso de un menú (por ejemplo el menú Salir), podríamos capturar el evento MousePressed dentro de la categoría Mouse.



Tablas

  • En Java la clase que representa el componente gráfico de una tabla es la clase JTable.
  • En NetBeans tenemos que arrastrar el componente gráfico.
Veremos que entre sus propiedades podemos establecer el modelo (Model).
El concepto de modelo es aplicable tanto a listas (JList), combos (JComboBox) como tablas (JTable).
  • En el caso de las tablas, en el modelo es donde se van a definir que número de columnas va a tener la tabla, número de filas y contenido.
Es decir, por programación no vamos a añadir contenido a la tabla, lo que vamos a hacer es obtener el modelo de la tabla y sobre dicho modelo vamos a añadir datos.


  • El método para obtener el modelo de una tabla es: nombreObjetoTabla.getModel(). Esto devuelve un objeto de la clase TableModel que es una interface donde se encuentra definidos métodos y propiedades 'comunes' a todos los modelos.
Podríamos definir nuestro propio modelo creando una clase que implemente dicha interface, pero también podemos hacer uso de unos modelos ya creados en Java que nos van a proporcionar la funcionalidad que necesitamos para añadir filas al modelo, borrar datos, aumentar el número de filas.
Uno de ellos es la clase DefaultTableModel.
Cuando queramos modificar el contenido del modelo tendremos que poner una orden como esta: DefaultTableModel dtModel = (DefaultTableModel)nombreObjetoTable.getModel();
Ahora podremos acceder a los métodos y propiedades de dicho modelo entre los que se encuentran:


  • Si quisiéramos asociar un modelo nuevo a una tabla lo podemos hacer por programación llamando al método setModel(TableModel).


  • En el ejemplo se puede ver como al pulsar la propiedad Model del objeto JTable, gráficamente podemos establecer el número de filas inicial así como el número de columnas:
Prog gui 10.jpg


Prog gui 9.jpg
  • Un ejemplo de código en el que se añaden filas a una tabla:
Partimos que disponemos de un array de objetos de una clase Alumno formada por dos atributos (nombre / edad). Dicho array es un atributo de clase definido en la clase Alumnos.
  1.     private void cargarAlumnos(){
  2.        
  3.         DefaultTableModel tm = (DefaultTableModel)tblAlumnos.getModel();
  4.        
  5.         //tm.setNumRows(0);   //Podríamos establecer por programación el número de filas. Esto borraría todas.
  6.         String[]datosFila = new String[2];
  7.  
  8.         for(int cont=0; cont < Alumnos.alumnos.length();cont++){
  9.             Alumno alumno = Alumnos.alumnos[cont];
  10.             datosFila[0] = alumno.getNombre();
  11.             datosFila[1] = String.valueOf(alumno.getEdad());
  12.             tm.addRow(datosFila);
  13.         }
  14.     }


ComboBox

  • En Java la clase que representa el componente gráfico (de tipo Swing) de una combo es la clase JComboBox.
  • En NetBeans tenemos que arrastrar el componente gráfico.
Veremos que entre sus propiedades podemos establecer el modelo (Model).
El concepto de modelo es aplicable tanto a listas (JList), combos (JComboBox) como tablas (JTable).


  • En el caso de los combo, podemos utilizar una clase Model de Java que implementa la interface ComboxModel. Dicha clases es la clase DefaultComboBoxModel.
Recordar que a través del modelo vamos a añadir e eliminar elementos del mismo.
  • Métodos que podremos utilizar de la clase ComboBox:
  • Métodos que podremos utilizar del modelo DefaultComboBoxModel:



  • Por defecto, el modelo que asigna Java a este componente gráfico es un DefaultComboBoxModel, por lo que no tendremos que hacer nada si este modelo nos vale.

Para asignarle un modelo 'concreto' diferente al que asigna por defecto, podremos hacerlo por código o bien gráficamente.

Si lo hiciéramos por código, tendríamos que escribir después de la llamada a initComponents en el constructor del JDialog, lo siguiente:
  1.     public DlgAlumnoBaja(java.awt.Frame parent, boolean modal) {
  2.         super(parent, modal);
  3.         initComponents();
  4.        
  5.         DefaultComboBoxModel dcbModel = new DefaultComboBoxModel();
  6.         cboAlumnos.setModel(dcbModel);
  7.     }
  • Siendo cboAlumnos el nombre de la combo.


Si lo hacemos gráficamente, tendremos que pulsar sobre la propiedad Model como hicimos en la JTable:
Prog gui 11.jpg


En la pantalla que aparece debemos de escoger la opción Código Personal y escribir en la caja de texto: new DefaultComboBoxModel() como se ve en la imagen:
Prog gui 12.jpg



  • A partir de este momento ya podríamos añadir elementos a la combo con el método addElement del modelo asociado.
Pero resulta que el modelo por defecto va a aceptar objetos de la clase String.
Nosotros queremos aprovechar la ventaja de programar con objetos para que acepte (en este ejemplo) objetos de una clase Alumno creada previamente.
Al asignar al modelo elementos que son objetos, lo que va a visualizar la combo va a ser el resultado de llamar al método toString de la clase Alumno (que estará sobrecargado por nosotros y mostrará el nombre junto a la edad).
De esta forma, al recuperar el elemento seleccionado de la lista recuperaremos un objeto de la clase Alumno con todos los atributos del mismo.
Tened en cuenta que para dar de baja a un alumno necesitamos un identificador (puede ser un valor de un atributo).
Si no guardáramos objetos, el valor que podríamos recuperar de la combo sería un texto que no nos serviría para identificar al alumno, si el texto no es su campo identificador.
Tendríamos que utilizar el índice del elemento seleccionado en la combo para ir a nuestro array local en el que tenemos guardados todos los alumnos (y que hemos usado para cargar los alumnos en la combo) y por la posición de la combo, eliminar en esa misma posición el alumno del array.


  • Para indicar que el modelo va a guardar objetos de la clase Alumno tendremos que presionar el botón de Código en las propiedades del ComboBox y cambiar la propiedad Parámetros de tipo por <Alumno> como se ve en la imagen:
Prog gui 13.jpg
  • El código para añadir un objeto al combo sería:
  1.         DefaultComboBoxModel dlModel = (DefaultComboBoxModel)cboAlumnos.getModel();
  2.        
  3.         Alumno alumno = new Alumno("Pepe",33);
  4.        
  5.         dlModel.addElement(alumno);
Si tuviéramos los alumnos en un array tendríamos que recorrer el array e ir añadiendo uno a uno.
Recordar que lo que va a visualizar el ComboBox va a ser lo que devuelva el método 'toString' de la clase Alumno.
  • El código para borrar un objeto del combo sería:
  1.         if (cboAlumnos.getSelectedIndex()==-1){
  2.             JOptionPane.showMessageDialog(this, "Es necesario seleccionar un alumno para darlo de baja!!!");
  3.             return;
  4.         }
  5.        
  6.         Alumno alumno = (Alumno)cboAlumnos.getSelectedItem();
  7.         int resultado = JOptionPane.showConfirmDialog(this, "¿ Estás seguro de dar de baja al alumno " + alumno.getNombre() + "?", "Aviso", JOptionPane.YES_NO_OPTION);
  8.         if (resultado==JOptionPane.YES_OPTION){
  9.             DefaultComboBoxModel dcboModel = (DefaultComboBoxModel)cboAlumnos.getModel();
  10.             dcboModel.removeElement(alumno);
  11.         }
Como vemos primero debemos comprobar que esté algún alumno seleccionado (líneas 1-4).
Después obtenemos el alumno (objeto) seleccionado con la llamado al método 'getSelectedItem()' (línea 6). Podríamos obtenerlo también utilizando la posición del elemento seleccionado.
Por último llamamos al método 'removeElement' pasando el objeto que queremos borrar de la lista (línea 10)
Comentar que en el caso de tener un array de datos de donde el combo carga los mismos, tendremos que actualizarlo y borrar también dicho elemento.
Para buscar el objeto en el array podríamos utilizar el índice del elemento seleccionado y buscar la misma posición en el array o podríamos buscar el objeto completo (dependerá del tipo de array utilizado, tendréis la posibilidad de buscar por un objeto).



Listas

  • En Java la clase que representa el componente gráfico (de tipo Swing) de una lista es la clase JList.
  • En NetBeans tenemos que arrastrar el componente gráfico.
Veremos que entre sus propiedades podemos establecer el modelo (Model).
El concepto de modelo es aplicable tanto a listas (JList), combos (JComboBox) como tablas (JTable).


  • En el caso de las listas, podemos utilizar una clase Model de Java que implementa la interface ListModel. Dicha clases es la clase DefaultListModel.
Recordar que a través del modelo vamos a añadir e eliminar elementos del mismo.
  • Métodos que podremos utilizar de la clase JList:
  • Métodos que podremos utilizar del modelo DefaultListModel:



  • Podemos ver en la siguiente imagen las propiedades de una JList.
Prog gui 14.jpg
Entre ellas podemos ver:
  • SelectionMode: En la que indicamos si vamos a permitir seleccionar un elemento de la lista o un grupo de ellos (de forma continua o aleatoria).
  • model: En la que indicamos el modelo de la lista.


  • Para indicarle el modelo hacemos lo mismo que en los casos anteriores.
  • Si lo hiciéramos por código, tendríamos que escribir después de la llamada a initComponents en el constructor del JDialog, lo siguiente:
  1.     public DlgAlumnoModificar(java.awt.Frame parent, boolean modal) {
  2.         super(parent, modal);
  3.         initComponents();
  4.        
  5.         DefaultListModel dlstModel = new DefaultListModel();
  6.         lstAlumnos.setModel(dlstModel);
  7.     }
  • Siendo lstAlumnos el nombre de la lista.
  • Gráficamente, presionando sobre la propiedad model:
En la pantalla que aparece debemos de escoger la opción Código Personal y escribir en la caja de texto: new DefaultListModel() como se ve en la imagen:
Prog gui 15.jpg


  • A partir de este momento ya podríamos añadir elementos a la lista con el método addElement del modelo asociado.
Pero resulta que el modelo por defecto va a aceptar objetos de la clase String.
Nosotros queremos aprovechar la ventaja de programar con objetos para que acepte (en este ejemplo) objetos de una clase Alumno creada previamente.
Al asignar al modelo elementos que son objetos, lo que va a visualizar la combo va a ser el resultado de llamar al método toString de la clase Alumno (que estará sobrecargado por nosotros y mostrará el nombre junto a la edad).
De esta forma, al recuperar el elemento seleccionado de la lista recuperaremos un objeto de la clase Alumno con todos los atributos del mismo.
Tened en cuenta que para dar de baja a un alumno necesitamos un identificador (puede ser un valor de un atributo).
Si no guardáramos objetos, el valor que podríamos recuperar de la combo sería un texto que no nos serviría para identificar al alumno, si el texto no es su campo identificador.
Tendríamos que utilizar el índice del elemento seleccionado en la combo para ir a nuestro array local en el que tenemos guardados todos los alumnos (y que hemos usado para cargar los alumnos en la combo) y por la posición de la combo, eliminar en esa misma posición el alumno del array.


  • Para indicar que el modelo va a guardar objetos de la clase Alumno tendremos que presionar el botón de Código en las propiedades de la JList y cambiar la propiedad Parámetros de tipo por <Alumno> como se ve en la imagen:
Prog gui 16.jpg



Gestión de eventos

  • En Java se utiliza lo que se llama gestión de eventos delegada.
  • Los eventos los gestionan unas clases 'especiales' denominadas 'oyentes' y que las conforman una serie de Interfaces:
  • ActionListener: Gestiona los eventos de 'click'.
  • MouseListener: Gestiona los eventos del ratón.
  • KeyListener: Gestiona los eventos del teclado.
  • ...


Para poder gestionar los eventos de un tipo vamos a tener una clase que implemente alguna/s de las interfaces anteriores.
Cada interface tiene uno o un conjunto de métodos que serán llamados cuando se produzca el evento.
Así, la interface ActionListener tiene el método actionPerformed que será llamado cuando se produzca el evento de 'click'.
  • El siguiente paso será 'asociar' un objeto de la clase que implementa la interface con algún componente gráfico que 'produzca' ese evento. Es decir, el componente gráfico debe ser una 'fuente de eventos.
En el caso de los botones, la forma de asociarlo es mediante la llamada al método: addActionListener.


  • Disponéis en este enlace de todas las interfaces que gestionan eventos. Si pulsáis sobre la interfaces podéis ver cuales son los métodos que las conforman.



Proyecto Netbeans de muestra

  • En este proyecto se muestra un ejercicio práctico de los recursos gráficos aprendidos anteriormente.
Prog gui 17.jpg


  • Comentar que el mantenimiento de datos va a llevar consigo las siguientes operaciones sobre los mismos: CONSULTA, ALTA, MODIFICACIÓN y BAJA.
En este proyecto se ha creado una pantalla por cada una de las operaciones y si han utilizado componentes gráficos diferentes para mostrar su funcionamiento.
Comentar que esto no tiene por qué ser así, y se puede realizar el mantenimiento con dos pantallas solamente:
  • Una para dar de alta o modificar (sería la misma pantalla, modificando el botón de alta por el de modificar y enviando los datos en el caso de modificación.
  • Una para las restantes operaciones. Se podría implementar con un botón de alta que llamaría a la pantalla anterior y una tabla con todos los datos y asociado a cada fila dos botones, uno para dar de baja y otro para modificar, que llamaría a la pantalla anterior.
Php laravel acceso datos ex1 1.jpg
Ejemplo de pantalla única para el mantenimiento de una tabla de perfumes hecho en PHP con el framework LARAVEL.




Recursos varios

  • En este enlace se explica como podemos crear nuestro propio modelo para una JList y poder añadir y borrar objetos.


-- Ángel D. Fernández González -- (2017).