Está en la página 1de 17

Construccin de interfaces grcos de usuario con Netbeans o a

9 de enero de 2004

Indice
1. Creacin del contenedor de objetos o 2. Adicin de componentes al contenedor o 3. Conguracin de componentes o 4. Construccin de men s o u 5. Modicando el gestor de posicionamiento 6. Copiando objetos 7. Asistente de conexin o 8. El gestor de posicionamiento GridBagLayout 9. A adir manejadores de eventos n 10.Contenedores dentro de contenedores 11.Creacin de un panel para dibujar y gestionar sus eventos o 12.Localizacin de los programas ya terminados o 1 3 5 6 6 7 7 9 11 13 14 17

1.

Creacin del contenedor de objetos o

La creacin del interfaz grco de usuario (GUI) con Netbeans es muy sencilla. Se comienza creando o a un contenedor mediante una determinada plantilla, y luego se arrastran a l, los componentes visuales, e ajustndoles las propiedades que se necesiten. a Vamos a crear un GUI simple. El GUI concatenar los strings de dos campos de texto y luego mosa trar el resultado en un tercer campo de texto. a Ejecuta el entorno Netbeans, abre un directorio de trabajo, y crea un paquete para el programa que vamos a crear: 1. 2. 3. Ejecuta el IDE. Pincha en la solapa GUI Editing de la ventana principal para cambiar al modo GUI. Decide qu directorio quieres usar para colocar el cdigo fuente. Si el directorio ya est montado, e o a abre el directorio en la ventana Explorer. Si no est montado, pulsa con el botn derecho sobre a o el nodo de ms alto nivel de Filesystems, selecciona Mount Directory del men contextual, y a u monta el directorio. Pincha con el botn derecho el directorio montado, selecciona New Java Package. Llama o GuiDemoBasic al nuevo paquete. Esta operacin se muestra en la siguiente gura. o 1

4.

A continuacin, crea el contenedor a partir de una plantilla. Nosotros elegiremos JFrame para este o programa. Otros posibles contenedores son Applet, Dialog, Frame o Panel de AWT, y JApplet, JDialog, JInternalFrame, JFrame o JPanel de Swing. 1. 2. Pincha con el botn derecho en el nuevo paquete GuioDemoBasic, y selecciona New o JFrame Form del men contextual. u Nombra AddStrings al nuevo JFrame, y pincha en Finish:

3.

El IDE abre una ventana Source Editor con el cdigo Java para la nueva clase del JFrame. o Adems abre una ventana Form Editor, que incluye la paleta de componentes en la parte superior, a el inspector de componentes en la parte derecha y el panel editor del form bajo la paleta de componentes.

Si observamos con algn navegador de directorios lo que ha ocurrido tras los pasos anteriores, pou demos comprobar que se ha creado un directorio llamado GuiDemoBasic que contiene el chero AddStrings.java que contiene el cdigo Java que aparece en el Source Editor. Adems aparece el o a chero AddStrings.form que es usado por el Form Editor para leer y guardar el form que estamos creando. Este ultimo chero no es necesario para compilar ni ejecutar el programa. El cdigo Java creado con Netbeans puede ser exportado, compilado y ejecutado fuera del IDE en o cualquier entorno Java. Tambin el cdigo Java creado en otros entornos puede ser importado, moe o dicado, compilado y ejecutado en Netbeans. Pero,actualmente no hay ninguna forma de generar un chero .form a partir del cdigo importado. Eso signica que el cdigo importado debe modicarse a o o mano, en lugar de con el Form Editor.

2.

Adicin de componentes al contenedor o

La paleta de componentes nos permite seleccionar qu componente queremos aadir al form. En la e n parte superior derecha de la paleta aparecen varias solapas, con las distintas categor de componentes as que podemos usar. Los tres botones de la parte izquierda de la paleta se usan para denir el modo del Form Editor. Por ahora, aseguraos que el botn Selection Mode est pulsado. o a

Vamos a aadir tres componentes JLabel. Para ello: n 1. 2. 3. Pinchar en la solapa Swing de la paleta de componentes. Pinchar en el botn JLabel. o Mantener pulsada la tecla shift y pinchar tres veces en el panel del editor de forms. Esto hace que aparezcan tres JLabel. Si no hubiesemos mantenido pulsada la tecla shift, slo se hubiese o aadido un JLabel. n

