Как включить поддержку эмодзи в приложениях Tkinter? - PullRequest
0 голосов
/ 07 сентября 2018

Я внедрил это приложение для чата Python от Саураба Чатурведи, чтобы начать изучать, как работает сеть. Приложение простое и использует модуль Tkinter.

Мне бы хотелось расширить функциональность приложения, позволив пользователям печатать смайлики в окне сообщений и отображать их как смайлики в списке сообщений при отправке сообщений. Например, если пользователь вводит «:)» в окне сообщения, оно должно отображаться как ?.

До сих пор я исследовал, как включить поддержку эмодзи в приложениях Tkinter. Я встречал Отображение смайликов / символов в Python с использованием tkinter lib , но я не думаю, что это напрямую решает мою проблему. Я не уверен, что в данный момент собираюсь решить эту проблему правильным образом.

Если это поможет, я запускаю Windows 10 и использую Python 3. И вы должны иметь возможность реализовать приложение чата, запустив два сценария (сервер и клиент), описанные в Статья Саураба, (Кроме того, потенциально связанная проблема заключается в том, что эмодзи не отображаются должным образом в моем интерпретаторе Python 3. Например,

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

приводит к двум вопросительным знакам в прямоугольниках, а не к).)

Любые предложения о том, как я могу включить эмодзи в списке сообщений?


EDIT:

Как следует из комментария @ abarnert ниже, стоит упомянуть, что эта проблема не возникла из-за моей попытки использовать библиотеку emoji для перевода пользовательского ‘:)’ в emoji. Скорее, первоначальный вопрос возник, потому что я не был уверен, как выполнить рендеринг «:)» в виде «?» в приложении на основе Tkinter, во-первых.

1 Ответ

0 голосов
/ 08 сентября 2018

У вас здесь несколько проблем, и я не уверен, на какой вы застряли, поэтому я постараюсь охватить все.


Во-первых, как вы "смоделируете" строку?

Вам необходимо точно определить, что это означает - какой набор входов вы сопоставляете с какими выходами, если :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)?

Эта часть является дубликатом вопроса, который вы связали . В Tkinter есть известная ошибка, которая по-прежнему существует на 3.7, и самый известный обходной путь - это некрасиво.

Но, хотя это может быть безобразно , это не так трудно . Ответ на этот вопрос связан с другим вопросом , где Martijn Pieters предоставляет замечательную функцию with_surrogates, которую вы можете просто вызвать в своей эмодифицированной строке.

Если вам нужно что-то простое, но хакерское - которое сделает сервер практически бесполезным с чем-либо , но глючным клиентом 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)
...