[英]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”的处理程序应该更新position参数(我们在不正确的情况下看到)中收到的值,以反映应该插入未来文本的位置并将其返回。 这很重要,因此在信号处理程序返回后光标会更改到正确的位置(这由gtk
完成)。 如果不更新并返回,则光标保持在位置0。
在遵循使用entry.get_position()
获取正确位置值的建议之后,我发现pygobject
正在忽略我的处理程序中的更新和返回位置。 它表现得好像我没有返回任何东西(光标保持在位置0)。 设置处理程序内的位置没有帮助,因为gtk
会在处理程序返回后将其再次更改为0。
在进行了一些进一步的调查之后,我了解到问题在于pygobject
中输入/输出参数的处理,这在大多数情况下效果很好但不能用于信号(参见bug 644927 )
如果使用connect将处理程序附加到信号并且信号具有输入/输出参数,则可能无法在处理程序中收到您期望的内容,即使您返回值, 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.Entry之外,您还必须继承Gtk.Editable。 如果您不这样做,您将开始看到验证或您在do_insert_text
执行的任何操作, do_insert_text
应用程序中的每个其他Gtk.Entry
。 如果您不继承,则覆盖Gtk.Editable提供的基本实现,该实现由应用程序中的所有其他Gtk.Entry
小部件调用。 通过继承自Gtk.Editable,您只覆盖仅适用于您的自定义类的基本实现的“本地”副本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.