En Java, la colocacin y tamao de los componentes dentro del contenedor est determinada por el o n a gestor de posicionamiento (Layout manager) que tenga denido el contenedor. En este caso el gestor de posicionamiento que tiene denido el JFrame es por ahora BorderLayout. Para aadir los componentes JTextField usaremos un procedimiento algo distinto. n 1. 2. 3. 4. Pincha con el botn derecho en el nodo JFrame del inspector de componentes. o Selecciona Add From Palette en el men contextual y elige Swing JTextField. u Repite el proceso tres veces. Notar que los componentes aparecen tanto en el editor de forms como en el inspector de componentes.

Para ver la apariencia del GUI que hemos construidos podemos pulsar el botn Test Form (colocado o en la parte superior izquierda del Form Editor). En modo Test el gestor de posicionamiento funciona del mismo modo que en la aplicacin compilada, y tambin los componentes del GUI responden a o e eventos de ratn y teclado, aunque los componentes no estn conectados a manejadores de eventos. o a

Modiquemos el gestor de posicionamiento del JFrame para conseguir un aspecto mejor. Intentemos el gestor FlowLayout. 4

1. 2. 3.

Pincha la solapa Layouts en la paleta de componentes. Selecciona el botn FlowLayout. o Pincha en cualquier lugar dentro del JFrame en el editor del form.

Si testeamos ahora el form, obtendremos lo siguiente:

3.

Conguracin de componentes o

Si miramos en el Source Editor el mtodo InitComponents(), podemos ver que aparece sombreado e en color azul claro. Esto nos indica que es cdigo reservado, o sea que se genera automticamente y o a no debe modicarse a mano. 1. Modicacin del texto o a) Seleccionar jLabel1 en el inspector de componentes. b) c) d) e) Pulsar la solapa Properties y localizar la propiedad text. Cambiar su valor de jLabel1 a String A. Notar que el valor tambin cambia en el editor de forms y en el cdigo reservado del Source e o Editor. Modica ahora el valor de la propiedad texto de los otros componentes como muestra la siguiente tabla. Para el componente jTextField3 desactivaremos la propiedad Editable. Componente jLabel1 jLabel2 jLabel3 jTextField1 jTextField2 jTextField3 2. Text String A String B String A+B A default B default result Editable N/A N/A N/A True True False

Cambiar el tamao de componentes n Los componentes tienen ahora mismo el tamao que se adapta al texto que contienen. n a) Pincha la solapa Other Properties y localiza la propiedad preferredSize. b) c) Cambiar el valor de todos los componentes a [80, 30]. Testea de nuevo el form.

3.

Renombrar componentes. Demos nombres ms signicativos a los componentes. a a) Pinchar con el botn derecho cada uno de los componentes en el inspector de componentes, o seleccionando Rename del men contextual. u b) Renombra los componentes segn muestra la siguiente tabla. u Nombre original jLabel1 jLabel2 jLabel3 jTextField1 jTextField2 jTextField3 5 Nuevo nombre lblA lblB lblSum tfA tfB tfSum

4.

Modicacin del t o tulo del Frame a) Selecciona el node JFrame en el inspector de componentes.

b) Selecciona la solapa Properties. c) Pon en el title el valor AddString 1.0.

4.

Construccin de men s o u

Ahora aadiremos una barra de mens a nuestro form. n u 1. Seleccionar JMenuBar en la solapa Swing de la paleta de componentes. 2. Pinchar con el ratn en cualquier parte del panel del editor del form. o

Inicialmente la barra de mens tendr slo un men, sin ningn item. Vamos a aadir otro men, y u a o u u n u le pondremos a cada uno sus opciones (items). 1. 2. 3. 4. Pinchar con el botn derecho del ratn en el nuevo JMenuBar en el inspector de componentes. o o Seleccionar Add JMenu del men contextual. u Pinchar con el botn derecho del ratn en JMenu1. o o Seleccionar Add JMenuItem en el men contextual. u Adems de JMenuItem, es posible elegir JCheckBoxMenuItem, JRadioButtonMenuItem, JMenu a (para submens), y JSeparator. u En JMenu2 aadir otro JMenuItem, un JSeparator y un JMenuItem. n Renombrar los JMenu y JMenuItem, modicando adems algunas propiedades segn muestra la a u siguiente tabla: Nombre original jMenu1 jMenuItem1 jMenu2 jMenuItem2 jMenuItem3 Nuevo nombre FileMenu ExitItem HelpMenu ContetsItem AboutItem Text File Exit Help Contents About Tooltip text File Exit Help Contents About Mnemonic F X H C A

