Desarrollo de interfaces gráficas en Python 3 con Tkinter

Tekst
0
Recenzje
Przeczytaj fragment
Oznacz jako przeczytane
Czcionka:Mniejsze АаWiększe Aa

Unidad 4
OPCIONES COMUNES

En Tkinter, el aspecto de un widget se describe a través de una serie de características; algunas son específicas y otras son compartidas por muchos widgets. Estas características comunes son las siguientes:

•Dimensiones: height, width, bd, borderwidth, border, padx, pady y highlightthickness.

•Color: background (bg), activebackground, activeforeground, disabledbackground, disabledforeground, foreground (fg), highlightbackground y highlightcolor.

•Fuente del texto: font.

•Foco: takefocus.

•Posición: anchor.

•Relieve: relief.

•Imágenes: bitmap, image y compound.

•Cursor del ratón: cursor.

Para asignar un valor a cualquiera de estas características, se utilizan keyword arguments. Como seguramente sepa, los argumentos de una función pueden ser de tipo positional o keyword. En el primer caso (el que estará acostumbrado a usar), cada argumento se identifica por su posición al invocar la función (o método); es decir, son posicionales.

Los argumentos de tipo keyword van precedidos de su nombre, por lo que podrán ocupar cualquier posición. Esto es especialmente útil cuando hay muchos argumentos opcionales, como en el caso de la mayoría de los widgets.


A las características también se las llama “opciones”, incluso “atributos”. Esta última acepción debe entenderse en el sentido general del término, es decir, como un rasgo o cualidad del widget (y no como lo que se entiende en Python como atributo de una clase).

Veamos en detalle cada uno de estos grupos.

4.1 DIMENSIONES

Las primeras opciones que estudiará son las relacionadas con las dimensiones de diversas características de un widget, entre las que destacan:

•bd, borderwidth o border. Ancho del borde utilizado para dar un aspecto tridimensional al widget.

•height. Altura del widget. Dependiendo de su tipo, podrá ser un número de píxeles o líneas.

•highlightthickness. Ancho del rectángulo que aparece alrededor del widget cuando tiene el foco.

•padx. Espacio adicional, interno a los límites del widget, que se le añade horizontalmente.

•pady. Espacio adicional, interno a los límites del widget, que se le añade verticalmente.

•width. Ancho del widget. Dependiendo de su tipo, podrá ser un número de píxeles o caracteres.


Cuando una opción tiene varios nombres, tenga en cuenta que puede haber widgets que solo admitan uno de ellos.


Si el valor de una dimensión se especifica como un número seguido del carácter ‘c’, se estará especificando en centímetros; si se usa el carácter ‘m’, en milímetros; mientras que ‘i’ hará referencia a pulgadas (inches en inglés).

En la primera práctica que realizará con este tipo de atributos comunes, modificará el programa ¡Hola Mundo! inicial para no tener que añadir los retornos de carro ni los espacios antes y después del texto, con el fin de evitar que este quede pegado a los bordes de la ventana. Su código ahora es el siguiente:


Como puede observar, el único cambio está en el constructor de la clase Label, ya que ahora se utilizan los atributos padx y pady para añadir un espacio adicional de 10 píxeles alrededor de la etiqueta:


Ejecute el programa y observe que el resultado es similar al utilizado de base.

4.2 COLOR

El segundo bloque de atributos tiene que ver con el color. Tkinter representa los colores con cadenas. Hay dos formas de especificarlos:

•Por su nombre en inglés: "white", "black", "red", "green", "blue", "cyan", “yellow", “orange", y "magenta". Dependiendo de su instalación, podría disponer de otros adicionales.

•Indicando la intensidad de los colores rojo, verde y azul en dígitos hexadecimales.

Para entender esta última forma de expresar los colores, primero debe saber que al rojo, al verde y al azul se los considera primarios porque el resto de colores se pueden obtener a partir de una composición de estos tres colores primarios. El valor de intensidad mínimo que pueden tener es 0 y el máximo es 255.

Ejemplos de especificación de colores utilizando la nomenclatura RGB:

•Blanco: (255, 255, 255)

•Negro: (0, 0, 0)

•Rojo: (255, 0, 0)

•Verde: (0, 255, 0)

•Azul: (0, 0, 255)

•Amarillo: (255, 255, 0)

•Púrpura: (255, 0, 255)

•Cian: (0, 255, 255)

Dicha notación es la decimal. En hexadecimal, un color se representa con una almohadilla #, seguida de seis caracteres hexadecimales (0-9 y A-F). Estos caracteres se dividen en tres parejas de dos caracteres cada una para representar los colores R, G y B (en dicho orden). La intensidad máxima de un color es FF (255 en decimal) y la mínima es 00 (0 en decimal).

