如何格式化 Gtk.Entry 中的条目

How to format the entries in Gtk.Entry

例如,电话格式为+999 99 9999-9999。也就是说,GtkEntry 会在用户键入时自动添加字符(+、[space] 和 -)。

1。如何制作入口验证器?

为了在 gtk 中执行入口验证器,您需要将 insert_text 信号连接到验证方法。它是这样的:

class EntryWithValidation(Gtk.Entry):
    """A Gtk.Entry with validation code"""

    def __init__(self):
        Gtk.Entry.__init__(self)
        self.connect("insert_text", self.entryInsert)

    def entryInsert(self, entry, text, length, position):
        # Called when the user inserts some text, by typing or pasting.

        # The `position` argument is not working as expected in Python
        pos = entry.get_position() 

        # Your validation code goes here, outputs are new_text and new_position (cursor)

        if new_text:
            # Set the new text (and block the handler to avoid recursion).
            entry.handler_block_by_func(self.entryInsert)
            entry.set_text(new_text)
            entry.handler_unblock_by_func(self.entryInsert)

            # Can't modify the cursor position from within this handler,
            # so we add it to be done at the end of the main loop:
            GObject.idle_add(entry.set_position, new_pos)

        # We handled the signal so stop it from being processed further.
        entry.stop_emission("insert_text")

此代码将生成警告:Warning: g_value_get_int: assertion 'G_VALUE_HOLDS_INT (value)' failed Gtk.main() 因为无法处理 Gtk 信号的 Python 绑定中的 return 个参数。 提供了有关错误的详细信息。正如接受的答案中所建议的那样,您可以像这样覆盖默认信号处理程序:

class EntryWithValidation(Gtk.Entry, Gtk.Editable):

    def __init__(self):
        super(MyEntry, self).__init__()

    def do_insert_text(self, new_text, length, position):

        # Your validation code goes here, outputs are new_text and new_position (cursor)

        if new_text:
            self.set_text(new_text)
            return new_position
        else:
            return position

2.The验证码

您现在需要编写验证代码。这有点繁琐,因为我们需要将光标放在插入文本的末尾,但我们可能在格式化时添加了一些额外的字符。

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GObject

class TelNumberEntry(Gtk.Entry):
    """A Gtk.Entry field for phone numbers"""

    def __init__(self):
        Gtk.Entry.__init__(self)
        self.connect("insert_text", self.entryInsert)

    def entryInsert(self, entry, text, length, position):

        pos = entry.get_position() 
        old_text = entry.get_text()

        # Format entry text

        # First we filter digits in insertion text
        ins_dig = ''.join([c for c in text if c.isdigit()]) 
        # Second we insert digits at pos, truncate extra-digits
        new_text = ''.join([old_text[:pos], ins_dig, old_text[pos:]])[:17] 
        # Third we filter digits in `new_text`, fill the rest with underscores
        new_dig = ''.join([c for c in new_text if c.isdigit()]).ljust(13, '_')
        # We are ready to format 
        new_text = '+{0} {1} {2}-{3}'.format(new_dig[:3], new_dig[3:5], 
                                               new_dig[5:9], new_dig[9:13]).split('_')[0] 

        # Find the new cursor position

        # We get the number of inserted digits
        n_dig_ins = len(ins_dig) 
        # We get the number of digits before
        n_dig_before = len([c for c in old_text[:pos] if c.isdigit()])
        # We get the unadjusted cursor position
        new_pos = pos + n_dig_ins

        # If there was no text in the entry, we added a '+' sign, therefore move cursor
        new_pos += 1 if not old_text else 0 
        # Spacers are before digits 4, 6 and 10
        for i in [4, 6, 10]:
            # Is there spacers in the inserted text?
            if n_dig_before < i <= n_dig_before + n_dig_ins: 
                # If so move cursor
                new_pos += 1

        if new_text:
            entry.handler_block_by_func(self.entryInsert)
            entry.set_text(new_text)
            entry.handler_unblock_by_func(self.entryInsert)

            GObject.idle_add(entry.set_position, new_pos)

        entry.stop_emission("insert_text")

if __name__ == "__main__":
    window = Gtk.Window()
    window.connect("delete-event", Gtk.main_quit)
    entry = TelNumberEntry()
    window.add(entry)
    window.show_all()
    Gtk.main()