如何在Tkinter中打印非BMP Unicode字符(例如&x1D12B;)

如何在Tkinter中打印非BMP Unicode字符(例如&x1D12B;),unicode,utf-8,tkinter,tcl,python-3.4,Unicode,Utf 8,Tkinter,Tcl,Python 3.4,注意:非BMP字符可以在的空闲状态下显示(因此,Tkinter现在也可能显示它们,因为它们都使用TCL),这是在我发布此问题一段时间后发布的。我计划在试用Python3.9之后(在安装了Xubuntu的更新版本之后)对其进行编辑。我还了解到,在IDLE中编辑这些字符可能不像其他字符那样简单 所以,今天我在制作输入某些Unicode字符的快捷方式。一切进展顺利。然后,当我决定使用这些字符时(在我的Tkinter程序中;它们甚至不会尝试进入空闲状态),目前无法显示这些字符,因为它们在Python3

注意:非BMP字符可以在的空闲状态下显示(因此,Tkinter现在也可能显示它们,因为它们都使用TCL),这是在我发布此问题一段时间后发布的。我计划在试用Python3.9之后(在安装了Xubuntu的更新版本之后)对其进行编辑。我还了解到,在IDLE中编辑这些字符可能不像其他字符那样简单



所以,今天我在制作输入某些Unicode字符的快捷方式。一切进展顺利。然后,当我决定使用这些字符时(在我的Tkinter程序中;它们甚至不会尝试进入空闲状态),目前无法显示这些字符,因为它们在Python3.4的Tkinter中应该是这样的(尽管有人提到使用代理项对可能会如何工作[在Python2.x中])。但是,您可以实现将字符转换为可显示代码并返回的方法,并在必要时调用它们。当您打印到文本小部件、复制/粘贴、文件对话框*、选项卡栏、状态栏以及其他内容时,必须调用它们

*默认的Tkinter文件对话框不允许对对话框进行很多内部工程。我制作了自己的文件对话框,部分是为了帮助解决这个问题。如果你有兴趣,请告诉我。希望将来我能在这里发布他们的代码


这些方法将超出范围的字符转换为代码,反之亦然。代码是用序号格式化的,如下所示:
{119083ū}
。括号和ū只是为了区分这是一个代码<代码>{119083ū}表示
我的答案基于@Shule answer,但提供了更多的pythnoic和易于阅读的代码。这也提供了一个真实的案例

这是将项目填充到
tkinter.Listbox
的方法。没有反向转换。此解决方案仅负责显示带有Tcl不允许字符的字符串

class MyListbox (Listbox):
    # ...
    def populate(self):
        """
        """
        def _convert65536(to_convert):
            """Converts a string with out-of-range characters in it into a
            string with codes in it.

            Based on <https://stackoverflow.com/a/28076205/4865723>.
            This is a workaround because Tkinter (Tcl) doesn't allow unicode
            characters outside of a specific range. This could be emoticons
            for example.
            """
            for character in to_convert[:]:
                if ord(character) > 65535:
                   convert_with = '{' + str(ord(character)) + 'ū}'
                   to_convert = to_convert.replace(character, convert_with)
            return to_convert

        # delete all listbox items
        self.delete(0, END)

        # add items to listbox
        for item in mydata_list:
            try:
                self.insert(END, item)
            except TclError as err:
                _log.warning('{} It will be converted.'.format(err))
                self.insert(END, _convert65536(item))
class MyListbox(列表框):
# ...
def填充(自我):
"""
"""
def-U转换器65536(到转换器):
“”“将包含超出范围字符的字符串转换为
包含代码的字符串。
基于。
这是一个解决方案,因为Tkinter(Tcl)不允许unicode
超出特定范围的字符。这可能是表情符号
例如
"""
对于转换为[:]中的字符:
如果作战需求文件(字符)>65535:
转换_为=“{'+str(ord(character))+'ū}”
to_convert=to_convert.replace(字符,转换为)
返回到_转换
#删除所有列表框项目
self.delete(0,结束)
#将项目添加到列表框
对于mydata_列表中的项目:
尝试:
自我插入(结束,项目)
除Tcl错误作为错误外:
_log.warning(“{}它将被转换。”.format(err))
自我插入(结束,65536(项目))

您是否尝试过用UTF-8编码代理项对代码单元。这并不理想,但可能有效。(U+1D12B->)Tcl目前主要假设每个字符都在U+000000…U+00FFFF范围内。这是错误的;我们知道。试试这个:
b'\xED\xA0\xB4\xED\xB4\xAB'
。但别忘了这样做是违反标准的(UTF编码规范)。这需要Tcl 8.7和Tk 8.7来修复(或者是一种在早期版本中不受支持的极不寻常的构建配置)。这个项目很复杂,;请参阅和其他关键规范文档。但是您的方法不允许将标签或按钮与这些unicode字符一起使用,是吗?这些方法不允许在任何小部件上显示超出范围的字符。它允许显示代表这些字符的代码,这样您就可以处理带有这些字符的文本(这样您就可以正确地保存文本,这样它就不会崩溃等等)。这段代码在文本编辑器中可能是最有用的(因此您可以使用超出范围的字符实际打开和编辑文件;它不太适合阅读)。您可以在按钮和标签小部件上显示这些代码,因为这些代码不包含超出范围的字符,但这可能不是您想要的。这些方法只是将超出范围的字符转换为代码,反之亦然,因此您可以在无法显示字符的地方显示代码(例如,在小部件中),并将它们转换回可能的字符(例如在保存的txt文件、剪贴板或非Tkinter Python代码中)。如何在实际代码中实现这一点?我的意思是我必须检查我放在Tkinter GUI中的每个字符串吗?这将是一个混乱的局面,并导致大量尝试,除了块…@buhtz在打印到tkinter小部件之前,请将文本转换为将在tkinter小部件中打印的字符(使用
convert65536
)。当您从小部件获取要操作的文本时,使用
convert65536back
将其转换为实际字符。您不需要调用
parse65536