Así, por ejemplo, el color rojo se expresaría como “#FF0000” porque los dos primeros caracteres representan la intensidad máxima de este color (FF, la máxima), los dos siguientes la del verde (00, la mínima) y los dos últimos la del azul (00, la mínima). Por el mismo motivo, el color verde se especificaría como “#00FF00” y el azul como “#0000FF”. El blanco se representaría como “#FFFFFF” (es la suma de los tres colores básicos) y el negro como “#000000” (no hay ningún color).

Los principales atributos (opciones) relacionados con el color son:

•background o bg. Color de fondo con el que se muestra el widget en su estado habitual.

•activebackground. Color de fondo cuando el widget está activo, es decir, cuando el cursor del ratón se encuentra sobre él (y no está inactivo).

•activeforeground. Color de primer plano cuando el widget está activo.

•disabledbackground. Color de fondo del widget cuando está inactivo, es decir, cuando no se puede actuar sobre él.

•disabledforeground. Color de primer plano cuando el widget está inactivo.

•foreground o fg. Color de primer plano con el que se muestra el widget en su estado habitual.

•highlightbackground. Color del rectángulo que rodea el widget cuando no tiene el foco. Debe utilizarse junto con highlightthickness.

•highlightcolor. Color del rectángulo que rodea el widget cuando tiene el foco. Debe utilizarse junto con highlightthickness.


Al igual que se indicó en las opciones anteriores, cuando alguna tenga varios nombres, puede haber widgets que solo admitan uno de ellos. El nombre más largo suele ser el más admitido comúnmente (background en vez de bg, foreground en vez de fg, borderwidth en vez de bd, etc.).

Modifique la sentencia del programa anterior, donde se creaba la etiqueta:


Debe quedar como sigue:


Se ha asignado un color de fondo amarillo y otro azul de primer plano (el del texto) con los atributos bg y fg, respectivamente. El resultado lo puede ver a continuación:


Ahora quite las opciones padx y pady del constructor de la etiqueta y páselas al método pack(). El programa quedaría así:


En este caso, ahora ambas opciones hacen referencia al interior de los bordes de la ventana principal, por lo que la etiqueta se separa de estos 10 píxeles:


Si quisiera que dentro de la etiqueta también hubiera ese margen interno, debería añadir de nuevo las opciones padx y pady a su constructor, o incluir las opciones ipadx e ipady al método pack(). Quedaría así:


Como puede apreciar en esta nueva imagen, ahora existe un espacio de 10 píxeles tanto en el interior como en el exterior de la etiqueta:

 


A diferencia del método pack(), el constructor de la etiqueta no tiene las opciones ipadx e ipady. Además, recuerde que las opciones padx y pady de dicho método hacen referencia al borde interno de la ventana principal (o widget contenedor), no al de la etiqueta. Por eso, las opciones ipadx e ipady del método pack() tienen el mismo efecto que padx y pady en los widgets que contienen.

4.3 FUENTE

Una de las características compartidas por los controles gráficos que muestran o permiten la entrada de textos es la fuente (tipo de letra). Una fuente se describe como una tupla con el siguiente formato:

(familia, tamaño)

Opcionalmente, se puede añadir un elemento más, consistente en una cadena que contiene uno o más modificadores de estilo para indicar si el texto va en negrita, cursiva, subrayado o tachado (bold, italic, underline u overstrike); por ejemplo, para que un texto use la fuente Times New Roman con un tamaño de 24 píxeles en itálica y negrita, la tupla que debería utilizar es:


Pruébelo, sustituyendo la sentencia donde se creaba la etiqueta del programa anterior


por:


El resultado será el mostrado más abajo:


Para conocer la lista de fuentes disponibles en su sistema, utilice este sencillo programa:


Le aparecerá una pequeña ventana y, en la shell, verá el botón sobre el que deberá hacer doble clic para obtener la lista completa de fuentes:


Dicha lista la puede ver parcialmente en la siguiente imagen:


4.4 FOCO

Muchos de los widgets de una aplicación, especialmente aquellos con los que se realiza la entrada de datos, son susceptibles de tener el foco en un momento determinado; es decir, que lo que se escriba con el teclado vaya dirigido hacia ellos. Una forma de hacer que un widget tenga el foco es pulsarlo con el ratón. Pero también se podría usar el tabulador, haciendo que este vaya pasando de uno a otro, en lo que se conoce como “enfoque transversal” (focus traversal). El orden en el que se mueve sigue las siguientes reglas:

•En el caso de los widgets contenidos en la ventana principal (o un widget contenedor), el foco los va recorriendo en el mismo orden en que se crearon.

