El atributo de posición de Gtk 3 en la señal de inserción de texto de Gtk.

Tengo problemas para administrar la señal de inserción de texto emitida por el widget Gtk.Entry. Considere el siguiente ejemplo:

from gi.repository import Gtk def on_insert_text(entry, new_text, new_text_length, position): print(position) entry = Gtk.Entry() entry.connect('insert-text', on_insert_text) window = Gtk.Window() window.connect("destroy", lambda q: Gtk.main_quit()) window.add(entry) window.show_all() Gtk.main() 

El atributo de posición que estoy recibiendo en el manejador de señales es siempre 0. A menos que esté entendiendo mal, ¿no debería ser la posición donde se debe insertar el siguiente texto?

Al final, lo que quiero hacer es validar la entrada de texto en el widget para restringir los caracteres que serán aceptados. La forma en que planeo hacer esto es similar al ejemplo proporcionado en la documentación en la que todos los caracteres se transforman en mayúsculas.

Se espera que el controlador de ‘insertar texto’ actualice el valor recibido en el parámetro de posición (que hemos visto en forma incorrecta) para reflejar la posición desde la cual se debe insertar el texto futuro y devolverlo. Esto es importante para que el cursor se cambie al lugar correcto después de que regrese el manejador de señales (esto lo hace gtk ). Si no actualiza y regresa, el cursor permanece en la posición 0.

Después de seguir la sugerencia de utilizar entry.get_position() para obtener el valor de posición correcto, descubrí que pygobject estaba ignorando la actualización y el retorno de la posición en mi controlador. Se comportó como si no estuviera devolviendo nada (el cursor se mantuvo en la posición 0). La configuración de la posición dentro del controlador no ayudó, porque gtk lo cambiaría de nuevo a 0 después de que el controlador regresara.

Después de una investigación adicional, aprendí que el problema radica en el manejo de los parámetros de entrada / salida en pygobject que funciona bien en la mayoría de los casos pero no con señales (consulte el error 644927 )

Si usa Conectar para adjuntar un controlador a la señal y la señal tiene un parámetro de entrada / salida, es posible que no reciba lo que espera en el controlador e incluso si devuelve un valor, es probable que pygobject no maneje este valor correctamente. Cualquier cosa que dependa de ese valor probablemente no funcionará como se espera (por ejemplo, avanzar el cursor a la nueva posición)

Sin embargo, hay una solución que consiste en anular el vfunc asociado (el controlador predeterminado) en lugar de conectarse con connect() . Esta solución implica derivar de la clase base pero funciona.

Puede usar este método para la validación / transformación de Gtk.Entry en Gtk.Entry . Un ejemplo de manejo de mi caso de uso sería:

 import re import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk class MyEntry(Gtk.Entry, Gtk.Editable): def __init__(self): super(MyEntry, self).__init__() def do_insert_text(self, new_text, length, position): regexp = re.compile('^(\d*\.?\d*)$') if new_text == '.' and '.' in self.get_text(): return position elif regexp.match(new_text) is not None: self.get_buffer().insert_text(position, new_text, length) return position + length return position entry = MyEntry() window = Gtk.Window() window.connect("destroy", lambda q: Gtk.main_quit()) window.add(entry) window.show_all() Gtk.main() 

En este caso, el parámetro de posición se recibe correctamente y pygobject ve y utiliza el valor de retorno, por lo que el cursor está colocado correctamente.

Nota importante Tienes que heredar de Gtk.Editable además de Gtk.Entry. Si no lo hace, comenzará a ver la validación o lo que sea que haga dentro de do_insert_text aplicándose a todos los demás Gtk.Entry en su aplicación. Si no hereda, está anulando la implementación base proporcionada por Gtk.Editable, a la que llaman todos los demás widgets de Gtk.Entry en su aplicación. Al heredar de Gtk.Editable, usted reemplaza solo la copia ‘local’ de la implementación base que solo se aplica a su clase personalizada.