如何在 Tkinter 应用程序中启用对表情符号的支持?

How can I enable support for emoji in Tkinter applications?

我已经实现了 Saurabh Chaturvedi 的这个 Python chat application,开始学习网络的工作原理。该应用程序很简单,并使用了 Tkinter 模块。

我想通过允许用户在消息框中键入表情符号并在他们发送消息时将它们呈现为消息列表中的表情符号来扩展应用程序的功能。例如,如果用户在消息框中键入“:)”,它应该呈现为 .

到目前为止,我已经研究了如何在 Tkinter 应用程序中启用对表情符号的支持。我遇到了 Displaying emojis/symbols in Python using tkinter lib,但我不认为它直接解决了我的问题。我不确定我目前是否正在以正确的方式解决这个问题。

如果有任何帮助,我是 运行 Windows 10 并使用 Python 3。您应该能够通过 运行 实现聊天应用程序Saurabh’s article 中描述的两个脚本(服务器和客户端)。 (此外,一个可能相关的问题是表情符号在我的 Python 3 解释器中没有正确显示。例如,

>>> import emoji
>>> print(emoji.emojize(":thumbs_up:"))

在方框中显示两个问号,而不是 .)

关于如何在消息列表中呈现表情符号有什么建议吗?


编辑:

根据下面@abarnert 的评论,值得一提的是,这个问题确实 而不是 源于我尝试使用表情符号库将用户的“:)”翻译成表情符号。相反,最初的问题出现是因为我不确定如何像在基于 Tkinter 的应用程序中一样执行“:)”的渲染。

你这里有多个问题,我不确定你卡在哪个问题上,所以我会尽力解决所有问题。


首先,你如何"emojify"一个字符串?

您需要准确定义这意味着什么——您将哪些输入集映射到哪些输出,如果 :8 是一个输入是否意味着 80:80 应该将 :8 在中间变成表情符号(如果不是,说明为什么不的规则到底是什么)等

那么实现起来并不难——无论您是循环 s.split() 还是更复杂的 re.finditer,您的规则是否需要考虑当前模式之外的上下文,等等。取决于您选择的规则。

无论如何,PyPI 上有许多库对此进行了多种变体,您已经找到了至少一个,emoji。所以我假设这个问题已经解决了。


接下来,您将它挂接到您的代码中的什么位置?

据推测,只要用户提交聊天消息,您就会触发一个回调。我不知道你是怎么设置的,但这并不重要,所以让我们举一个简单的例子:

def callback(widget):
    msg = widget.get()
    conn.sendall(msg)
    msglog.append(f'>>> {msg}')

此函数从消息输入小部件中获取字符串内容,然后将该字符串发送到服务器,并将其显示在消息日志小部件中。所以,您需要做的就是:

def callback(widget):
    msg = widget.get()
    msg = emojify(msg)
    conn.sendall(msg)
    msglog.append(f'>>> {msg}')

第三,你如何处理 tkinter 不能正确处理表情符号(和其他非 BMP 字符)的事实?

这部分是 the question you linked 的翻版。 Tkinter 有一个已知的错误,它在 3.7 中仍然存在,而最著名的解决方法有点丑陋。

但是,虽然它可能 丑陋 ,但并不 。该问题的答案链接到 ,其中 Martijn Pieters 提供了一个很好的 with_surrogates 函数,您可以在表情符号字符串上调用它。

如果你想要一些简单但 hacky 的东西 - 这将使服务器基本上无法使用任何东西 一个有问题的 tkinter 客户端 - 你可以在通过网络发送消息之前这样做:

def callback(widget):
    msg = widget.get()
    msg = emojify(msg)
    tkmsg = with_surrogates(msg)
    conn.sendall(tkmsg)
    msglog.append(f'>>> {tkmsg}')

但更简洁的解决方案是将它们作为正确的 UTF-8 通过网络发送,并且仅对其进行代理以进行显示,两者均在此处:

def callback(widget):
    msg = widget.get()
    msg = emojify(msg)
    conn.sendall(msg)
    tkmsg = with_surrogates(msg)
    msglog.append(f'>>> {tkmsg}')

…在接收其他用户消息的代码中:

def on_msg(msg):
    tkmsg = with_surrogates(msg)
    msglog.append(tkmsg)