•Si el valor del atributo takefocus de un widget contenedor fuera True (por ejemplo, un frame o un panel), el foco iría primero a este y, luego, a todos los que contenga en el orden en que fueron creados, de forma recursiva.

•Para evitar que un widget pueda llegar a tener el foco, solo tiene que asignar el valor False al atributo takefocus, lo que haría que este pasara de largo en su recorrido al ir pulsando el tabulador.


Por defecto, el foco no pasará por las etiquetas, frames o menús al pulsar el tabulador. Para que lo haga, tendrá que asignar el valor True a dicho atributo.


Como ya sabe, los atributos highlightthickness y highlightcolor permiten dibujar un marco del ancho y color especificado alrededor del widget que tenga el foco.

Cada widget se comporta de una forma diferente cuando tiene el foco:

•Campo de entrada de texto. Cualquier carácter se agregará a su texto.

•Botón. Podrá presionarse con la barra espaciadora.

•Checkbuttons. Cambia de estado (seleccionado o no seleccionado) al pulsar la barra espaciadora.

Radiobuttons. Se selecciona (si todavía no lo estuviera) con la barra espaciadora.

•Barra de scroll. Las teclas PageUp y PageDown desplazan el contenido de página en página. Las teclas ↑ y ↓ lo mueven en sentido vertical, y las teclas ← y → en sentido horizontal.

•Barra de desplazamiento. Si su orientación fuera horizontal, se movería con las teclas ← y →. Si fuera vertical, se movería con las teclas ↑ y ↓.


Tendrá ocasión de estudiar cada uno de estos widgets más adelante.

Para probar el funcionamiento de esta opción, realizará una nueva práctica utilizando campos de entrada de texto. Es habitual que los formularios le permitan pasar de un campo a otro pulsando el tabulador. Aunque este widget se describirá en detalle más adelante, las opciones con las que se va a utilizar ya las conoce, por lo que no será impedimento para entender el código mostrado a continuación:



En la primera sentencia, además de Tk, se importa también la clase Entry, que representa el campo de entrada de texto:


A continuación, se crea la ventana principal (root):


Después, se crean los campos de entrada de texto. Todo lo que se escriba en ellos aparecerá en color azul sobre un fondo amarillo (opciones bg y fg), con un tipo de letra Times New Roman de 24 píxeles, en cursiva y negrita (opción font). Además, se añaden los atributos highlightcolor y highlightthickness para que, cuando el campo tenga el foco (se pueda escribir en él), muestre un marco de color rojo con un grosor de línea de dos píxeles. Lo más interesante en esta práctica es que el tercer campo incluye también la opción takefocus, cuyo valor False hará que no pueda obtener el foco al pulsar el tabulador:


Las últimas sentencias sitúan los campos de texto en la ventana principal, uno debajo del otro. Para separarlos de los bordes de esta y entre sí, se utilizan las opciones padx y pady:


Ejecute el programa y pulse sobre el primer campo. Observe que aparece un marco rojo alrededor, que indica que ya puede empezar a escribir en él. Ahora pulse el tabulador; comprobará que el foco salta al campo inferior. Vuelva a pulsar de nuevo el tabulador. Esta vez, el foco irá al último campo, saltando el tercero, ya que se asignó el valor False a su opción takefocus. Si vuelve a pulsar el tabulador, el foco regresará de nuevo al primer campo, repitiéndose el ciclo.

La siguiente secuencia de imágenes muestra este recorrido del foco:


4.5 POSICIÓN

El atributo anchor especifica dónde se sitúa el texto o la imagen de un widget en su interior. Sus posibles valores y significado son los mismos que en la opción anchor, ya estudiada en el método place(): CENTER (predeterminada), N, S, W, E, NE, NW, SE y SW. Por ejemplo, si usara el valor W, el texto o la imagen se ubicaría en el lado izquierdo del widget. En cambio, con NW se colocaría en la esquina superior izquierda.

Para probar este nuevo atributo, se utilizará el siguiente código, que será una adaptación del conocido ¡Hola Mundo!:



En este caso, una vez creada la ventana principal, se le asigna un tamaño de 200 × 100 píxeles con el método geometry():


Lo realmente interesante reside en el constructor de la etiqueta, ya que ahora se le da el mismo tamaño de la ventana con las opciones width y height:


Con esto se consigue que la etiqueta quede centrada, incluso aunque modifique el tamaño de la ventana:


Ahora cambie dicha sentencia por:


El resultado obtenido sería el mostrado a continuación:


Realice un último cambio, sustituyendo la sentencia anterior por:


En esta ocasión, el texto se vería en la esquina inferior derecha:


En ambos casos, aunque cambie el tamaño de la ventana, la posición del texto seguirá siendo la misma.

