Confección de interfaces de usuario con JAVA - SWING

26,278 views

Published on

CONFECCIÓN DE INTERFACES DE USUARIO

JAVA + SWING

Published in: Technology
3 Comments
12 Likes
Statistics
Notes
No Downloads
Views
Total views
26,278
On SlideShare
0
From Embeds
0
Number of Embeds
295
Actions
Shares
0
Downloads
1,128
Comments
3
Likes
12
Embeds 0
No embeds

No notes for slide

Confección de interfaces de usuario con JAVA - SWING

  1. 1. Desarrollo de interfaces: 1.Interfaces de Usuario (Componentes, Eventos, Escuchadores… ) Jose Alberto Benítez Andrades jose@indipro.es www.indipro.es @indiproweb @jabenitez88Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 1
  2. 2. SwingLas interfaces gráficas de usuario (GUI) ofrecen al usuario ventanas,cuadros de diálogo, barras de herramientas, botones, listasdesplegables y muchos otros elementos con los que ya estamos muyacostumbrados a tratar.Las aplicaciones son conducidas por eventos y se desarrollan haciendouso de las clases que para ello nos ofrece la API de Java.La interfaz de usuario es la parte del programa que permite al usuariointeraccionar con él.La API de Java proporciona una biblioteca de clases para el desarrollode Interfaces gráficas de usuario (en realidad son dos). Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 2
  3. 3. SwingLa biblioteca proporciona un conjunto de herramientas para laconstrucción de interfaces gráficas que tienen una apariencia y secomportan de forma semejante en todas las plataformas en las que seejecuten.La estructura básica de la biblioteca gira en torno a componentesycontenedores. Los contenedores contienen componentes ysoncomponentes a su vez, de forma que los eventos pueden tratarse tantoen contenedores como en componentes.La API está constituida por clases, interfaces y derivaciones.AWT ySwing Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 3
  4. 4. Componentes SwingJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 4
  5. 5. Jerarquía de clases para las GUIComponent: superclase de todas las clases de interfaz gráfica.Container: para agrupar componentes.JComponent: superclase de todos los componentes de Swing que sedibujan directamente en los lienzos (canvas).Sus subclases son los elementos básicos de la GUI.JFrame: ventana que no está contenida en otras ventanas.JDialog: cuadro de diálogo.JApplet: subclase de Applet para crear applets tipo Swing.JPanel: contenedor invisible que mantiene componentes de interfaz yque se puede anidar, colocándose en otros paneles o en ventanas.También sirve de lienzo.Graphics: clase abstracta que proporciona contextos gráficosdonde dibujar cadenas de texto, líneas y otras formas sencillas. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 5
  6. 6. Jerarquía de clases para las GUIColor: color de los componentes gráficos.Font: aspecto de los caracteres.FontMetrics: clase abstracta para propiedades de las fuentes.Categorías de clases: Contenedores:  JFrame, JApplet, JWindow, JDialog Componentes intermedios:  JPanel, JScrollPane Componentes:  JLabel, JBbutton, JTextField, JTextArea, ... Clases de soporte:  Graphics, Color, Font, ... Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 6
  7. 7. Jerarquía de clases para las GUI: JComponentJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 7
  8. 8. Jerarquía de clases para las GUI: JComponentJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 8
  9. 9. Jerarquía de componentes Graphics (java.awt) Component (funcionalidad básica de componentes gráficos) Button, Canvas, CheckBox, Choice, Label, List, ScrollBar TextComponent TextField, TextArea Container (permite agrupar, añadir y eliminar componentes) (también definir diseño o disposición (layout managers)) ScrollPane Panel Applet (java.applet) JApplet (javax.swing) Window Frame JFrame (javax.swing) Dialog FileDialog JDialog (javax.swing) JWindow (javax.swing) JComponent (javax.swing)Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 9
  10. 10. Contenedores Contenedores de alto nivel: JFrame Habitualmente la clase JFrame se emplea para crear la ventana principal de una aplicación en Swing. JDialog Ventanas de interacción con el usuario. Contenedores intermedios: JPanel Agrupa a otros componentes. JScrollPanel Incluye barras de desplazamiento.Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 10
  11. 11. ContenedoresJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 11
  12. 12. Jerarquía Contenedor alto-nivel JFrame Content Menu Bar Pane JLabelJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 12
  13. 13. JerarquíaJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 13
  14. 14. JerarquíaJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 14
  15. 15. Añadir elementosModo 1:1. Obtenemos el panel de contenido del frame: Container panel = this.getContentPane();2. Añadimos componentes a dicho panel: panel.add(unComponente);Modo 2:A partir de 1.5 también se puede hacer directamente sobre elJframe add(unComponente); Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 15
  16. 16. 1. Con herencia de JFrame utilizando ContainerJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 16
  17. 17. 2. Con herencia de JFrame sin ContainerJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 17
  18. 18. 3. Ejemplo sin herencia con ContainerJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 18
  19. 19. 4. Ejemplo sin herencia sin ContainerJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 19
  20. 20. Administradores de disposiciónLos componentes se agregan al contenedor con el método add().JButton unBoton = new JButton("Texto del botón");panel.add(unBoton);El efecto de add() depende del esquema de colocación o disposición (layout) del contenedor que se use.Existen diversos esquemas de disposición: FlowLayout, BorderLayout, GridLayout, ...Los objetos contenedores se apoyan en objetos LayoutManager (administradores de disposición).Clases más usadas que implementa la interfaz LayoutManager:FlowLayout: un componente tras otro de izquierda a derecha.BorderLayout: 5 regiones en el contenedor (North, South, ...).GridLayout: contenedor en filas y columnas. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 20
  21. 21. Administradores de disposiciónPara organizar el contenedor se utiliza el método setLayout():public void setLayout(LayoutManager mgr)setLayout(new BorderLayout());setLayout(new FlowLayout());setLayout(new GridLayout(3,4));El layout manager elige la mejor posición y tamaño de cada componente deacuerdo al espacio disponible. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 21
  22. 22. Administradores de disposiciónBorderLayout organiza el FlowLayout coloca los componentes de izquierda a derecha y de arriba haciacontenedor en 5 zonas: abajo: Para distribuciones más complejas podemos insertar paneles (JPanel) en los contenedores y obtener el tamaño de un componente con el método getSize(). Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 22
  23. 23. FlowLayoutJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 23
  24. 24. BorderLayoutJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 24
  25. 25. GridLayoutsetLayout(new GridLayout(filas, columnas))Crea una zona de filas x columnas componentes y éstos se van acomodando de izquierda a derecha y dearriba a abajo.GridLayout tiene otro constructor que permite establecer la separación (en pixels) ente loscomponentes, que es cero con el primer constructor.Así, por ejemplo:new GridLayout(3, 4, 2, 2)crea una organización de 3 filas y 4 columnas donde los componentes quedan a dos pixels deseparación.Ejemplo:setLayout(new GridLayout(3, 4, 2, 2);for(int i = 0; i < 3 * 4; i++) { add(new JButton(Integer.toString(i + 1)));} Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 25
  26. 26. GridLayoutJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 26
  27. 27. Paneles como contenedoresLos paneles actúan como pequeños contenedores para agruparcomponentes. Colocamos los componentes en paneles y lospaneles en el frame o incluso en otros paneles. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 27
  28. 28. Paneles como contenedoresJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 28
  29. 29. Paneles como contenedoresJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 29
  30. 30. Dibujo de gráficos en panelesJPanel se puede usar para dibujar.Para dibujar en un panel se crea una clase derivada de Jpanel y se redefine elmétodo paintComponent() que le indica al panel como dibujar.La clase Graphics es una clase abstracta para todos los contextos gráficos.Una vez obtenido el contexto gráfico podemos llamar desde esteobjeto a las funciones gráficas definidas en la clase Graphics.Graphics contiene información acerca de la zona que necesita ser redibujada:el objeto donde dibujar, un origen de traslación, el color actual, la fuenteactual, etcétera. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 30
  31. 31. Ejemplo de dibujoJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 31
  32. 32. Ejemplo de dibujoCuando utilizamos el método paintComponent() para dibujar en un contextográfico g, ese contexto es un ejemplar de una subclase concreta de la claseGraphics para la plataforma específica.El método paintComponent() es llamado la primera vez y cada vez que esnecesario redibujar el componente.Al hacer super.paintComponent(g) nos aseguramos de que el área visualizadase limpia antes de volver a dibujar. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 32
  33. 33. Ejemplo de dibujo  Creación de un color RGBJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 33
  34. 34. Algunos métodos de GraphicsJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 34
  35. 35. Interacción con el usuarioAl interactuar con la aplicación, el usuario: Acciona componentes (ActionEvent).  El usuario pulsa un botón.  El usuario termina de introducir un texto en un campo y presiona Intro.  El usuario selecciona un elemento de una lista pulsando el preferido (o de un menú).  Pulsa o suelta botones del ratón (MouseEvent). Minimiza, cierra o manipula una ventana (WindowEvent). Escribe con el teclado (KeyEvent). Descubre porciones de ventanas (PaintEvent) Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 35
  36. 36. Interacción con el usuarioCuando el usuario de un programa o applet mueve el ratón, presionaun pulsador o pulsa una tecla, genera un evento (actionEvent).Los eventos son objetos de ciertas clases. Normalmente un objeto dealguna subclase de EventObject que indica: El elemento que accionó el usuario. La identificación del evento que indica la naturaleza del evento. La posición del ratón en el momento de la interacción. Teclas adicionales pulsadas por el usuario, como la tecla Control, la tecla de Cambio a mayúsculas, etcétera. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 36
  37. 37. Acciones del usuarioJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 37
  38. 38. Modelo para responder a eventosCreamos un manejador de eventos en dos pasos:• ƒDefinimos una clase específica que haga de oyente de eventos y que implemente el método actionPerformed().• Registramos un ejemplar como oyente de componentes: Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 38
  39. 39. Modelo para responder a eventosSe añade el oyente especificado (ejemplar de MiOyente) a la lista deoyentes para recibir eventos de acción (ActionEvent) desde esecomponente. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 39
  40. 40. Ejemplo: botón con pitidoJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 40
  41. 41. Ejemplo: reproducir un valorJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 41
  42. 42. Ejemplo: reproducir un valorJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 42
  43. 43. Ejemplo: contador de pulsacionesJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 43
  44. 44. Ejemplo: cambio de colorJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 44
  45. 45. Ejemplo: cambio de colorJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 45
  46. 46. ActionEventEl objeto ActionEvent ofrece un método getActionCommand()que devuelve un objeto con la información sobre el origen delevento (el botón en nuestro caso).Con un botón, devuelve la etiqueta del botón.Para identificar botones individuales: Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 46
  47. 47. ActionEventEl método getSource() indica el objeto en el que se haoriginado el evento: Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 47
  48. 48. Un conversor Euros-PesetasJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 48
  49. 49. Un conversor Euros-Pesetas La clase OyenteBoton es interna y tiene acceso a los elementos de la clase ContenedoraJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 49
  50. 50. Interfaces para procesar eventosPara facilitar la tarea del programador se han creado una serie de interfacesque deben implementarse cuando se quieren procesar algunos de estoseventos. Algunas interfaces y sus métodos son: Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 50
  51. 51. Interfaces para procesar eventos• JButton: Botón aislado. Puede pulsarse, pero su estado no cambia• „JToggleButton : Botón seleccionable. Cuando se pulsa el botón, su estado pasa a seleccionado, hasta que se pulsa de nuevo (entonces se deselecciona) o „isSelected() permite chequear su estado• „JCheckBox : Especialización de JToggleButton que implementa una casilla de verificación. Botón con estado interno, que cambia de apariencia de forma adecuada según si está o no está seleccionado• „JRadioButton: Especialización de JToggleButton que tiene sentido dentro de un mismo grupo de botones (ButtonGroup) que controla que sólamente uno de ellos está seleccionado Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 51
  52. 52. Componentes : JButton• Constructores: JButton(String text) JButton(String text, Icon icon) JButton(Icon icon)• ƒ Respuesta a botones: o Implementar la interfaz ActionListener o Implementar el método actionPerformed(ActionEvent e) Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 52
  53. 53. Ejemplosboton1 = new JButton("A Euros ");boton1.setIcon(new ImageIcon("flag1.gif"));boton2 = new JButton(new ImageIcon("flag2.gif"));boton3 = new JButton("Botón",new ImageIcon("flag8.gif")); Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 53
  54. 54. Componentes : JLabelPara texto, una imagen o ambos:JLabel(String text, int horizontalAlignment)JLabel(String text)JLabel(Icon icon)JLabel(Icon icon, int horizontalAlignment)eti1 = new JLabel("Etiqueta de texto...");eti2 = new JLabel(new ImageIcon("flag8.gif")); Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 54
  55. 55. Componentes : JTextFieldCampos de texto para introducir caracteres:JTextField(int columns)JTextField(String text)JTextField(String text, int columns)JTextField text1 = new JTextField("hola", 10);Poner texto: text1.setText("Adios");Obtener texto: String str = text1.getText();Agregar al Panel: p1.add(text1); Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 55
  56. 56. Componentes : JComboBoxListas de elementos para seleccionar un solo valor:Creación: JComboBox ch1 = new JComboBox();Agregar opciones: ch1.addItem(Object elemento);Registrar Evento: ch1.addItemListener( objeto);Obtener selección: val = ch1.getSelectedIndex(); ch1.getItem()Implementar la interfaz ItemListenerImplementar el método itemStateChanged(ItemEvent e) ch1.addItemListener(new OyenteItem()); . . . class OyenteItem implements ItemListener { public void itemStateChanged(ItemEvent e) { ... } } Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 56
  57. 57. Componentes : JListListas de elementos para seleccionar uno o varios valores:JList l1 = new JList();JList l2 = new JList(Object[] elements);String[] cosas = {"Opción 1", "Opción 2", "Opción 3"};Jlist l2 = new Jlist(cosas);Registrar evento: l2.addListSelectionListener(oyente);Obtener selección:int[] indices = l2.getSelectedIndices(); Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 57
  58. 58. Componentes : JListImplementar la interfaz ListSelectionListennerImplementar el método valueChanged(ListSelectionEvent e) l.addListSelectionListener(new OyenteLista()); ... class OyenteLista implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { int[] indices = l.getSelectedIndices(); int i; for(i = 0; i < indices.length; i++) { ... } } } Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 58
  59. 59. Componentes : JScrollBarCreación:bar1 = new Scrollbar(Scrollbar.HORIZONTAL,0,0,0,100);Registrar evento:bar1.addAdjustmentListener(oyente);Implementar la interfaz AdjustmentListenerImplementar el métodoadjustmentValueChanged(AdjustmentEvent e) bar1.addAdjustmentListener(new OyenteBarra()); ... class OyenteBarra implements AdjustmentListener { public void adjustmentValueChanged(AdjustmentEvent e) { ... } }Obtener valor:int val = bar1.getValue(); // val entre 0 y 100 Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 59
  60. 60. Componentes: JScrollBar y JComboBoxJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 60
  61. 61. Componentes: JScrollBar y JComboBoxJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 61
  62. 62. Componentes: JScrollBar y JComboBoxJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 62
  63. 63. Movimientos de ratónJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 63
  64. 64. Pulsaciones de ratónJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 64
  65. 65. Ejemplo de cuadro de mensajeJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 65
  66. 66. Ejemplo de cuadro de opcionesJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 66
  67. 67. Ejemplo de cuadro de entrada de datosJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 67
  68. 68. Ejemplo de cuadro de entrada de datosJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 68
  69. 69. MenúsJava ofrece varias clases para poner menús en una ventana:JMenuBarJMenuJMenuItemJCheckBoxMenuItemJRadioButtonMenuItemUn JFrame o JApplet puede guardar un barra de menú donde se cuelgan menúsdesplegables.Los menús tienen elementos de menú que puede seleccionar el usuario.Las barras de menús se pueden contemplar como una estructura que soporta menús. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 69
  70. 70. MenúsUna ventana (frame) sólo puede tener una barra de menús(objeto MenuBar), que se sitúa en la parte de arriba del mismo.Los submenús son botones JMenu.Los elementos de los menús son botones JMenuItem.Cuando se activa un menú se despliegan automáticamente lasopciones del menú. Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 70
  71. 71. MenúsJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 71
  72. 72. Ejemplo de menúJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 72
  73. 73. Ejemplo de menúJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 73
  74. 74. Ejemplo de menúJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 74
  75. 75. Otro ejemploAplicación que permite realizar operaciones aritméticas.La interfaz contiene etiquetas y campos de texto para losoperandos y el resultado. La operación se selecciona en el menú: Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 75
  76. 76. Otro ejemploJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 76
  77. 77. Otro ejemploJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 77
  78. 78. Otro ejemploJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 78
  79. 79. Otro ejemploJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 79
  80. 80. Clases adaptadoras¡ Poco eficiente, sólo implementamos un método ! Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 80
  81. 81. Clases adaptadorasJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 81
  82. 82. Clases adaptadoras• Si por ejemplo una de nuestras clases implementa la interfaz WindowListener, deberá implementar todos los métodos sociados, aún cuando sólo utilicemos uno de ellos.• „Las clases adaptadoras se encargan de implementar todos los métodos del la clase de escucha. Así sólo necesitaremos redefinir aquellos métodos que nos van a ser útiles para gestionar eventos , sin preocuparnos del resto.• Para ello dedemos indicar que nuestra clase es una subclase del adaptador: class UnaClase extends Adaptador{ ... } Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 82
  83. 83. Clases adaptadorasclass MiAdaptador extends WindowAdapter { public void windowClosing(windowEvent e) { System.exit(0); }}. . .this.addWindowListener(new MiAdaptador());. . . Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 83
  84. 84. Clases adaptadorasSólo las clases que poseen más de un método tienen adaptador , y son lassiguientes:ComponentListener posee ComponentAdapterContainerListener posee ContainerAdapterFocusListener posee FocusAdapterKeyListener posee KeyAdapterMouseListener posee MouseAdapterMouseMotionListener posee MouseMotionAdapterWindowListener posee WindowAdapter Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 84
  85. 85. EjemploJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 85
  86. 86. Arquitectura MVC (Modelo-Vista-Controlador)La arquitectura MVC es una arquitectura típica de diseño de GUI. El modelo representa la estructura lógica de la GUI, independientemente de su representación visual. La vista constituye la representación visual de la GUI. El controlador constituye la lógica de interacción con el usuario.El mejor modelo separa en las tres partes:public static void main(String args[]) { Modelo modelo = new Modelo(); Controlador controlador = new Controlador(modelo); GUI gui = new GUI(controlador); } Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 86
  87. 87. Applet mínimo con Swing (JApplet)Jose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 87
  88. 88. Esquema de applet con swingJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 88
  89. 89. EjemploJose Alberto Benítez Andrades– jose@indipro.es - @jabenitez88 89

×