我在管理 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' 的处理程序应该更新位置参数中收到的值(我们已经看到不正确)以反射(reflect) future 文本应该插入的位置并返回它。这很重要,因此在信号处理程序返回后光标会更改到正确的位置(这由 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
中所做的任何事情。适用于所有其他 Gtk.Entry
在你的应用程序中。如果你不继承,你将覆盖 Gtk.Editable 提供的基础实现,它被所有其他调用 Gtk.Entry
您的应用程序中的小部件。通过从 Gtk.Editable 继承,您仅覆盖基实现的“本地”副本,该副本仅适用于您的自定义类。
关于python - 来自 Gtk.Entry 的插入文本信号上的 Gtk 3 位置属性始终为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38815694/