How can I enable support for emoji in Tkinter applications? How can I enable support for emoji in Tkinter applications? tkinter tkinter

How can I enable support for emoji in Tkinter applications?


You have multiple problems here, and I'm not sure which one you're stuck on, so I'll try to cover everything.


First, how do you "emojify" a string?

You need to define exactly what that means—what set of inputs do you map to what outputs, is if :8 is an input does that mean 80:80 should turn the :8 in the middle into an emoji (and, if not, what exactly is the rule that says why not), etc.

Then it's not that hard to implement—whether you're looping over s.split() or a more complicated re.finditer, whether your rules need to take context outside the current pattern into account, etc. depends on what rules you chose.

At any rate, there are a number of libraries on PyPI that do a variety of variations on this, and you already found at least one, emoji. so I'll assume this problem is solved.


Next, where do you hook that into your code?

Presumably, you have a callback that gets fired whenever the user submits a chat message. I don't know exactly how you set that up, but it doesn't really matter, so let's just make up a simple example:

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

This function gets the string contents out of a message input widget, and then both sends that string to the server, and displays it in a message log widget. So, all you need to do is:

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

Third, how do you deal with the fact that tkinter can't handle emoji (and other non-BMP characters) correctly?

This part is a dup of the question you linked. Tkinter has a known bug, which is still there as of 3.7, and the best known workaround is kind of ugly.

But, while it may be ugly, it's not that hard. The answer to that question links to another question, where Martijn Pieters provides a nice with_surrogates function that you can just call on your emojified string.

If you want something simple but hacky—which will make the server basically useless with anything but a buggy tkinter client—you can do that before sending the messages over the wire:

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

But a cleaner solution is to send them over the wire as proper UTF-8, and only surrogatize it for display, both here:

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

… and in the code that receives messages from other users:

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