Как вставить специальные символы в tkinter - PullRequest
0 голосов
/ 02 апреля 2019

Я создаю графический интерфейс с tkinter, в этом графическом интерфейсе есть некоторые виджеты ввода, которые пользователь должен заполнить, а входные данные будут сохранены в файле.Проблема, с которой я сталкиваюсь, заключается в том, что пользователь не может вставлять специальные символы, такие как эмодзи, в эти виджеты ввода.

Я нашел несколько способов их отображения ...:

.... но я не нашел ничего о моей проблеме.
Я думал о ее решении, отображая рядом с записями таблицу с смайликами и относительным кодом, чтобы вставить его в запись вместо прямой вставки смайликов, так что-товот так ...:
1: ? 2: ? 3: ? 4: ?
... и попросить пользователя вставить 1, 2, 3 или 4 вместо смайликов, но я не думаю,что это хороший способ решить проблему.

Из моего исследования я понял, что проблема в модуле tkinter, и мне было интересно, есть ли способ ее преодоления.

# -*- coding: utf-8 -*-
from tkinter import *

def sumbit():
    print(var.get())

root = Tk()
root.tk.call('encoding', 'system', 'utf-8')

var = StringVar()
entry = Entry(root, textvariable=var)
entry.pack()
button = Button(root, text="sumbit", command=sumbit)
button.pack()

root.mainloop()

Это пример проблемы, у меня есть окнос виджетом Entry, где пользователь может вставить смайлик, но если пользователь вставляет смайлик, код вызывает следующую ошибку:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Program Files\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
    return self.func(*args)
  File "C:/Users/mcara/PycharmProjects/1/python/1.py", line 5, in sumbit
    print(var.get())
  File "C:\Program Files\Python37-32\lib\tkinter\__init__.py", line 484, in get
    value = self._tk.globalgetvar(self._name)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xed in position 0: invalid continuation byte

Я работаю с Windows и Pyton 3.7

1 Ответ

0 голосов
/ 03 апреля 2019

Я работал над этой проблемой, как это сейчас:

# -*- coding: utf-8 -*-
from tkinter import *
import tkinter.font as tkFont

# Dict with all the emojis
# it is made in this format -->    EMOJI_NAME: EMOJI_SURROGATE_PAIR
emoji_dict = {
    "GRINNING_FACE": '\ud83d\ude00',
    "GRINNING_FACE_WITH_BIG_EYES": '\ud83d\ude03',
    "GRINNING_FACE_WITH_SMILING_EYES": '\ud83d\ude04',
    "BEAMING_FACE_WITH_SMILING_EYES": '\ud83d\ude01',
    "GRINNING_SQUINTING_FACE": '\ud83d\ude06',
    "GRINNING_FACE_WITH_SWEAT": '\ud83d\ude05',
    "LAUGHING_ON_THE_FLOOR": '\ud83e\udd23',
    "TEARS_OF_JOY": '\ud83d\ude02',
    "SMILING_FACE_SLIGHTLY": '\ud83d\ude42',
    "UPSIDE-DOWN_FACE": '\ud83d\ude43',
    "WINKING_FACE": '\ud83d\ude09',
}

emoji_num_name = dict()
emoji_name_num = dict()
counter = 0
for key in emoji_dict:
    emoji_num_name[counter] = key
    emoji_name_num[key] = counter
    counter += 1


def search(text):
    for widget in emoji_frame.winfo_children():
        if isinstance(widget, Button):
            widget.destroy()

    emoji_name_list = list(emoji_dict.keys())
    emoji_name_list.sort()
    if text == "" or text == " ":
        creates_emojis()
    else:
        x = 10
        y = 0
        for emoji_name in emoji_name_list:
            if emoji_name.startswith(text):
                emoji_code = emoji_dict[emoji_name]
                code_ = emoji_name_num[emoji_name]
                emoji_button = Button(emoji_frame, text=emoji_code, borderwidth=0, font=customFont)
                emoji_button.place(x=x, y=y)
                emoji_button.bind("<Button-1>", lambda event, code=code_, var=sumbit_var: insert_emoji(var, ":-" + str(code) + "-:"))

                if x <= 150:
                    x += 30
                else:
                    x = 10
                    y += 30
        emoji_frame.configure(widt=200, height=y+60)


