En juillet 2018, la dernière version de Kivy (1.10.1) est sortie. Voici l'écran IME La demande d'extraction de contenu a été adoptée et IME fonctionne et le japonais en cours de saisie s'affiche.
Bien qu'il s'agisse de la bibliothèque GUI de Python "Kivy", il existe un problème en raison du fait que le japonais (IME) ne s'affiche pas lors de la saisie du japonais dans l'entrée de texte dans l'environnement Windows / MacOS. Cette fois, nous avons étudié la raison pour laquelle il n'était pas affiché et avons pris des mesures pour le rendre visible. Le système d'exploitation de vérification est Windows.
Tout d'abord, Kivy, comme illustré ci-dessous, la couche basse réalise diverses fonctions par des bibliothèques comme OpenGL.
Parmi eux, la saisie de caractères est réalisée en utilisant SDL.
La source est extraite du Tutoriel de l'entrée de texte SDL.
SDL_StartTextInput();
while (!done) {
SDL_Event event;
if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
/*Fin*/
done = SDL_TRUE;
break;
case SDL_TEXTINPUT:
/*Ajouter un nouveau texte à la fin du texte*/
strcat(text, event.text.text);
break;
case SDL_TEXTEDITING:
/*
Mettre à jour le texte non converti.
Mettre à jour la position du curseur.
Convertir la longueur de la sélection(si possible).
*/
composition = event.edit.text;
cursor = event.edit.start;
selection_len = event.edit.length;
break;
}
}
Redraw();
}
}
En regardant cela, vous pouvez voir que l'événement "SDL_TEXTINPUT" est émis lors de la saisie de caractères et que l'événement "SDL_TEXTEDITING" est émis lors de l'utilisation de l'IME.
Dans cet esprit, jetons un œil au [code source github] de kivy (https://github.com/kivy/kivy). C'est core / window / _window_sdl2.pyx Qui reçoit l'événement de SDL et le traite. pyx) fonction "poll". La fonction d'interrogation reçoit l'événement de SDL et émet l'événement avec la fonction _event_loop de window_sdl2.py. En regardant le code de la fonction "poll", il ressemble à ceci:
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)
~ Omis ~
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
Comme vous pouvez le voir, ** L'entrée de caractères et l'événement "textinput" sont renvoyés en réponse à l'événement "SDL_TEXTINPUT" lorsque l'entrée de caractères est confirmée, mais il est émis par SDL lors de l'entrée (IME). Il n'y a aucun traitement à effectuer en réponse à l'événement "SDL_TEXTEDIT". ** ** C'est la raison pour laquelle les caractères ne sont pas affichés lors de la saisie du japonais.
Maintenant que je connais la raison, je vais réfléchir à ce qu'il faut faire ensuite. En termes de traitement, je pense que la procédure suivante devrait être ajoutée en premier.
Recevoir l'événement "SDL_TEXTEDIT" de SDL et renvoyer une chaîne de caractères.
Enregistrez un nouvel événement "textedit" à traiter.
@souan a ajouté pull request à kivy lui-même. De plus, en tant qu'exemple de programme, il est placé sur github.
Exemple d'émission d'un événement textedit: https://github.com/Adachinski/kivy/tree/textedit_patch_smple Exemple d'utilisation: https://github.com/Adachinski/kivy_textedit_sample
Ce qui suit concerne la source réelle.
Source: https://github.com/kivy/kivy/pull/5109
Ajout du processus lorsque SDL_TEXTEDIT est reçu dans la fonction d'interrogation du fichier kivy / core / window / _window_sdl2.pyx.
def poll(self):
cdef SDL_Event event
cdef int rv
with nogil:
rv = SDL_PollEvent(&event)
if rv == 0:
return False
~ Omis ~
elif event.type == SDL_TEXTINPUT:
s = event.text.text.decode('utf-8')
return ('textinput', s)
elif event.type == SDL_TEXTEDITING:★ Ajouter un événement
s = event.edit.text.decode('utf-8')★ Entrez les caractères de IME
return ('textedit', s)
else:
# print('receive unknown sdl event', event.type)
pass
À propos, ce fichier est un fichier pyx, vous devez donc le créer avec cython et recréer la bibliothèque. Comme kivy est OpenGL + SDL, il était difficile de créer l'environnement, et je construisais l'environnement de construction avec Windows, mais cela a pris 2 à 3 jours. Les détails sur la construction de l'environnement seront publiés à une date ultérieure.
Postscript: J'ai rédigé un article sur la création d'un environnement pour les entrées japonaises.
Source: https://github.com/Adachinski/kivy/tree/textedit_patch_smple
Pour ce faire, modifiez window_sdl2.py. https://github.com/Adachinski/kivy/commits/textedit_patch_smple/kivy/core/window/window_sdl2.py
Les points de correction sont les suivants.
class WindowSDL(WindowBase):
__events__ = ('on_textedit',)★ Ajout
~ Omis ~
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
~ Omis ~
elif action == 'textinput':
text = args[0]
self.dispatch('on_textinput', text)
elif action == 'textedit':★ Ajout de texte
text = args[0]
self.dispatch('on_textedit', text)
# unhandled event !
else:
Logger.trace('WindowSDL: Unhandled event %s' % str(event))
~ Omis ~
def on_textedit(self, text):★ Ajout
pass
Source: https://github.com/Adachinski/kivy_textedit_sample
Héritez de la classe "TextInput" dans TextInputIME.py et ajoutez-en une nouvelle J'ai créé une classe "TextInputIME". Nous déclarons également la variable testtext comme StringProperty. Lorsque le traitement de l'événement textedit arrive, le caractère saisi est stocké dans testtext. Après cela, dans le fichier kv, le contenu du testtext est affiché dans Label.
L'écran de fonctionnement réel est le suivant.
Au fur et à mesure que vous tapez, les caractères que vous saisissez apparaissent sur l'étiquette IME (zone grise).
Lorsque vous appuyez sur la touche Entrée et tapez, les caractères que vous tapez seront affichés dans l'entrée de texte.
J'ai réussi à afficher le japonais que je tapais, mais je n'ai pas pu faire ce qui suit en raison d'un problème (spécification?) Côté SDL.
Cependant, ce contenu en lui-même n'est pas un facteur très critique personnellement, de sorte que la situation actuelle est indécise.
Recommended Posts