Ожидается, что обработчик «insert-text» обновит значение, полученное в параметре позиции (которое мы видели неверно), чтобы отразить позицию, из которой должен быть вставлен будущий текст, и вернуть его. Это важно, чтобы курсор был изменен в нужное место после возврата обработчика сигнала (это делается gtk
). Если вы не обновляете и не возвращаете, курсор остается в позиции 0.
После того, как вы предложили использовать entry.get_position()
, чтобы получить правильное значение позиции, я узнал, что обновление и возврат позиции в моем обработчике игнорируется pygobject
. Он вел себя так, как будто я ничего не возвращал (курсор остался в позиции 0). Установка позиции внутри обработчика не помогла, потому что gtk
изменит ее обратно на 0 после возврата обработчика.
После некоторого дальнейшего исследования я узнал, что проблема заключается с обработкой в / из параметров в pygobject
, который хорошо работает в большинстве случаев, но не с сигналами (см bug 644927)
Если вы используете подключение к прикрепить обработчик сигнала, а сигнал имеет параметр ввода/вывода, который может не получить то, что вы ожидаете от обработчика, и даже если вы вернете значение, это значение, вероятно, не будет корректно обрабатываться pygobject
. Все, что зависит от этого значения, вероятно, не работает должным образом (например, переместить курсор в новое положение)
Существует решение, хотя, который должен отменить связанный с ним vfunc (обработчик по умолчанию) вместо того, чтобы соединяться с connect()
. Это решение подразумевает получение базового класса, но оно действительно работает.
Вы можете использовать этот метод для проверки/преобразования входных данных на Gtk.Entry
. Пример обработки мой случай использования будет:
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()
В этом случае параметр позиции принят правильно и возвращаемое значение рассматривается и используется pygobject поэтому курсор правильно.
Важное примечание Вы должны наследовать от Gtk.Editable в дополнение к Gtk.Entry. Если вы этого не сделаете, вы начнете видеть валидацию или все, что вы делаете внутри do_insert_text
, применяя к любой другой Gtk.Entry
в своем приложении. Если вы не наследуете, вы переопределяете базовую реализацию, предоставляемую Gtk.Editable, которая вызывается всеми другими Gtk.Entry
виджетами в вашем приложении. Наследуя от Gtk.Editable, вы переопределяете только «local» копию базовой реализации, которая применяется только к вашему пользовательскому классу.
Просто запустил ваш код. Я также получил эту проблему, но если вам действительно нужна позиция, просто используйте 'entry.get_position()'. К какому примеру в документации вы ссылаетесь на этот путь? – B8vrede
В описании класса Gtk.Editable имеется ссылка на сигнал «insert-text» и пример возможного обработчика для этого сигнала. В документах текст преобразуется в нижний регистр, в моем случае я бы проверял его на регулярное выражение и решал, нужно ли вставлять или нет, но структура обработчика будет точно такой, как показано на рисунке. Кстати, 'entry.get_posisition()' делает работу, я думаю, поэтому я, вероятно, буду ее использовать. –
Я думаю, что поведение, которое мы видим, связано с тем, что привязки python не обрабатывают все правильно. Когда вы запустили мой примерный код выше, вы также получили следующее предупреждение? 'Предупреждение: g_value_get_int: assertion 'G_VALUE_HOLDS_INT (значение)' failed Gtk.main()' –