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

Posted

技术标签:

【中文标题】如何格式化 Gtk.Entry 中的条目【英文标题】:How to format the entries in Gtk.Entry 【发布时间】:2017-02-25 18:19:51 【问题描述】:

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

【问题讨论】:

你可以试试validator。这个旧的 (2006) discussion 也很有用。 【参考方案1】:

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 绑定中的返回参数。这个question 提供了有关该错误的详细信息。正如接受的答案中所建议的那样,您可以像这样覆盖默认信号处理程序:

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.验证码

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

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

【讨论】:

很好,你的例子有效。但我收到了警告:gtkentry_with_formation.py:62: Warning: g_value_get_int: assertion 'G_VALUE_HOLDS_INT (value)' failed Gtk.main() 很高兴它有效。该警告是由于处理 Python 中的位置参数时的错误。看到这个问题:***.com/questions/38815694/… 抱歉回到那个问题。既然Gtk.Entry继承自Gtk.Editable,为什么还要对Gtk.EntryGtk.Editable进行双重继承? 这是为了避免覆盖 gtk.Editable 实现。请参阅此问题的答案***.com/questions/38815694/…,底部的注释对此进行了更详细的说明。

以上是关于如何格式化 Gtk.Entry 中的条目的主要内容,如果未能解决你的问题,请参考以下文章

如何使用格式化数组之类的独白记录多行条目?

如何将 GtkEntry 小部件设置为仅使用 C 接受数字?

在 Gtk::Entry 小部件中强制输入数字

在 Gtk::Entry 更改之前,我应该捕获啥信号来获取它的文本?

在 Rails 中使用嵌套表单 - 如何使显示页面根据用户想要的呈现数量以表格格式显示每个新条目?

如何从数据框中提取值以用于条件格式,同时一次将其应用于某些选择类别或数据条目?