如何格式化 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.Entry
和Gtk.Editable
进行双重继承?
这是为了避免覆盖 gtk.Editable 实现。请参阅此问题的答案***.com/questions/38815694/…,底部的注释对此进行了更详细的说明。以上是关于如何格式化 Gtk.Entry 中的条目的主要内容,如果未能解决你的问题,请参考以下文章
如何将 GtkEntry 小部件设置为仅使用 C 接受数字?
在 Gtk::Entry 更改之前,我应该捕获啥信号来获取它的文本?