来自 Gtk.Entry 的插入文本信号的 Gtk 3 位置属性始终为 0
Gtk 3 position attribute on insert-text signal from Gtk.Entry is always 0
我在管理 Gtk.Entry 小部件发出的插入文本信号时遇到问题。考虑以下示例:
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()
我在信号处理程序上收到的位置属性始终为 0。除非我误解了这不应该是应该插入下一个文本的位置吗?
最后我想做的是验证小部件中的文本输入以限制将被接受的字符。我打算这样做的方式类似于文档中提供的示例,其中所有字符都转换为大写。
'insert-text' 的处理程序应该更新位置参数中接收到的值(我们已经看到不正确)以反映未来文本应该插入的位置,return 它.这很重要,因此光标会更改到信号处理程序 return 之后的正确位置(这是由 gtk
完成的)。如果你不更新 return 那么光标会停留在位置 0.
在遵循使用 entry.get_position()
获取正确位置值的建议后,我发现 pygobject
忽略了处理程序中位置的更新和 return。它表现得好像我没有 returning 任何东西(光标保持在位置 0)。在处理程序中设置位置没有帮助,因为 gtk
会在处理程序 returned 之后再次将其更改回 0。
经过进一步调查后,我了解到问题出在 pygobject
中 in/out 参数的处理,这在大多数情况下效果很好,但信号却不行(参见 bug 644927)
如果您使用 connect 将处理程序附加到信号并且该信号有一个 in/out 参数,您可能无法在处理程序中收到您期望的内容,即使您 return 一个值 这个值可能也不会被 pygobject
正确处理。任何依赖于该值的东西都可能无法按预期工作(例如将光标前进到新位置)
有一个解决方案是覆盖关联的 vfunc(默认处理程序)而不是与 connect()
连接。此解决方案意味着从基础派生 class 但它确实有效。
您可以使用此方法在 Gtk.Entry
上输入 validation/transformation。处理我的用例的示例是:
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()
在这种情况下,位置参数被正确接收并且 return 值被 pygobject 看到并使用,因此光标被正确定位。
重要提示
除了 Gtk.Entry 之外,您还必须继承 Gtk.Editable。如果您不这样做,您将开始看到验证或您在 do_insert_text
中所做的任何事情都适用于应用程序中的所有其他 Gtk.Entry
。如果您不继承,您将覆盖 Gtk.Editable 提供的基础实现,它会被应用程序中的所有其他 Gtk.Entry
小部件调用。通过从 Gtk.Editable 继承,您仅覆盖仅适用于您的自定义 class.
的基本实现的 'local' 副本
我在管理 Gtk.Entry 小部件发出的插入文本信号时遇到问题。考虑以下示例:
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()
我在信号处理程序上收到的位置属性始终为 0。除非我误解了这不应该是应该插入下一个文本的位置吗?
最后我想做的是验证小部件中的文本输入以限制将被接受的字符。我打算这样做的方式类似于文档中提供的示例,其中所有字符都转换为大写。
'insert-text' 的处理程序应该更新位置参数中接收到的值(我们已经看到不正确)以反映未来文本应该插入的位置,return 它.这很重要,因此光标会更改到信号处理程序 return 之后的正确位置(这是由 gtk
完成的)。如果你不更新 return 那么光标会停留在位置 0.
在遵循使用 entry.get_position()
获取正确位置值的建议后,我发现 pygobject
忽略了处理程序中位置的更新和 return。它表现得好像我没有 returning 任何东西(光标保持在位置 0)。在处理程序中设置位置没有帮助,因为 gtk
会在处理程序 returned 之后再次将其更改回 0。
经过进一步调查后,我了解到问题出在 pygobject
中 in/out 参数的处理,这在大多数情况下效果很好,但信号却不行(参见 bug 644927)
如果您使用 connect 将处理程序附加到信号并且该信号有一个 in/out 参数,您可能无法在处理程序中收到您期望的内容,即使您 return 一个值 这个值可能也不会被 pygobject
正确处理。任何依赖于该值的东西都可能无法按预期工作(例如将光标前进到新位置)
有一个解决方案是覆盖关联的 vfunc(默认处理程序)而不是与 connect()
连接。此解决方案意味着从基础派生 class 但它确实有效。
您可以使用此方法在 Gtk.Entry
上输入 validation/transformation。处理我的用例的示例是:
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()
在这种情况下,位置参数被正确接收并且 return 值被 pygobject 看到并使用,因此光标被正确定位。
重要提示
除了 Gtk.Entry 之外,您还必须继承 Gtk.Editable。如果您不这样做,您将开始看到验证或您在 do_insert_text
中所做的任何事情都适用于应用程序中的所有其他 Gtk.Entry
。如果您不继承,您将覆盖 Gtk.Editable 提供的基础实现,它会被应用程序中的所有其他 Gtk.Entry
小部件调用。通过从 Gtk.Editable 继承,您仅覆盖仅适用于您的自定义 class.