5. 6.

El nuevo aspecto del programa es el siguiente:

5.

Modicando el gestor de posicionamiento

El gestor de posicionamiento que hemos usado (FlowLayout) nos ha permitido cambiar el tamao n de los componentes. Pero ahora queremos que las tres etiquetas queden alineadas juntos con los tres campos de texto. Para conseguir esto cambiaremos de nuevo el gestor de posicionamiento al tipo GridLayout. 1. 2. Pincha con el botn derecho en el nodo JFrame del inspector de componentes. o Selecciona GridLayout en el men contextual. u

3. 4.

Selecciona el nodo GridLayout en el inspector de componentes. Cambia la propiedad Columns al valor 3 y la propiedad Rows al valor 2.

Ahora todo queda bien alineado, aunque hemos perdido en parte el control sobre el tamao de los n componentes, ya que GridLayout hace que todas las celdas tengan el mismo tamao, sucientemente n grande para que quepa el ms grande de ellos. El resultado ahora es: a

6.

Copiando objetos

Es posible copiar y pegar objetos en la ventana Explorer con facilidad. Pueden copiarse miembros de clases (campos, constructores, mtodos, patrones bean) entre clases, y tambin componentes GUI e e entre forms. Copiemos la clase que hemos construido hasta el momento en un nuevo programa: 1. 2. 3. 4. 5. Crear un nuevo paquete para la copia. Pincha con el botn derecho en el sistema de cheros o montado, y selecciona New Java Package, y nombra GuiDemoAdvanced al nuevo paquete. Pincha con el botn derecho en el Explorer, en el nodo AddStrings del antiguo paquete Guio DemoBasic . Pincha con el botn derecho el nodo GuiDemoAdvanced y seleccionar Paste Copy en el men cono u textual. Haz doble click en el nuevo nodo AddStrings para abrirlo en el las ventanas Source Editor y Form Editor. Notar que el nombre del paquete ha sido cambiado automticamente. a En el inspector de componentes dene la propiedad t tulo (title) con AddStrings 2.0.

7.

Asistente de conexin o

Nuestro objetivo en el programa que estamos construyendo es que el tercer JTextField (tfSum) muestre la concatenacin de los otros dos. Si tfA o tfB recibe un ActionEvent, la propiedad text de o tfSum debe cambiar para mostrar el resultado. El asistente de conexin nos ayuda a establecer enlaces entre los eventos de un componente y las o acciones de otro. El asistente de conexin se activa pinchando en el botn Connection Mode de la paleta de compoo o nentes (botn que est junto al de Selection Mode). o a

1. 2. 3.

Selecciona el modo Conexin. o Selecciona el componente que enviar el ActionEvent en Form Editor. O sea, el JTextField a llamado tfA. Selecciona ahora el componente destino. O sea, el JTextField llamado tfSum.

4.

El asistente de conexin se lanza. Abre el nodo action, y selecciona actionPerformed. Acepta o el nombre por defecto del mtodo tfAActionPerfomed, y pulsa Next. e

5.

En el siguiente panel del asistente mantener la operacin por defecto Set Property, seleccionar o la propiedad text, y pinchar en Next.

6.

En el ultimo panel especicar Get Parameter From pulsando el botn User Code. Introducir o luego el siguiente cdigo y pulsar en Finish: o tfA.getText() + tfB.getText()

7. 8. 9.

Si miramos en la ventana Source Editor podemos ver se ha aadido un nuevo mtodo tfAActionPerformed, n e para manejar el ActionEvent que lanza el componente tfA. Repetir la operacin para el otro campo de texto, tfB. o Compilar y ejecutar. Cambiar el campo de texto para comprobar que funciona. El campo de texto resultado, tfSum, muestra tfA concatenado con tfB, como ilustra la siguiente gura. 8

8.

El gestor de posicionamiento GridBagLayout

