Читать книгу Desarrollo de interfaces gráficas en Python 3 con Tkinter - Tomás Domínguez Mínguez - Страница 25

5.3 GESTIÓN DEL FOCO

Оглавление

El siguiente grupo de métodos está relacionado con el foco de un widget, es decir, con la entrada de datos por teclado:

•focus_get(). Devuelve el widget que tiene el foco en una aplicación. Si no lo tuviera ninguno, devolvería None.

•focus_set(). Pone el foco en un widget determinado.

•tk_focusFollowsMouse(). Fuerza que el foco esté donde se encuentre el ratón.

•tk_focusNext(). Devuelve el widget que sigue en la secuencia transversal del foco.

•tk_focusPrev(). Devuelve el widget que precede en la secuencia transversal del foco.


Recuerde que la secuencia transversal del foco está formada por los widgets por los que va pasando cuando se pulsa el tabulador.

La práctica que va a realizar en esta ocasión es un juego donde se muestra una ventana con cuatro campos. Al iniciar el programa, el foco se encuentra en el primer campo y, a partir de ese momento, cambia de forma aleatoria entre el de arriba y el de abajo. El objetivo es ser capaz de escribir correctamente una determinada palabra en todos ellos. Si se confundiera al añadir alguno de sus caracteres, el juego finalizaría, deshabilitándolos y mostrando un mensaje en color rojo que indicaría que el reto no ha sido conseguido. En caso contrario, el mensaje de acierto se mostraría en color verde.

El código del programa es el siguiente:




En primer lugar, se importa todo aquello que se va a utilizar. En concreto, de Tkinter se va a necesitar la clase Tk para crear la ventana principal, Entry para los campos de texto y Label para los mensajes de éxito o fracaso. De la librería random se importa la función randint(), para generar números aleatorios:


Luego, se declaran las variables de configuración. La primera (texto) almacena el texto que deberá escribirse correctamente en todos los campos para completar el juego. La segunda (periodo) es el tiempo que permanecerá el foco en un campo antes de cambiar al siguiente. Cuanto menor sea su valor, en milisegundos, más dificultad entrañará el juego:


Salte la declaración de la función, que se describirá más adelante, hasta encontrar las sentencias en las que se crea la ventana principal (root); se le asigna un texto a su barra de título y se impide que pueda redimensionarse:


A continuación, se crean los campos de texto (campo1, campo2, campo3 y campo4). En ellos se establece la misma fuente (opción font), el mismo borde (opción bd) y, sobre todo, un marco de color rojo de dos píxeles de grosor para indicar cuándo tienen el foco (opciones highlightcolor y highlightthickness):



Una vez creados los campos, se colocan verticalmente en la ventana principal con el método pack(). El espacio entre ellos se fija con las opciones padx


La siguiente sentencia establece el foco en el primer campo (campo1), para lo que se hace uso de uno de los métodos descritos en esta sección: focus_set():


Por último, se comienza el juego invocando la función modifica_foco(), en cuyo único argumento se debe indicar el campo activo en ese momento, inicialmente campo1:


Ha llegado el momento de conocer el contenido de esta función. En primer lugar, se declara la variable estado, cuyos valores indicarán si el juego está en curso (“EN CURSO”), o si se ha finalizado con éxito (“OK”) o con fracaso (“KO”). Cuando se invoca la función es porque, de momento, está en curso; de ahí que se asigne inicialmente dicho estado:


Después, se obtiene el valor del campo actual (el pasado como argumento), utilizando el método get():


Las siguientes sentencias determinan si el juego ha terminado (podrá ser con éxito o con fracaso). Para ello, si los caracteres que hay escritos en dicho campo (texto_campo_actual) no coincidieran con los del texto de referencia (texto), el juego pasaría a un estado “KO” (más tarde se verá lo que se hace en este estado). En caso contrario, se comprobaría si el contenido de todos los campos coincide con el texto completo de referencia, en cuyo caso el juego pasaría a un estado “OK” (a continuación, descubrirá qué se hace en este otro estado):


Si el juego no hubiera terminado (no se ha cumplido ninguna de las condiciones de los if anteriores), su estado seguiría siendo en “EN CURSO”, por lo que se cumpliría la condición del siguiente if, en el que se decide el campo al que tendría que pasar el foco. Para saber cuál es, se usa la función randint(), que devuelve aleatoriamente el número 0 o el 1 (equivalente a False y True). En función de dicho valor, se invocaría a la función tk_focusNext() o tk_focusPrev() para identificar el campo siguiente o el anterior al que tiene el foco actualmente. Una vez conocido dicho campo (nuevo_campo), se le asigna el foco con el método focus_set(). Por último, se invoca de nuevo a esta función con el método after() para continuar jugando:


Si el juego ha finalizado (el estado no es “en curso”), se ejecutan las sentencias del bloque else. Dentro, hay otra sentencia if…else que determina si el juego ha finalizado con éxito (estado “OK”) o no. Si lo hubiera hecho con éxito, se crearía la etiqueta que muestra el mensaje de felicitación. La fuente del texto sería la misma de los campos de entrada (opción font), pero de color verde (opción fg). En caso contrario, la etiqueta tendría otro texto menos afortunado, con la misma fuente pero en color rojo. En ambos casos, se deshabilitan todos los campos de texto utilizando el método configure(), con el que se asigna el valor "disabled" al atributo. Por último, se llama al método pack(), para presentar en pantalla la etiqueta con el mensaje correspondiente de finalización del juego:



El atributo state, compartido por muchos widgets, determina el estado del widget en el que se encuentra. Se describirá más adelante, cuando estudie cada uno de ellos.

Seguro que estará deseando empezar a jugar. Espero que tenga mejor suerte que yo.



Si quiere mejorar la jugabilidad del programa, y también su dificultad, obligue a introducir algún carácter al cambiar el foco de campo.

Desarrollo de interfaces gráficas en Python 3 con Tkinter

Подняться наверх