Korean IME problem in ttk.Entry

Hello!
I’m a college student who wants to be a Python engineer, attending a Korean university.
Working on the project, and I came here because there was a problem with themed tkinter.
There is a problem with the Korean IME in the ttk.Entry object.

Hangul(Korean) creates words from a combination of letters(initial, medial, finale).
I’d like to dynamically print those letters with get() method whenever I type that letters into ttk.Entry
But only when ttk.Entry enters one completed letter, the letter is printed.

Desired example)
input ㅎ >>> print console: ㅎ
input ㅏ >>> print console: 하
input ㄴ >>> print console: 한

Actual action)
input ㅎ >>> print console:
input ㅏ >>> print console:
input ㄴ >>> print console:
input whitespce >>> print console: 한

To look up that using event(type: QInputMethodEvent) in the QLineEdit of PyQt5 with event.preeditString(), the action I want will be implemented!
However, I understand that tkinter and PyQt5 are difficult to mix using, because of different event loops.

I’m already been working on the project quite a bit, so hard to change the entire code to PyQt5.
I would like to implement such as preeditString() only in certain parts…
What are the options? Only way to change all code…? :frowning:

widgets.py

class Entry(ttk.Entry):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.bind("<Control-a>", self.select_all)
        
    def select_all(self, event):
        event.widget.select_range(0, "end")
        event.widget.icursor("end")
        return "break"


class DebounceEntry(Entry):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.bind("<Key>", self._on_key)
        
        self._on_key_func = None
        self._after_id = None
        self._debounce_ms = 200
        
    def _on_key(self, event=None):
        if self._on_key_func is None:
            return
        
        if self._after_id is not None:
            self.after_cancel(self._after_id)
        self._after_id = self.after(self._debounce_ms, self._on_key_func, event)
    
    def bind_on_key(self, func, debounce_ms=None):
        self._on_key_func = func
        if debounce_ms is not None:
            self._debounce_ms = debounce_ms

filters.py

import logging
import tkinter as tk
from tkinter import ttk

from playground.ui.widgets import DebounceEntry
from playground.korean_regexp.functions import (
    get_reg_exp as re_korean, eng_to_kor, kor_to_eng
)

logger = logging.getLogger(__name__)


class FiltersFrame(ttk.LabelFrame):
    def __init__(self, parent, play_tab, function_callback=None):
        logger.debug("Initailizing Playground FiltersFrame")
        super().__init__(parent, text="Filters")
        self.parent = parent
        self.play_tab = play_tab
        self.function_callback = function_callback
        
        self.name_label = ttk.Label(self, text="Course Name:")
        self.name_label.grid(row=0, column=0, padx=(5, 0), pady=(5, 5), sticky="w")
        # Using here!
        self.name = DebounceEntry(self, width="30")
        self.name_last_seen = ""
        self.name.bind_on_key(self.on_name_key)
        self.name.grid(row=0, column=1, padx=(5, 0), pady=(5, 5), sticky="w")

        self.name.bind("<KeyRelease>", self.IME_test)
        
    def selected_command(self, _event=None):
        self.play_tab.packs_frame.render_packs()
    
    def on_name_key(self, _event=None):
        name = self.name.get().strip()
        if name != self.name_last_seen:
            self.name_last_seen = name
            self.play_tab.packs_frame.render_packs()
            
    def IME_test(self, event):
        search_term = self.name.get()
        print(search_term)

I’m not sure how the ttk console works, or if this will work with unicode code points (especially if the letters are multi-code point grapheme clusters. But by default you could save currently printed characters in a buffer, and preppend the character with ‘\b’ * its length, to delete or move the cursor back and overwrite them. When some function detects the end of a word, flush the buffer end, print the final word, and bump the cursor over.

Thanks for the good comments. But unlike other Unicode characters, in particular Hangul is the only character that combines a consonant. So if you delete a character while typing or move the cursor, it is impossible to continue typing from that character. And in tkinter, for some reason, until one combined character is completed, the key was pressed, but it seems that there is no input…

Let me know if you need another code to think about! Thanks again for your comments