Cuando se necesita ms control sobre el tamao y posicin de los componentes GUI, puede usarse a n o GridBagLayout. Tambin podriamos utilizar NullLayout, pero esto reducir la portabilidad entre e a distintas plataformas. GridBagLayout es un gestor de posicionamiento estndar de Java que fue dia seado para control preciso de los componentes GUI. El inconveniente que presenta es que es complejo n de congurar y tedioso de modicar. Sin embargo usando el Optimizador de GridBagLayout de Netbeans se facilita bastante la tarea. Con l, podemos ajustar visualmente el tamao y posicin de los e n o componentes y luego ajustar numricamente para obtener una precisin ms exacta. e o a GridBagLayout tambin divide el contenedor en una rejilla de varias las y columnas (al igual que e GridLayout). Pero ahora, las las y columnas no necesitan ser todas de la misma altura o anchura. Vamos a utilizar el Optimizador de GridBagLayout para nuestro programa AddStrings: 1. Establecer GridBagLayout como gestor de posicionamiento. Puede hacerse arrastrando GridBagLayout desde la paleta de componentes hasta el editor del form, o pinchando con el botn derecho del o ratn en el nodo JFrame del inspector de componentes y seleccionar Set Layout en el men cono u textual. Iniciar el optimizador. En el inspector de componentes pinchar con el botn derecho el nodo o GridBagLayout, y luego seleccionar Customize del men contextual para abrir el optimizador u (Customizer Dialog).

2.

3.

Recoloca los componentes JLabel y JTextField segn la siguiente gura: u

4.

Ajustar algunas propiedades de los componentes. Seleccionar el componente en el panel derecho, y luego ajusta los valores con los paneles de la izquierda. Puede hacerse ajustando las propiedades de la parte superior, o bien con los controles visuales de la parte inferior. Nosotros slo ajustaremos el campo de texto tfSum. Deber ser del doble de tamao de los o a n campos de entrada de texto. Ajusta las propiedades segn la siguiente tabla, luego cierra el u optimizador, compila y ejecuta. Propiedad Fill Grid width Internal padding X Nuevo valor Horizontal 4 60

5.

Las propiedades del gestor de posicionamiento pueden tambin ajustarse sin abrir el optimizador. e Basta con seleccionar el componente en el inspector de componentes y luego hacer pinchar la solapa Layout de la parte de abajo.

Al ejecutar ahora el programa obtenemos:

10

9.

A adir manejadores de eventos n

Miremos detallamente el cdigo que genera Netbeans para manejar eventos del GUI. Automticamente o a crea un mtodo para manejar el evento windowClosing. Localizar el mtodo exitForm en el cdigo e e o fuente. Este mtodo es el cdigo por defecto, que se ejecutar con el evento windowClosing, y que e o a fue creado cuando se creo el contenedor JFrame. La primera y ultima l neas de exitForm son cdigo o reservado (sombreadas en azul claro), pero el cuerpo del mtodo no lo es. Podemos modicar libremente e el cuerpo de este mtodo. Este es el patrn comn para mtodos manejadores de eventos que genera e o u e Netbeans. Por defecto el mtodo exitForm para un JFrame contiene slo la siguiente l e o nea: System.exit(0); Adems del evento windowClosing, podemos manejar los dems eventos de los componentes GUI, a a creando un mtodo por cada evento que seleccionemos manualmente. El asistente de conexin inclu e o a una forma para seleccionar un evento y luego crear un mtodo para manejarlo. Veamos otra forma de e generar un mtodo para manejar un evento. e 1. Abrir el nodo ExitItem en el Explorer: AddStrings Form AddStrings [JFrame] jMenuBar1 FileMenu ExitItem 2. Pinchar con el botn derecho este nodo y seleccionar en el men contextual Events Action o u actionPerformed. Como resultado se aade el mtodo ExitItemActionPerformed() al n e cdigo fuente. o

3.

Localizar este mtodo en el cdigo fuente. Es un mtodo vac Copiar o escribir la sentencia e o e o. System.exit(0); del mtodo exitForm en el mtodo ExitItemActionPerformed(). e e