4.6 RELIEVE

El relieve determina el efecto 3D mostrado por un widget. Para aplicarlo, se utiliza el atributo relief, cuyos valores pueden ser: FLAT, RAISED, SUNKEN (por defecto), GROOVE y RIDGE. Es importante que el widget tenga un borde con cierta anchura (opción bd); si fuera muy estrecho, el efecto apenas sería perceptible.


Recuerde que, para hacer uso de cualquier constante, antes deberá importarla. También podrá usar directamente sus valores; por ejemplo, la constante FLAT tiene el valor “flat”, el de RAISED es “raised”, etc.

 

Para demostrar el efecto que tiene este atributo, se utilizará el siguiente programa:


En primer lugar, se importan las clases del paquete Tkinter que se van a utilizar; en concreto, Tk para crear la ventana principal y Label y Entry para mostrar el típico campo de entrada de datos de un formulario, precedido por una etiqueta que indica la información que se debe introducir:


Una vez creada la ventana principal, se evita que pueda ser redimensionada:


A la etiqueta se la asigna el texto genérico “Campo:”. El campo de texto se crea con un efecto SUNKEN (es el predeterminado, por lo que realmente no habría sido necesario incluir esta opción) y un borde de cinco píxeles de grosor:


Las últimas sentencias sitúan la etiqueta a la izquierda del campo, con la separación indicada en las opciones padx y pady:


El resultado de su ejecución es el siguiente:


Ahora, cambie el valor del atributo relief por FLAT, RAISED, GROOVE o RIDGE, y ejecute de nuevo el programa cada vez que lo haga. El resultado será el mostrado en las siguientes imágenes. Se ha añadido un título a la ventana indicando el valor asignado a dicho atributo:


4.7 IMÁGENES

En Tkinter, las imágenes se pueden representar mediante dos clases:

•BitmapImage. Contiene imágenes de dos colores en formato xbm.

•PhotoImage. Contiene imágenes a todo color en formato gif, pgm o ppm.

El constructor de ambas clases tiene como argumento el nombre del archivo que contiene la imagen:

BitmapImage (archivo)

PhotoImage (archivo)

Para asociar una imagen a un widget, se pueden utilizar los siguientes atributos:

•bitmap. Solo admite objetos de la clase BitmapImage.

•image. En este caso, su valor podrá ser un objeto de la clase BitmapImage o PhotoImage.

Normalmente, los píxeles del primer plano de un bitmap se muestran negros y los del fondo se muestran transparentes. Para asignarles otros colores, use las opciones foreground y background.

Tkinter dispone de una serie de bitmaps prediseñados que puede utilizar para expresar advertencias, errores, preguntas, etc. Se muestran a continuación.


Sus nombres son, de izquierda a derecha: "error", "gray75", "gray50", "gray25", "gray12", "hourglass", "info", "questhead", "question" y "warning". También podría crear sus propios bitmaps con archivos en formato xbm.


Para mostrar una imagen, además de utilizar objetos de la clase BitmapImage o PhotoImage, también puede hacer uso de ImageTk, que pertenece a la librería PIL (Python Imaging Library), y que soporta una amplia variedad de formatos de imágenes.

Relacionado con los atributos bitmap e image, se encuentra el atributo compound, que se utiliza cuando la imagen aparece junto a un texto (por ejemplo, en una etiqueta o un botón), indicando su posición respecto de este. Sus valores son: NONE, TOP, BOTTOM, LEFT, RIGHT y CENTER, dependiendo de si quiere que la imagen no aparezca o aparezca encima, debajo, a la izquierda, a la derecha o centrada con el texto, respectivamente.

El siguiente código permite practicar con algunos de los últimos atributos descritos:


En este nuevo programa, tras importar las clases Tk y Label del paquete Tkinter, se crea una ventana a la que se le asigna un tamaño de 200 × 100 píxeles con el método geometry():


A continuación, se crea la etiqueta, en cuyo constructor se establecen los valores de diversos atributos. En primer lugar, se le da un aspecto 3D con la opción relief. Luego, se le añade un texto y un icono con las opciones text y bitmap. Además, para que la imagen quede a la izquierda, se utiliza el atributo compound:


Por último, la etiqueta se muestra centrada horizontal y verticalmente en la ventana con el método place(), utilizando los atributos y valores que ya conoce de una práctica anterior:


Ejecute el programa y observe el resultado. Tal como se aprecia, ahora la etiqueta tiene un borde que da la sensación 3D pretendida, dentro de la que se muestra tanto el texto como el bitmap del reloj a su izquierda:



Para resaltar el efecto de relieve en 3D, amplíe el grosor del borde de la etiqueta con la opción bd.