Il semble que de nombreuses personnes sont incapables de taper alors que l'on dit que les jeunes sont loin des ordinateurs. Cependant, les jeunes sont habitués à manipuler des smartphones au lieu de pouvoir utiliser des PC, et la saisie rapide des lycéennes actuelles est aussi rapide que les filles du garage sont surprises.
Dans ce cas, il semble que l'on dise depuis un certain temps que l'entrée PC doit se faire par effleurement, mais aucun logiciel ne pouvait être facilement essayé.
J'ai donc créé un clavier à l'aide d'une application appelée Pyto qui permet la programmation Python sur iOS.
J'ai également trouvé une image où j'essayais de créer un clavier à l'aide de l'écran tactile.
[Côté IOS] iPhone SE 2020 (iOS13.4.1) Pyto (12.0.3)
[Côté PC] Windows 10 Home 64bit (1909) Python 3.7.4
Bibliothèque pyautogui (0.9.50) pyperclip (1.8.0)
Envoie les données d'entrée du terminal iOS au PC via la communication par socket.
Les fonctions sont la saisie de caractères, Entrée et Retour arrière. Il est possible d'ajouter des fonctions telles que la croix et la suppression, mais cette fois nous l'avons limité à la saisie de caractères.
La conversion Kanji est effectuée du côté iOS, et une fois la conversion confirmée, appuyez à nouveau sur Confirmer pour envoyer les caractères au PC.
Le code source complet se trouve sur GitHub. Il y a 2 fichiers côté iOS et 1 fichier côté PC.
text_client.py
# text_client.py
import socket
class Sender():
def __init__(self, port, ipaddr, timeout=5.0):
self.port = port
self.ipaddr = ipaddr
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(timeout)
def connect(self):
self.sock.connect((self.ipaddr, self.port))
def send(self, text, enc="utf-8"):
"""
Envoyer des données
Parameters
----------
text : str
Texte à envoyer
enc : str
Le type d'encodage. Aucun sans encodage
"""
if(enc is not None):
text_ = text.encode(enc)
else:
text_ = text
self.sock.sendall(text_)
def close(self):
self.sock.close()
Classe de transmission de texte. Envoyez des données en utilisant la communication par socket. Nous utiliserons ceci dans le deuxième fichier.
flick_kb.py
# flick_kb.py
import sys
import socket
import pyto_ui as ui
import text_client as myclient
class MySender(myclient.Sender):
def __init__(self, port, ipaddr, timeout=5.0):
print(port, ipaddr)
super().__init__(port, ipaddr, timeout)
self.editflag = False
def connect(self):
try:
super().connect()
self.editflag = True
print("connection")
except socket.timeout:
print("timed out")
super().close()
sys.exit()
def send_text(self, text):
self.send(text)
def send_end_flag(self):
#Envoyer un drapeau pour notifier au PC la fin de l'application
if(self.editflag):
self.send(b"\x00", enc=None)
self.editflag = False
def close(self):
self.send_end_flag()
super().close()
def did_end_editing(self, sender):
if(self.editflag):
if sender.text == " ":
self.send(b"\x0a", enc=None) # enter
sender.text = " "
elif sender.text == "":
self.send(b"\x08", enc=None) # backspace
else:
self.send_text(sender.text[1:]) #Envoyer du texte sans l'espace précédent
sender.text = " "
sender.superview["text_field1"].become_first_responder() #Gardez la zone de texte floue
def did_change_text(self, sender):
if sender.text == "":
sender.text = " " #Pour la détection de retour arrière
self.send(b"\x08", enc=None) # backspace
def main():
args = sys.argv
if(len(args)<=2):
print("Input arguments. [PORT] [IP Address]")
sys.exit()
else:
port = int(args[1])
ipaddr = args[2]
#Émetteur
print("start connection...")
mysender = MySender(port=port, ipaddr=ipaddr, timeout=5.0)
mysender.connect()
#Partie GUI
view = ui.View()
view.background_color = ui.COLOR_SYSTEM_BACKGROUND
text_field = ui.TextField(placeholder="Back Space")
text_field.name = "text_field1"
text_field.text = " "
text_field.become_first_responder()
text_field.action = mysender.did_change_text
text_field.did_end_editing = mysender.did_end_editing
text_field.return_key_type = ui.RETURN_KEY_TYPE_DONE
text_field.width = 300
text_field.center = (view.width/2, view.height/2)
text_field.flex = [
ui.FLEXIBLE_BOTTOM_MARGIN,
ui.FLEXIBLE_TOP_MARGIN,
ui.FLEXIBLE_LEFT_MARGIN,
ui.FLEXIBLE_RIGHT_MARGIN
]
view.add_subview(text_field)
ui.show_view(view, ui.PRESENTATION_MODE_SHEET)
#Terminer le traitement
mysender.close()
print("end")
if __name__=="__main__":
main()
C'est un corps de clavier flick. J'utilise pyto_ui.TextField
de pyto. La partie GUI est presque la même que l'exemple de code de Pyto.
C'est TextField
, mais lorsque vous appuyez sur Entrée, il perd automatiquement le focus. Puisqu'une entrée continue n'est pas possible avec cela, la méthode d'appel de la fonction devenir_premier_répondeur ()
et de l'afficher à nouveau est prise. Par conséquent, le clavier disparaît un instant après avoir appuyé sur la touche de confirmation.
De plus, comme la méthode mysender.did_change_text
définie dans text_field.action
de la partie GUI est appelée avant même que les caractères japonais ne soient confirmés, il semble qu'elle ne puisse pas être envoyée au moment où la conversion est confirmée. .. Par conséquent, le texte est envoyé en appuyant deux fois sur le bouton de confirmation, "Confirmer la conversion → Confirmer". Vous devez appuyer trois fois sur la touche de confirmation pour insérer un saut de ligne.
Backspace ne répond pas en l'absence de texte. Par conséquent, j'ai essayé de mettre un espace dans la zone de texte à l'avance. Il est déterminé que Backspace a été pressé lorsque cet espace a été effacé. Une fois effacé, un nouvel espace est immédiatement inséré par le processus sender.text =" "
`.
J'ai utilisé UTF-8 LF (0x0a), Backspace (0x08) et NULL (0x00) pour Enter, Backspace et End code, respectivement, mais ils ne sont utilisés que comme indicateurs, ils n'ont donc pas de signification originale. Par conséquent, le code de saut de ligne reflète les paramètres du système d'exploitation et de l'éditeur du PC.
flick_kb_receiver.py
# flick_kb_receiver.py
import sys
import time
import socket
import pyautogui
import pyperclip
import threading
def type_text(text):
#Entrez les caractères donnés (copiez et collez dans le presse-papiers)
pyperclip.copy(text)
pyautogui.hotkey("ctrl", "v")
return True
def type_backspace():
pyautogui.typewrite(["backspace"])
return True
def type_enter():
pyautogui.typewrite(["enter"])
return True
class Receiver():
def __init__(self, port, ipaddr=None, set_daemon=True):
"""
Receveur
Parameters
----------
port : int
Numéro de port à utiliser
ipaddr : None or str
Adresse IP du PC récepteur. Acquis automatiquement avec Aucun.
set_daemon : bool
Voulez-vous faire du thread un démon? Arrêtez le thread principal sans attendre la fin du thread récepteur.
"""
if(ipaddr is None):
host = socket.gethostname()
ipaddr = socket.gethostbyname(host)
self.ipaddr = ipaddr
self.port = port
self.set_daemon = set_daemon
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.loopflag = False
print("ip:{0} port:{1}".format(self.ipaddr, self.port))
def loop(self):
self.sock.settimeout(0.5)
self.sock.bind((self.ipaddr, self.port))
self.sock.listen(1)
print("start listening...")
while(self.loopflag):
try:
conn, addr = self.sock.accept()
except socket.timeout:
continue
print("accepted")
with conn:
while(self.loopflag):
# print("waiting...")
data = conn.recv(1024)
if(not data):
break
if(data[:1]==b"\x08"): #Si vous appuyez successivement sur retour arrière, plusieurs messages seront envoyés en même temps (exemple: b)"\x08\x08\x08), vérifiez donc uniquement les 8 premiers octets
print("> BS")
type_backspace()
elif(data==b"\x0a"):
print("> Enter")
type_enter()
elif(data==b"\x00"):
print("STOP CLIENT")
break
else:
text = data.decode("utf-8")
print(">", text)
type_text(text)
def start_loop(self):
self.loopflag = True
self.thread = threading.Thread(target=self.loop)
if(self.set_daemon):
self.thread.setDaemon(True)
self.thread.start()
print("start_thread")
def stop_loop(self):
print("stop loop")
self.loopflag = False
time.sleep(0.6) #Attendez que le socket expire
if(not self.set_daemon):
print("waiting to stop client...") #Attendez que l'expéditeur s'arrête
self.thread.join()
print("stop_thread")
def close_sock(self):
self.sock.close()
print("socket closed")
def main():
#Arguments de ligne de commande
ipaddr = None
args = sys.argv
if(len(args)<=1):
print("Usage: flick_kb_receiver [PORT] [IP (optional)]")
sys.exit()
elif(len(args)==2):
port = int(args[1])
else:
port = int(args[1])
ipaddr = args[2]
#Traitement principal
receiver = Receiver(port=port, ipaddr=ipaddr)
receiver.start_loop()
while True:
stopper = input()
if(stopper=="s"):
receiver.stop_loop()
break
receiver.close_sock()
if __name__=="__main__":
main()
C'est du côté PC. J'ai utilisé pyautogui pour la saisie de caractères. pyautogui est une bibliothèque qui permet des opérations générales sur PC telles que les opérations de touches et les opérations de souris. Si les données binaires reçues ne sont pas Enter, Backspace ou End code, elles sont décodées et envoyées au processus de saisie de texte.
Cependant, il semble que la saisie japonaise ne soit pas possible avec pyautogui, donc la méthode consiste à enregistrer le texte dans le presse-papiers avec la méthode type_text
puis à le coller (Reference. / 2017/10/18/231 750)).
En ce qui concerne le retour arrière, si vous supprimez des caractères en continu du côté du smartphone, plusieurs codes de retour arrière \ x08
peuvent être envoyés en même temps comme \ x08 \ x08 \ x08
. Par conséquent, j'écris ʻif (data [: 1] == b "\ x08"): `pour ne voir que le premier octet. D'ailleurs, s'il s'agit de «data [0]», «8» (valeur convertie en nombre décimal) sera renvoyé.
La partie communication s'exécute dans un thread séparé et le thread principal attend la commande de fin de programme. Pendant l'exécution, vous pouvez quitter le programme en tapant s
dans la console et en appuyant sur Entrée. Cependant, étant donné que le thread de la section de communication ne s'arrête pas lorsque la communication est connectée, la section de communication est transformée en démon et arrêtée de force lorsque le thread principal se termine. Je ne sais pas si c'est un bon moyen.
[PC]
flick_kb_receiver.py
[iOS]
flick_clavier (dossier arbitraire)
├── flick_kb.py (fichier d'exécution)
├── text_client.py
python flick_kb_receiver.py 50001
flick_kb.py
dans l'application Pyto sur le côté iOS et appuyez sur la marque d'engrenage en bas à droite. Entrez le numéro de port et l'adresse IP dans Arguments, puis exécutez
Exemple: 50001 192.168.1.2
Si une erreur se produit dans la section d'importation du côté iOS, cela signifie que l'accès au dossier n'est pas autorisé, alors autorisez-le à partir de la marque de verrouillage Nanjing en bas à droite de l'écran de l'éditeur Pyto.
L'autorisation d'accès au pare-feu a été donnée lorsque le PC a été démarré pour la première fois, mais il ne pouvait pas être connecté à moins que l'accès public ne soit autorisé.
Le GIF ci-dessus est une combinaison ultérieure des écrans PC et iPhone. De la connexion à la saisie de caractères dans VSCode et à la déconnexion. Presque aucun retard n'a été ressenti.
Je pense que l'entrée flick est une très bonne technique en tant que clavier pour saisir le japonais avec un petit écran tactile. Cette fois, j'ai en fait essayé la saisie par effleurement sur un PC, et j'ai senti que le seuil pour PC serait abaissé en augmentant les options de saisie par effleurement pour les personnes qui ne peuvent pas utiliser un clavier de PC. Il y avait peu de mouvement de la ligne de visée entre le PC et le smartphone, et j'ai pu entrer sans aucune gêne.
Cependant, je peux frapper plus rapidement avec un clavier PC, donc il n'y a que peu d'avantages à utiliser la saisie par effleurement. Est-il possible de le frapper d'une main ou de l'utiliser en dormant? Après tout, l'entrée clavier du PC peut utiliser tous les doigts et les symboles sont faciles à taper, il est donc bon de l'utiliser.