def insert_emoji(var, code):
    var.set(var.get() + code)


def creates_emojis():
    x = 10
    y = 0
    for emoji_name in emoji_dict:
        emoji_code = emoji_dict[emoji_name]
        code_ = emoji_name_num[emoji_name]
        emoji_button = Button(emoji_frame, text=emoji_code, borderwidth=0, font=customFont)
        emoji_button.place(x=x, y=y)
        emoji_button.bind("<Button-1>", lambda event, code=code_, var=sumbit_var: insert_emoji(var, ":-" + str(code) + "-:"))

        if x <= 150:
            x += 30
        else:
            x = 10
            y += 30
    emoji_frame.configure(widt=200, height=y+60)


def sumbit(text):
    text = text.split(":-")
    for index in range(len(text)):
        word = text[index]
        word = word.split("-:")
        for index_ in range(len(word)):
            little_word = word[index_]
            if little_word.isdigit():
                emoji_name = emoji_num_name[int(little_word)]
                emoji = emoji_dict[emoji_name]
                word[index_] = emoji
        text[index] = "".join(word)
    text = "".join(text)
    text = text.encode('utf-16', 'surrogatepass').decode('utf-16')
    print(text)


root = Tk()
root.tk.call('encoding', 'system', 'utf-8')
root.configure(width=500, height=500)
font = "Courier"
customFont = tkFont.Font(family=font, size=14)

emoji_frame = LabelFrame(text="emojis")
emoji_frame.place(x=10, y=60)

search_var = StringVar()
search_entry = Entry(root, textvariable=search_var)
search_entry.place(x=10, y=10)
search_button = Button(root, text="search", command=lambda: search(search_var.get().upper()))
search_button.place(x=10, y=30)
displat_all_button = Button(root, text="display all", command=lambda: creates_emojis())
displat_all_button.place(x=60, y=30)

sumbit_var = StringVar()
sumbit_entry = Entry(root, textvariable=sumbit_var)
sumbit_entry.place(x=200, y=10)
sumbit_button = Button(root, text="sumbit", command=lambda: sumbit(sumbit_var.get()))
sumbit_button.place(x=200, y=30)
creates_emojis()

root.mainloop()

Это работающий пример того, что я сделал, я создал своего рода таблицу, в которую вы можете вставить столько смайликов, сколько захотите (отредактировав emoji_dict и вставив смайлики, которые вы хотите) и вернуть результат в utf-8.

Для поиска emoji surrogate pair я использовал код

import re

_nonbmp = re.compile(r'[\U00010000-\U0010FFFF]')

def _surrogatepair(match):
    char = match.group()
    assert ord(char) > 0xffff
    encoded = char.encode('utf-16-le')
    return (
        chr(int.from_bytes(encoded[:2], 'little')) +
        chr(int.from_bytes(encoded[2:], 'little')))

def with_surrogates(text):
    return _nonbmp.sub(_surrogatepair, text)


emoji_dict = {
    "Grinning_Face": u'\ud83d\ude00',
    "Grinning_Face_With_Big_Eyes": u'\ud83d\ude03',
    "Grinning_Face_With_Smiling_Eyes": u'\ud83d\ude04',
    "Beaming_Face_With_Smiling_Eyes": u'\ud83d\ude01',
    "Grinning_Squinting_Face": u'\ud83d\ude06',
    "Grinning_Face_With_Sweat": u'\ud83d\ude05',
    "Laughing_on_the_Floor": u'\ud83e\udd23',
    "Tears_of_Joy": u'\ud83d\ude02',
    "Smiling_Face_Slightly": u'\ud83d\ude42',
    "Upside-Down_Face": u'\ud83d\ude43',
    "Winking_Face": u'\ud83d\ude09',
}

emoji_list =[ "?", "?", "?", "?", "?", "?", "?", "?", "?",  "?", "?", ]


for emoji in emoji_list:
    print(repr(_nonbmp.sub(_surrogatepair, emoji)))

вы можете найти его на этот вопрос Python: Найти эквивалентную суррогатную пару из не-BMP символа Юникода

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...