[PYTHON] Die Geschichte der Anzeige der Zeichen in Kivys japanischer Eingabe

Im Juli 2018 wurde die neueste Version von Kivy (1.10.1) veröffentlicht. Hier ist die IME-Anzeige Die Content-Pull-Anforderung wurde übernommen, IME funktioniert und die eingegebenen Japaner werden angezeigt.

Inhalt

Obwohl es sich um Pythons GUI-Bibliothek "Kivy" handelt, gibt es ein Problem, dass Japanisch (IME) während der japanischen Eingabe in der Texteingabe in einer Windows / MacOS-Umgebung nicht angezeigt wird. Dieses Mal haben wir den Grund untersucht, warum es nicht angezeigt wurde, und Maßnahmen ergriffen, um es sichtbar zu machen. Das Überprüfungsbetriebssystem ist Windows.

Warum Japanisch nicht angezeigt wird

Zunächst realisiert Kivy verschiedene Funktionen der Bibliothek, wie z. B. OpenGL in der unteren Ebene, wie unten gezeigt.

architecture.png

Unter diesen wird die Zeicheneingabe unter Verwendung von SDL realisiert.

Realisierung der Texteingabe in SDL

Die Quelle stammt aus Tutorial der SDL-Texteingabe.


    SDL_StartTextInput();
    while (!done) {
        SDL_Event event;

        if (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    /*Ende*/
                    done = SDL_TRUE;
                    break;
                case SDL_TEXTINPUT:
                    /*Fügen Sie am Ende des Textes neuen Text hinzu*/
                    strcat(text, event.text.text);
                    break;
                case SDL_TEXTEDITING:
                    /*
Aktualisieren Sie nicht konvertierten Text.
Aktualisieren Sie die Cursorposition.
Konvertieren Sie die Länge der Auswahl(wenn möglich).
                    */
                    composition = event.edit.text;
                    cursor = event.edit.start;
                    selection_len = event.edit.length;
                    break;
            }
        }
        Redraw();
    }

}

Wenn Sie sich das ansehen, können Sie sehen, dass das Ereignis "SDL_TEXTINPUT" bei der Eingabe von Zeichen und das Ereignis "SDL_TEXTEDITING" beim Betrieb von IME ausgegeben wird.

Informationen zum Empfangen von Ereignissen von SDL in Kivy

