Python 3.2.3 El widget de escala Tkinter se cuelga cuando está anidado en Frame

Soy relativamente inexperto con Tk, pero he hecho algunos proyectos simples antes y esto me tiene perplejo:

Tengo un widget de escala que representa un control deslizante de tiempo. Un threading.Timer se apaga a intervalos para mover el widget de escala. Al abotonarse, el hilo está deshabilitado; al abotonarse, el hilo se vuelve a habilitar. De modo que el usuario puede hacer clic y arrastrar el control deslizante de tiempo para reposicionar el "tiempo" de la aplicación. Hasta ahora, deshabilitar el subproceso durante la operación de la interfaz de usuario ha evitado bloqueos que supuse que estaban relacionados con la seguridad del subproceso (aparentemente bloqueos no deterministas, ocurrieron aproximadamente en el momento en que el subproceso intentaría actualizar el control deslizante).

Los únicos otros elementos de la interfaz de usuario "activos" son una serie de botones, que se configuran con el parámetro command=fnc. La escala es el único lugar donde estoy usando un enlace(). La aplicación es una aplicación de pantalla completa, por lo que estoy usando self.root.overridedirect (1) y geometría () en el nivel raíz para eliminar menús y bordes, y para que sea de pantalla completa.

Cambié el código, por lo que el widget de escala ahora está dentro de un marco en lugar de en el nivel raíz absoluto:

self.scale_timescrub = tkinter.Scale(self.root.master, from_=0, to=60, width=height_one, orient=tkinter.HORIZONTAL, showvalue=0)
self.scale_timescrub.grid(row=2,column=0,sticky=tkinter.N+tkinter.S+tkinter.E+tkinter.W)
self.scale_timescrub.bind('<Button-1>', self.press_scrub)
self.scale_timescrub.bind('<ButtonRelease-1>', self.release_scrub)

Ahora, la aplicación se bloquea cada vez que intento cualquier operación de IU con el widget de escala. Al presionar en cualquier parte del control deslizante, la CPU se bloquea y la aplicación nunca regresa. Sé que está relacionado con la crianza de los hijos porque cuando pirateo la aplicación para volver a poner la báscula en el nivel raíz, vuelve a funcionar. El widget nunca parece ingresar a sus funciones vinculadas, como press_scrub, cuando está relacionado con el marco.

¿Alguien puede aconsejarme qué estoy haciendo mal aquí?

Ejecutando Python 3.2.3 64b en Windows 7.

preguntado el 21 de mayo de 12 a las 11:05

¿El resto del código está disponible en alguna parte? Definitivamente ayudaría tener un ejemplo mínimo viable con el que podamos jugar que demuestre el problema. -

2 Respuestas

Usted escribió: "Un enhebrado. El temporizador se apaga a intervalos para mover el widget de escala". Al manejar este evento de temporizador, ¿está llamando a métodos de widget desde otro hilo? Si es así, definitivamente ese es el problema. Simplemente no puede cambiar la interfaz de usuario de otro hilo.

Nunca debería necesitar un objeto Timer: ¿sabe que puede programar algo para que se ejecute en un intervalo regular usando after?

Otra cosa a tener en cuenta, pero que no se puede determinar mirando el fragmento de código, es si está usando pack en el mismo widget contenedor. Combinatorio pack y grid en el mismo maestro causará el comportamiento que ves. Por lo general, verá ese comportamiento al inicio en tal caso, pero no siempre.

contestado el 21 de mayo de 12 a las 12:05

No estoy usando pack() y grid() en la misma aplicación. Como traté de indicar, al presionar el botón, elimino Thread.timer() y al presionar el botón y reactivo Thread.timer(). No tuve problemas con la corrección de esto en el pasado, incluso si after() puede ser un mejor estilo de programación. Examinaré after(), pero la evidencia apunta a que el padre Frame tiene algo que ver con eso. - Mayur patel

@Mayur Patel: Aunque elimines el cronómetro, aún podrías tener una condición de carrera. Confía en mí, no hay absolutamente ningún problema con la incrustación de widgets en Frames. Definitivamente hay un error en su código. La evidencia parece apuntar a subprocesos, ya que es un hecho documentado que Tkinter no es seguro para subprocesos. - Bryan Oakley

@Mayur Patel: considera esta posibilidad: haces clic en el control deslizante. Todavía en el hilo principal, Tk intentará actualizar la apariencia del botón antes de llamar al comando. Ahora, posiblemente, el otro hilo tiene prioridad. antes de cancelar el temporizador e intenta actualizar la interfaz de usuario también. Si tu vez intente actualizar un elemento GUI de otro hilo, su código eventualmente se romperá. - Bryan Oakley

Primero, parece haber alguna intención de que Tkinter sea seguro para subprocesos, pero estoy dispuesto a creer que no lo es. bugs.python.org/issue11077. En segundo lugar, al deshabilitar por completo el subproceso del temporizador, el problema persiste. Su condición de "considere esta posibilidad" no ocurre; solo hay un hilo. Los problemas de subprocesos tienden a ser intermitentes y se sienten no deterministas. Este problema es repetible e inmediato. Por supuesto, los widgets de crianza en Frames son una operación común; y, por supuesto, hay un error en mi código. Por eso pido ayuda. :-)- Mayur patel

El problema parece estar en mi uso de la palabra clave "maestro" como el nombre de mi objeto Frame de ventana completa. Cuando cambio el nombre de self.root.master a self.root.full_frame, todo funciona como se esperaba. Gracias a Bryan por señalar los peligros de subprocesos, que usaré para reevaluar otros aspectos de mi aplicación. Gracias a mgilson por mostrar interés en un reproducible. No había emparejado un reproducible antes de publicar porque pensé que tenía tantas configuraciones extrañas configuradas que cualquiera de ellas podría estar involucrada. De todos modos, gracias a todos. Nota personal: no llames a nada "maestro".

contestado el 21 de mayo de 12 a las 20:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.