Ahora la opcin Exit del men FileMenu hace que termine el programa. o u Veamos otra forma para asociar un mtodo al evento de un componente. En la versin actual del e o programa tenemos dos mtodos tfAActionPerformed y tfBActionPerformed que fueron creados con e el asistente de conexin para conectar las acciones en los campos de texto tfA y tfB, con el resultado en o tfSum. El asistente de conexin creo estos mtodos vac que luego nosotros rellenamos con cdigo o e os, o para que apareciese el resultado en tfSum. Sin embargo los dos mtodos contienen exactamente el e mismo cdigo. Esto es redundante, por lo que vamos a solucionarlo. o 1. Seleccionar tfB en el inspector de componentes, y pinchar en la solapa Event de la parte inferior de la ventana.

2. Pinchar tfBActionPerformed en la parte superior de la columna derecha, y luego pinchar el botn . . .. o

11

3.

En la ventana de dilogo que aparece seleccionar Remove para eliminar el mtodo tfBActionPerformed. a e

4.

Aadir ahora el mtodo tfAActionPerformed, y pinchar en OK para terminar. n e

Si miramos el cdigo fuente podemos ver que el mtodo tfBActionPerformed ha sido eliminado. o e Ahora tenemos un programa algo ms simple. Esta aproximacin permite asociar fcilmente el mismo a o a mtodo para manejar varios eventos. e Veamos dos ultimas formas de crear un mtodo manejador de eventos. e 1. 2. 3. En el inspector de componentes, pinchar con el botn derecho en el nodo lblA. o En el men contextual seleccionar Events Mouse mouseEntered. Esto crea el mtodo u e lblAMouseEntered(). Insertar la siguiente l nea en este mtodo: e lblA.setForeground(java.awt.Color.red); 4. 5. Ahora en el editor de forms, pincha con el botn derecho del ratn en la etiqueta lblA (con o o texto String A). Selecciona Events Mouse mouseExited en el men contextual. u

12

6.

Inserta el siguiente mtodo en el mtodo lblAMouseExited(): e e lblA.setForeground(java.awt.Color.green);

Compila el programa y ejectalo. Ahora la etiqueta String A cambia de color cuando el cursor del u ratn entra y sale el rectngulo que la encuadra. o a

10.

Contenedores dentro de contenedores

Un JPanel puede contener cualquier nmero de componentes. Puesto que un JPanel es l mismo un u e componente, puede colocarse dentro de otro JPanel, un JFrame, u otro contenedor GUI. Esto permite la construccin de complejos GUIs. o Si todos los componentes de todos los contenedores de un programa, fuesen visibles al mismo tiempo en Netbeans, resultar vialmente confuso e inmanejable. El editor de forms evita esta confusin a o mostrando slo un contenedor con sus componentes al mismo tiempo. Veremos que el desarrollador o tiene una forma sencilla para elegir el contenedor a mostrar. Vamos a rellenar el espacio libre que queda en la parte superior derecha de AddStrings con un JPanel. En este JPanel colocaremos un par de componentes. 1. Seleccionar el icono JPanel de la paleta de componentes y luego pincha la esquina vac de a AddStrings en el editor de form para aadir el JPanel. Esto hace que aparezca un pequeo n n cuadrado azul en esta esquina del editor de forms. Usemos el optimizador del GridBagLayout para ajustar el espacio que ocupa. Pincha con el botn derecho del ratn el nodo GridBagLayout en el inspector de componentes o o y selecciona Customize en el men contextual. u Selecciona el JPanel en la ventana de dilogo del optimizador y luego ajustar GridWidth al valor a 3 y GridHeight al valor 2. Cerrar el optimizador.

2. 3. 4.

13

Si miramos el editor de forms podemos comprobar que el JPanel parece no estar en el form, ya que el pequeo cuadrado azul ha desaparecido. No hay problema, el JPanel est todav en el inspector n a a de componentes. 1. Selecciona el JPanel en el inspector de componentes, lo que har que aparezca de nuevo el a cuadrado azul. 2. Pincha con el botn derecho del ratn el JPanel en el inspector de componentes y selecciona o o Design This Container del men contextual. Esto har que el JPanel ocupe todo el espacio u a y el JFrame desaparezca. 3. 4. Insertar un JButton y un JLabel desde la paleta de componentes en el JPanel. Compila y ejecuta para comprobar el resultado.

En este momento el editor de forms muestra el JPanel. Para volver al JFrame pincha con el botn o derecho del ratn y comprueba que ahora las aparecen las opciones Design This Container y Design o Top Container. Esto nos da una forma sencilla para movernos entre el JFrame y el JPanel.

11.

