简体   繁体   English

来自Gtk.Entry的插入文本信号的Gtk 3位置属性始终为0

[英]Gtk 3 position attribute on insert-text signal from Gtk.Entry is always 0

I am having trouble in managing the insert-text signal emitted by the Gtk.Entry widget. 我在管理Gtk.Entry小部件发出的插入文本信号时遇到了麻烦。 Consider the following example: 请考虑以下示例:

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()

The position attribute I am receiving on the signal handler is always 0. Unless I am misunderstanding this should it not be the position where the next text should be inserted? 我在信号处理程序上收到的位置属性总是为0.除非我误解了这应该是不应该插入下一个文本的位置?

In the end what I want to do is to validate the entry of text in the widget to restrict the characters that will be accepted. 最后我想要做的是验证小部件中文本的输入以限制将被接受的字符。 The way I plan to do this is similar to the example provided in the documentation in which all characters are transformed to uppercase. 我计划这样做的方式类似于文档中提供的示例,其中所有字符都转换为大写。

The handler of 'insert-text' is expected to update the value received in the position parameter (which we have seen in incorrect) to reflect the position from which future text should be inserted and return it. “insert-text”的处理程序应该更新position参数(我们在不正确的情况下看到)中收到的值,以反映应该插入未来文本的位置并将其返回。 This is important so the cursor is changed to the right place after the signal handler returns (this is done by gtk ). 这很重要,因此在信号处理程序返回后光标会更改到正确的位置(这由gtk完成)。 If you don't update and return then the cursor remains at position 0. 如果不更新并返回,则光标保持在位置0。

After following the suggestion of using entry.get_position() to obtain the right position value I found out that the update and return of position in my handler was being ignored by pygobject . 在遵循使用entry.get_position()获取正确位置值的建议之后,我发现pygobject正在忽略我的处理程序中的更新和返回位置。 It behaved as if I was not returning anything (the cursor remained at position 0). 它表现得好像我没有返回任何东西(光标保持在位置0)。 Setting the position inside the handler did not help, because gtk would change it back again to 0 after the handler returned. 设置处理程序内的位置没有帮助,因为gtk会在处理程序返回后将其再次更改为0。

After some further investigation I learned that the issue lies with the handling of in/out parameters in pygobject which works well in most cases but not with signals (see bug 644927 ) 在进行了一些进一步的调查之后,我了解到问题在于pygobject中输入/输出参数的处理,这在大多数情况下效果很好但不能用于信号(参见bug 644927

If you use connect to attach a handler to the signal and the signal has an in/out parameter you may not receive what you expect in the handler and even if you return a value this value will probably not be handled correctly by pygobject either. 如果使用connect将处理程序附加到信号并且信号具有输入/输出参数,则可能无法在处理程序中收到您期望的内容,即使您返回值, pygobject也可能无法正确处理此值。 Anything that depends on that value will probably not work as expected (eg advance the cursor to the new position) 依赖于该值的任何内容都可能无法按预期工作(例如,将光标前进到新位置)

There is a solution though which is to override the associated vfunc (the default handler) instead of connecting with connect() . 有一个解决方案是覆盖关联的vfunc(默认处理程序)而不是连接connect() This solution implies deriving from the base class but it does work. 这个解决方案意味着从基类派生但它确实有效。

You can use this method for input validation/transformation on Gtk.Entry . 您可以在Gtk.Entry上使用此方法进行输入验证/转换。 An example handling my use case would be: 处理我的用例的一个例子是:

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()

In this case the position parameter is received correctly and the return value is seen and used by pygobject so the cursor is correctly positioned. 在这种情况下,正确接收位置参数,并且pygobject可以看到并使用返回值,因此光标位置正确。

Important Note You have to inherit from Gtk.Editable in addition to Gtk.Entry. 重要说明除了Gtk.Entry之外,您还必须继承Gtk.Editable。 If you do not do so you will start seeing the validation or whatever you do inside do_insert_text applying to every other Gtk.Entry in your application. 如果您不这样做,您将开始看到验证或您在do_insert_text执行的任何操作, do_insert_text应用程序中的每个其他Gtk.Entry If you do not inherit you are overriding the base implementation provided by Gtk.Editable which is called by all other Gtk.Entry widgets in your application. 如果您不继承,则覆盖Gtk.Editable提供的基本实现,该实现由应用程序中的所有其他Gtk.Entry小部件调用。 By inheriting from Gtk.Editable you override only the 'local' copy of the base implementation which only applies to your custom class. 通过继承自Gtk.Editable,您只覆盖仅适用于您的自定义类的基本实现的“本地”副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM