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.
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.
Zunächst realisiert Kivy verschiedene Funktionen der Bibliothek, wie z. B. OpenGL in der unteren Ebene, wie unten gezeigt.
Unter diesen wird die Zeicheneingabe unter Verwendung von SDL realisiert.
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.
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.
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.
Empfangen Sie das Ereignis "SDL_TEXTEDIT" von SDL und geben Sie eine Zeichenfolge zurück.
Registrieren Sie ein neues "Textedit" -Ereignis, das verarbeitet werden soll.
@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.
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.
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
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.
Während der Eingabe werden die eingegebenen Zeichen auf dem IME-Etikett (grauer Bereich) angezeigt.
Wenn Sie die Eingabetaste drücken und eingeben, werden die eingegebenen Zeichen in der Texteingabe angezeigt.
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