As you pointed out, your code works as is on Windows (tested on Windows 10), however for macOS, the following workaround should work:
- Convert the encoding of the Emoji from UTF-32 to UTF-16 (No loss of functionality occurs since UTF-16 is a variable length encoding, hence any code point that can be represented in UTF-32 can be converted to UTF-16 only in these case where modern Emojis are involved, the UTF-16 encoded value will use 32 bits, same as UTF-32, meaning it should support Unicode v11 character representation).
- Pass the resulting string to the embedded Tcl/Tk interpreter.
In UTF-16, characters in ranges U+0000—U+D7FF and U+E000—U+FFFD are stored as a single 16 >bits unit. Non-BMP characters (range U+10000—U+10FFFF) are stored as “surrogate pairs”, >two 16 bits units: an high surrogate (in range U+D800—U+DBFF) followed by a low surrogate (in range U+DC00—U+DFFF).
For Tcl to perform the substitution of a unicode-escaped string (with its character/emoji representation), the string itself must be of the form "\uXXXX"
or "\uXXXX\uXXXX"
.
The chipmunk Emoji's encoding must be converted to UTF-16 => "\ud83d\udc3f"
# The tcl/tk code
set chipmunk "\ud83d\udc3f"
pack [set c [canvas .c -highlightcolor blue -highlightbackground black -background yellow]] -padx 4cm -pady 4cm -expand 1 -fill both
set text_id [$c create text 0 0 -text $chipmunk -font [list * 180]]
$c moveto $text_id 0 0
The equivalent code in python, will have at some point to bypass tkinter and issue direct tcl commands to the embedded/linked interpreter
import tkinter as tk
# the top-level window
top = tk.Tk()
# the canvas
c = tk.Canvas(top, highlightcolor = 'blue', highlightbackground = 'black', background = 'yellow')
# create the text item, with placeholder text
text_id = c.create_text(0,0, font = '* 180', text = 'to be replaced')
# pack it
c.pack(side = 'top', fill = 'both' , expand = 1, padx = '4c' , pady = '4c')
# The 'Bypassing' aka issuing tcl/tk calls directly
# For Tk calls use => c.tk.cal(...), we will not use this.
# For bare Tcl => c.tk.eval(...)
# chipmunk in UTF-16 (in this instance it is using 32-bits to represent the codepoint)
# as a raw string
chipmunk = r"\ud83d\udc3f"
# create another variable in tcl/tk
c.tk.eval('set the_tcl_chipmunk {}'.format(chipmunk))
# set the text_id item's -text property/option as the value of variable the_tcl_chipmunk, gotten by calling the tcl's set command
c.tk.eval( '{} itemconfig {} -text [set the_tcl_chipmunk]'.format( str(c), text_id ) )
# Apparently a hack to get the chipmunk in position
c.tk.eval( '{} moveto {} 0 0'.format( str(c), text_id ) )
# the main gui event loop
top.mainloop()
Getting the UTF-16 of chipmunk
There are two avenues you could pursue:
Getting it from a website, I use fileformat.info all the time chipmunk on fileformat.info and copy value shown for C/C++/Java source code
Doing the conversion from UTF-32 to UTF-16 in Python
# A UTF-32 string, since it's of the form "\UXXXX_XXXX" ( _ is not part of the syntax, a mere visual aide fo illustrative purposes)
chipmunk_utf_32 = '\U0001F43F'
# convert/encode it to UTF-16 (big endiann), to get a bytes object
chipmunk_utf_16 = chipmunk_utf_32.encode('utf-16-be')
# obtain the hex representation
chipmunk_utf_16 = chipmunk_utf_16.hex()
#format it to be an escaped UTF-16 tcl string
chipmunk = '\\u{}\\u{}'.format(chipmunk_utf_16[0:4], chipmunk_utf_16[4:8])
EDIT: The whole script
import tkinter as tk
# A UTF-32 string, since it's of the form "\UXXXX_XXXX" ( _ is not part of the syntax, a mere visual aide fo illustrative purposes)
chipmunk_utf_32 = '\U0001F43F'
# convert/encode it to UTF-16 (big endiann), to get a bytes object
chipmunk_utf_16 = chipmunk_utf_32.encode('utf-16-be')
# obtain the hex representation
chipmunk_utf_16 = chipmunk_utf_16.hex()
#format it to be an escaped UTF-16 tcl string
chipmunk = '\\u{}\\u{}'.format(chipmunk_utf_16[0:4], chipmunk_utf_16[4:8])
# the top-level window
top = tk.Tk()
# the canvas
c = tk.Canvas(top, highlightcolor = 'blue', highlightbackground = 'black', background = 'yellow')
# create the text item, with placeholder text
text_id = c.create_text(0,0, font = '* 180', text = 'to be replaced')
# pack it
c.pack(side = 'top', fill = 'both' , expand = 1, padx = '4c' , pady = '4c')
# The 'Bypassing' aka issuing tcl/tk calls directly
# For Tk calls use => c.tk.cal(...), we will not use this.
# For bare Tcl => c.tk.eval(...)
# chipmunk in UTF-16 (in this instance it is using 32-bits to represent the codepoint)
# as a raw string
#print(chipmunk)
#chipmunk = r"\ud83d\udc3f"
# create another variable in tcl/tk
c.tk.eval('set the_tcl_chipmunk {}'.format(chipmunk))
# set the text_id item's -text property/option as the value of variable the_tcl_chipmunk, gotten by calling the tcl's set command
c.tk.eval( '{} itemconfig {} -text [set the_tcl_chipmunk]'.format( str(c), text_id ) )
# Apparently a hack to get the chipmunk in position
c.tk.eval( '{} moveto {} 0 0'.format( str(c), text_id ) )
top.mainloop()
text='Hello'
and check if it displays "Hello" twice. – Tilneyconda install -c conda-forge tk
andconda install -c conda-forge/label/cf201901 tk
commands. – Tilney\uD83D\uDC3F
? – NephrosisPIL
to generate this emoji,and usePIL.ImageTk
to put it on the canvas? – Belongtext=' \U0001F43F'
), but this loophole doesn't work for more complex emoji that are more than one 32-bit codepoint, like 🏴 – Mirilla