Schauen wir uns vor diesem Hintergrund den [Github-Quellcode] von kivy an (https://github.com/kivy/kivy). Es ist core / window / _window_sdl2.pyx, Das das Ereignis von SDL empfängt und verarbeitet. pyx) "Umfrage" -Funktion. Die Poll-Funktion empfängt das Ereignis von SDL und gibt das Ereignis mit der Funktion _event_loop von window_sdl2.py aus. Wenn man sich den Code der "Umfrage" -Funktion ansieht, sieht es so aus:

    def poll(self):
        cdef SDL_Event event
        cdef int rv

        with nogil:
            rv = SDL_PollEvent(&event)
        if rv == 0:
            return False

        action = None
        if event.type == SDL_QUIT:
            return ('quit', )
        elif event.type == SDL_DROPFILE:
            return ('dropfile', event.drop.file)
        elif event.type == SDL_MOUSEMOTION:
            x = event.motion.x
            y = event.motion.y
            return ('mousemotion', x, y)
            
~ Ausgelassen ~

        elif event.type == SDL_KEYDOWN or event.type == SDL_KEYUP:
            action = 'keydown' if event.type == SDL_KEYDOWN else 'keyup'
            mod = event.key.keysym.mod
            scancode = event.key.keysym.scancode
            key = event.key.keysym.sym
            return (action, mod, key, scancode, None)
        elif event.type == SDL_TEXTINPUT: ★
            s = event.text.text.decode('utf-8')
            return ('textinput', s)
        else:
            #    print('receive unknown sdl event', event.type)
            pass

Wie Sie sehen können, ** gibt es die Zeichen zurück, die als Antwort auf das Ereignis "SDL_TEXTINPUT" eingegeben wurden, wenn die Zeicheneingabe bestätigt wurde, und das Ereignis "Texteingabe", wird jedoch während der Eingabe (IME) von SDL ausgegeben. Als Reaktion auf das Ereignis "SDL_TEXTEDIT" muss keine Verarbeitung durchgeführt werden. ** ** ** Dies ist der Grund, warum Zeichen während der Eingabe von Japanisch nicht angezeigt werden.

Ermöglichen Sie die Anzeige der in Japan eingegebenen Zeichen

Jetzt, wo ich den Grund kenne, werde ich darüber nachdenken, was ich als nächstes tun soll. In Bezug auf die Verarbeitung denke ich, dass das folgende Verfahren zuerst hinzugefügt werden sollte.

Über die eigentliche Quelle

@souan hat Pull Request zu kivy selbst hinzugefügt. Als Beispielprogramm wird es auch auf Github platziert.

Beispiel für die Ausgabe eines Textedit-Ereignisses: https://github.com/Adachinski/kivy/tree/textedit_patch_smple Anwendungsbeispiel: https://github.com/Adachinski/kivy_textedit_sample

Im Folgenden geht es um die eigentliche Quelle.

Hinzufügen des Ereignisses "SDL_TEXTEDIT"

Quelle: https://github.com/kivy/kivy/pull/5109

Der Prozess wurde hinzugefügt, wenn SDL_TEXTEDIT zur Abfragefunktion der Datei kivy / core / window / _window_sdl2.pyx empfangen wird.

    def poll(self):
        cdef SDL_Event event
        cdef int rv

        with nogil:
            rv = SDL_PollEvent(&event)
        if rv == 0:
            return False


~ Ausgelassen ~

        elif event.type == SDL_TEXTINPUT: 
            s = event.text.text.decode('utf-8')
            return ('textinput', s)
            
        elif event.type == SDL_TEXTEDITING:★ Ereignis hinzufügen
            s = event.edit.text.decode('utf-8')★ Geben Sie die Zeichen von IME ein
            return ('textedit', s)
        else:
            #    print('receive unknown sdl event', event.type)
            pass

Diese Datei ist übrigens eine Pyx-Datei, daher müssen Sie sie mit Cython erstellen und die Bibliothek neu erstellen. Da kivy OpenGL + SDL ist, war es schwierig, die Umgebung zu erstellen, und ich habe die Build-Umgebung mit Fenstern erstellt, aber es dauerte 2 bis 3 Tage. Details zum Aufbau der Umgebung werden zu einem späteren Zeitpunkt veröffentlicht.

Nachtrag: Ich habe einen Artikel darüber verfasst, wie man eine Umgebung für japanische Eingaben erstellt.

Ereignis "textedit" hinzufügen

Quelle: https://github.com/Adachinski/kivy/tree/textedit_patch_smple

Ändern Sie dazu window_sdl2.py. https://github.com/Adachinski/kivy/commits/textedit_patch_smple/kivy/core/window/window_sdl2.py

Die Korrekturpunkte sind wie folgt.

class WindowSDL(WindowBase):

    __events__ = ('on_textedit',)★ Ergänzung
 
~ Ausgelassen ~
        def _mainloop(self):
        EventLoop.idle()

        # for android/iOS, we don't want to have any event nor executing our
        # main loop while the pause is going on. This loop wait any event (not
        # handled by the event filter), and remove them from the queue.
        # Nothing happen during the pause on iOS, except gyroscope value sent
        # over joystick. So it's safe.
        while self._pause_loop:
            self._win.wait_event()
            if not self._pause_loop:
                break
            self._win.poll()

        while True:
            event = self._win.poll()
            if event is False:
                break
            if event is None:
                continue

            action, args = event[0], event[1:]
            if action == 'quit':
                if self.dispatch('on_request_close'):
                    continue
                EventLoop.quit = True
                self.close()
                break
~ Ausgelassen ~


            elif action == 'textinput':
                text = args[0]
                self.dispatch('on_textinput', text)
            elif action == 'textedit':★ Textedit hinzugefügt
                text = args[0]
                self.dispatch('on_textedit', text)

            # unhandled event !
            else:
                Logger.trace('WindowSDL: Unhandled event %s' % str(event))
    

~ Ausgelassen ~
    def on_textedit(self, text):★ Ergänzung
        pass

Beispiel für die tatsächliche Verwendung mit dem Ereignis "textedit"

Quelle: https://github.com/Adachinski/kivy_textedit_sample

Erben Sie die Klasse "TextInput" in TextInputIME.py und fügen Sie eine neue hinzu Ich habe eine "TextInputIME" -Klasse erstellt. Wir deklarieren die Variable testtext auch als StringProperty. Wenn die Verarbeitung des Textedit-Ereignisses erfolgt, wird das eingegebene Zeichen im Testtext gespeichert. Danach wird in der kv-Datei der Inhalt des Testtextes in Label angezeigt.

Der eigentliche Betriebsbildschirm sieht wie folgt aus.

Eintreten

editing.png

Während der Eingabe werden die eingegebenen Zeichen auf dem IME-Etikett (grauer Bereich) angezeigt.

Nach Bestätigung der Eingabe

complete.png Wenn Sie die Eingabetaste drücken und eingeben, werden die eingegebenen Zeichen in der Texteingabe angezeigt.

Was ist derzeit nicht möglich

Ich konnte das von mir eingegebene Japanisch anzeigen, konnte jedoch aufgrund eines Problems (Spezifikation?) Auf der SDL-Seite Folgendes nicht tun.

Dieser Inhalt selbst ist jedoch kein sehr kritischer Faktor, so dass die aktuelle Situation unentschlossen ist.

Recommended Posts

Die Geschichte der Anzeige der Zeichen in Kivys japanischer Eingabe
Die Geschichte, die Japan ausgab, wurde mit Django verwechselt
[Anmerkung] Japanische Schriftzeichen sind mit Atom-Runner verstümmelt
Die Geschichte, dass FastAPI die Vormachtstellung übernehmen könnte
Die Geschichte, die scipy plötzlich aufhörte zu laden
Die Geschichte, dass XGBoost endlich installiert wurde
Umgang mit dem Problem, dass japanische Zeichen bei der Ausgabe von Protokollen mit dem JSON-Protokollformatierer verstümmelt sind
Was ist der Grund, warum der Mensch keine grundlegenden Befehle auf Japanisch anzeigt?
Fehler, bei dem statische Dateien nicht auf dem AppEngine-Entwicklungsserver angezeigt werden
Die Geschichte, die zur Installation von Pip passt
Eine Geschichte, als ich IntelliJ unter Linux verwendete und kein Japanisch eingeben konnte