Creacin de un panel para dibujar y gestionar sus eventos o

Vamos a modicar el programa AddStrings para aadir un panel en el que dibujaremos una l n nea desde el vrtice superior izquierda, hasta el ultimo punto en el que hicimos click con el ratn. Inicialmente la e o l nea estar dibujada desde el vertice superior izquierda hasta las coordenadas 50, 50. El nuevo panel a sustituir al antiguo panel jPanel1. Este nuevo panel debe hacerse creando una nueva clase que sea a subclase de JPanel, en la que sobreescribiremos el mtodo paint(). e 1. 2. 3. 4. 5. 6. En primer lugar crearemos un nuevo paquete llamado GuiDemoAdvanced2. Usando el Explorer, copia el nodo AddStrings del antiguo paquete GuiDemoAdvanced en el nuevo paquete GuiDemoAdvanced2. Haz doble click en el nuevo nodo AddStrings para abrirlo en el editor de forms y editor de cdigo fuente. o En el inspector de componentes selecciona el nodo jPanel1 y elim nalo mediante el men conu textual. Selecciona el nodo GuiDemoAdvanced2 en el Explorer, y crea un nuevo JPanel: Men File u New Java GUI Forms JPanel Form. Nombraremos JPanelLinea a esta nueva clase. Aade dos campos x e y de tipo int a la clase JPanelLinea que nos servirn para guardar la n a ultima posicin donde hemos pinchado con el ratn dentro del panel. Para aadir estos campos o o n podemos hacerlo usando el editor del cdigo fuente, o bien pinchando con el botn derecho el nodo o o Fields en la clase JPanelLinea del Explorer, y seleccionando AddField en el men contextual. u

14

7.

Usando el editor del cdigo fuente incluye las sentencias de inicializacin de x e y en el constructor o o de JPanelLinea, despus de la llamada a initComponents();. e x=50; y=50;

8. Sobreescribe el mtodo paint(Graphics) en la clase JPanelLinea (mtodo heredado de JComponents). e e Para ello selecciona el nodo class JPanelLinea en el Explorer, pincha con el botn derecho o del ratn y selecciona Override Methods.... En el dilogo que aparece selecciona la clase o a JComponent y el mtodo void paint(Graphics), pincha en el botn Add y luego el botn e o o OK.

9.

Aade la sentencia g.drawLine(0,0,x,y); al nal del mtodo paint(). n e

15

10. Manejar el evento mousePressed. Puede hacerse seleccionando el nodo JPanel en el inspector de componentes, luego la solapa Events y pinchando nalmente en el evento mousePressed. Este paso har que se aada el mtodo formMousePressed(java.awt.event.MouseEvent evt) a n e a la clase JPanelLinea.

11. Aade las sentencias siguientes en el mtodo formMousePressed(java.awt.event.MouseEvent evt): n e x=evt.getX(); y=evt.getY(); repaint(); 12. Compila la clase JPanelLinea. Este paso es muy importante, ya que de no hacerlo el siguiente paso no se podr hacer. a 13. Aade el panel JPanelLinea como componente del JFrame de AddStrings. Para ello utilizando n el Explorer: Abre nodos de AddStrings hasta que sea visible el nodo [JFrame]. Copia JPanelLinea al portapapeles (con el botn derecho del ratn pincha el nodo JPanelLinea o o y selecciona Copy en el men contextual). u Pega el panel en el JFrame: Pincha con el botn derecho del ratn el nodo [JFrame] de o o AddStrings, y selecciona Paste en el men contextual. Este paso har que se aada al u a n JFrame de AddStrings un JPanelLinea llamado jPanelLinea1. Abre el optimizador del GridBagLayout del JFrame de AddStrings. Modica las siguientes propiedades del JPanelLinea: Propiedad Grid Width Grid Height Fill Valor 3 2 Both

16

Compila y ejecuta el programa. Puedes comprobar que al pinchar con el ratn dentro del panel, aparece o una l nea desde el vrtice superior izquierda del panel hasta el punto donde hemos pinchado. e

12.

Localizacin de los programas ya terminados o

En este guin se han desarrollado tres programas. Podis encontrar los cheros .java y .form de estos o e tres programas en la direccin http://decsai.ugr.es/~acu/NTP/archivos/ProgramasGuion2Java. o

17

También podría gustarte