[PYTHON] [Pyto] Ich habe versucht, ein Smartphone als Flick-Tastatur für den PC zu verwenden

image2.jpg

Einführung

Es wird gesagt, dass viele Menschen nicht tippen können, während junge Menschen nicht an PCs arbeiten. Junge Leute sind es jedoch gewohnt, mit Smartphones umzugehen, anstatt PCs benutzen zu können, und die Flick-Eingabe aktueller Highschool-Mädchen ist für Garagenmädchen überraschend schnell.

In diesem Fall scheint es seit einiger Zeit gesagt worden zu sein, dass die PC-Eingabe durch Streichen erfolgen sollte, aber es gab keine Software, die leicht ausprobiert werden konnte.

Also habe ich eine Flick-Tastatur mit einer App namens Pyto erstellt, die Python-Programmierung unter iOS ermöglicht.

Existierendes Produkt

Ich habe auch ein Bild gefunden, in dem ich versucht habe, mithilfe des Touchpanels eine Flick-Tastatur zu erstellen.

Umgebung

[IOS Seite] iPhone SE 2020 (iOS13.4.1) Pyto (12.0.3)

[PC-Seite] Windows 10 Home 64bit (1909) Python 3.7.4

Bibliothek pyautogui (0.9.50) pyperclip (1.8.0)

Spezifikation

Sendet die Eingabedaten des iOS-Terminals über die Socket-Kommunikation an den PC.

Funktionen sind Zeicheneingabe, Eingabe und Rücktaste. Es ist möglich, Funktionen wie die Kreuztaste und Löschen hinzuzufügen, diesmal haben wir sie jedoch auf die Zeicheneingabe beschränkt.

Die Kanji-Konvertierung wird auf der iOS-Seite durchgeführt. Nachdem die Konvertierung bestätigt wurde, drücken Sie erneut auf Bestätigen, um die Zeichen an den PC zu senden.

Quellcode und Kommentar

Der gesamte Quellcode befindet sich auf GitHub. Es gibt 2 Dateien auf der iOS-Seite und 1 Datei auf der PC-Seite.

iOS Seite

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"):
        """
Daten senden
        
        Parameters
        ----------
        text : str
Zu sendender Text
        enc : str
Die Art der Codierung. Keine und keine Kodierung
        """
        if(enc is not None):
            text_ = text.encode(enc)
        else:
            text_ = text
        self.sock.sendall(text_)
    
    def close(self):
        self.sock.close()
 

Textübertragungsklasse. Senden Sie Daten über Socket-Kommunikation. Wir werden dies in der zweiten Datei verwenden.

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):
        #Senden Sie ein Flag, um den PC über das Ende der Anwendung zu informieren
        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:])  #Senden Sie Text ohne das vorherige Leerzeichen
                sender.text = " "
    
        sender.superview["text_field1"].become_first_responder()  #Halten Sie das Textfeld unscharf
    
    def did_change_text(self, sender):
        if sender.text == "":
            sender.text = " "  #Zur Erkennung der Rücktaste
            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]
    
    #Sender
    print("start connection...")
    mysender = MySender(port=port, ipaddr=ipaddr, timeout=5.0)
    mysender.connect()
    
    #GUI-Teil
    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)
    
    #Verarbeitung beenden
    mysender.close()
    print("end")

if __name__=="__main__":
    main()

Es ist ein Flick-Tastaturkörper. Ich benutze pyto's pyto_ui.TextField. Der GUI-Teil entspricht fast dem Beispielcode von Pyto.

Dies ist "TextField", aber wenn Sie die Eingabetaste drücken, verliert es automatisch den Fokus. Da eine kontinuierliche Eingabe damit nicht möglich ist, wird die Methode zum Aufrufen der Funktion get_first_responder () und zum erneuten Anzeigen übernommen. Daher verschwindet die Tastatur nach dem Drücken der Bestätigungstaste für einen Moment.

Da die in "text_field.action" des GUI-Teils festgelegte Methode "mysender.did_change_text" aufgerufen wird, noch bevor die japanischen Zeichen bestätigt wurden, scheint sie zum Zeitpunkt der Bestätigung der Konvertierung nicht gesendet werden zu können. .. Daher wird der Text durch zweimaliges Drücken der Bestätigungstaste "Konvertierung bestätigen → Bestätigen" gesendet. Sie müssen die Bestätigungstaste dreimal drücken, um einen Zeilenumbruch einzufügen.

Die Rücktaste reagiert nicht, wenn kein Text vorhanden ist. Daher habe ich im Voraus versucht, ein Leerzeichen in das Textfeld einzufügen. Es wird festgestellt, dass die Rücktaste gedrückt wurde, als dieses Leerzeichen gelöscht wurde. Nach dem Löschen wird dem Prozess sender.text =" " `sofort ein neues Leerzeichen eingefügt.

Ich habe UTF-8 LF (0x0a), Backspace (0x08) und NULL (0x00) für Enter-, Backspace- und Endcode verwendet, aber sie werden nur als Flags verwendet, sodass sie keine ursprüngliche Bedeutung haben. Daher spiegelt der Zeilenvorschubcode die Einstellungen des PC-Betriebssystems und des Editors wider.

PC-Seite

flick_kb_receiver.py

# flick_kb_receiver.py
import sys
import time
import socket
import pyautogui
import pyperclip
import threading

def type_text(text):
    #Geben Sie die angegebenen Zeichen ein (kopieren und in die Zwischenablage einfügen)
    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):
        """
Empfänger

        Parameters
        ----------
        port : int
Zu verwendende Portnummer
        ipaddr : None or str
IP-Adresse des empfangenden PCs. Automatisch mit None erfasst.
        set_daemon : bool
Möchten Sie den Thread zu einem Daemon machen? Stoppen Sie den Haupt-Thread, ohne auf das Ende des Empfänger-Threads zu warten.
        """
        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"):  #Wenn Sie nacheinander die Rücktaste drücken, werden mehrere Nachrichten gleichzeitig gesendet (Beispiel: b)"\x08\x08\x08), überprüfen Sie also nur die ersten 8 Bytes
                        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)  #Warten Sie, bis die Steckdose abgelaufen ist
        if(not self.set_daemon):
            print("waiting to stop client...")  #Warten Sie, bis der Absender angehalten hat
            self.thread.join()
        print("stop_thread")
    
    def close_sock(self):
        self.sock.close()
        print("socket closed")

def main():
    #Kommandozeilenargumente
    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]

    #Hauptverarbeitung
    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()

Es ist die PC-Seite. Ich habe Pyautogui für die Zeicheneingabe verwendet. pyautogui ist eine Bibliothek, die allgemeine PC-Operationen wie Tasten- und Mausoperationen ermöglicht. Wenn es sich bei den empfangenen Binärdaten nicht um Eingabe-, Rücktaste- oder Endcode handelt, werden sie dekodiert und an den Texteingabeprozess gesendet.

Es scheint jedoch, dass japanische Eingaben mit pyautogui nicht möglich sind. Daher besteht die Methode darin, den Text mit der Methode "type_text" in der Zwischenablage zu speichern und dann einzufügen (Referenz. / 2017/10/18/231 750)).

In Bezug auf die Rücktaste können, wenn Sie Zeichen auf der Smartphoneseite kontinuierlich löschen, mehrere Rücktaste-Codes "\ x08" gleichzeitig gesendet werden, z. B. "\ x08 \ x08 \ x08". Deshalb schreibe ich if (data [: 1] == b" \ x08 "):, um nur das erste Byte zu sehen. Übrigens, wenn es sich um "data [0]" handelt, wird "8" (in Dezimalzahl konvertierter Wert) zurückgegeben.

Der Kommunikationsteil wird in einem separaten Thread ausgeführt, und der Hauptthread wartet auf den Befehl zum Beenden des Programms. Während der Ausführung können Sie das Programm beenden, indem Sie in der Konsole s eingeben und die Eingabetaste drücken. Da der Kommunikationsabschnittsthread jedoch nicht stoppt, wenn die Kommunikation verbunden ist, wird der Kommunikationsabschnitt in einen Dämon umgewandelt und zwangsweise gestoppt, wenn der Hauptthread endet. Ich weiß nicht, ob das ein guter Weg ist.

Bewegung

Dateipositionierung

[PC]

flick_kb_receiver.py

[iOS]

flick_Tastatur (beliebiger Ordner)
├── flick_kb.py (Ausführungsdatei)
├── text_client.py

Ausführungsverfahren

Verbindung / Eingang

  1. Führen Sie die Portnummer als Befehlszeilenargument auf der PC-Seite aus Beispiel: python flick_kb_receiver.py 50001
  2. Öffnen Sie flick_kb.py in der Pyto-App auf der iOS-Seite und drücken Sie die Zahnradmarkierung unten rechts. Wird ausgeführt, nachdem die Portnummer und die IP-Adresse unter Argumente eingegeben wurden Beispiel: 50001 192.168.1.2
  3. Platzieren Sie den Cursor auf einem beliebigen Texteditor oder Suchfenster auf Ihrem PC.
  4. Nachdem Sie die Eingabe im Textfeld auf der iOS-Seite bestätigt haben, drücken Sie erneut auf Bestätigen.
  5. Text wird auf der PC-Seite eingegeben
12C402D0-A9C4-41A1-9B3A-AF6F0A083CF8.jpeg Bildschirm zum Festlegen von Argumenten in Pyto

Trennen / beenden

  1. Stoppen Sie das Programm auf der iOS-Seite
  2. Geben Sie "s" in die Konsole auf der PC-Seite ein und drücken Sie die Eingabetaste, um das Programm auf der PC-Seite zu stoppen.

Wenn im Importbereich auf der iOS-Seite ein Fehler auftritt, ist der Ordnerzugriff nicht zulässig. Lassen Sie ihn daher über die Nanjing-Sperrmarke unten rechts im Pyto-Editor-Bildschirm zu.

Die Firewall-Zugriffsberechtigung wurde beim ersten Start des PCs erteilt, konnte jedoch nur verbunden werden, wenn der öffentliche Zugriff zulässig war.

Betriebszustand

E8D546BF-13AA-411C-8FE0-097E427CB509.gif

Das obige GIF ist eine spätere Kombination der PC- und iPhone-Bildschirme. Von der Verbindung über die Eingabe von Zeichen in VSCode bis hin zum Trennen der Verbindung. Es war fast keine Verzögerung zu spüren.

abschließend

Ich denke, Flick Input ist eine sehr gute Technik als Tastatur für die Eingabe von Japanisch mit einem kleinen Touchpanel. Dieses Mal habe ich tatsächlich versucht, die Flick-Eingabe auf einem PC vorzunehmen, und ich hatte das Gefühl, dass der Schwellenwert für den PC durch Erhöhen der Optionen für die Flick-Eingabe für Personen, die keine PC-Tastatur verwenden können, gesenkt wird. Die Sichtlinie zwischen dem PC und dem Smartphone bewegte sich kaum, und ich konnte ohne Beschwerden eingeben.

Mit einer PC-Tastatur kann ich jedoch schneller schlagen, sodass die Verwendung der Flick-Eingabe wenig Vorteile bringt. Kann man es mit einer Hand schlagen oder im Schlaf benutzen? Schließlich kann die PC-Tastatureingabe alle Finger verwenden, und es ist einfach, Symbole einzugeben, daher ist es gut, sie zu verwenden.

Recommended Posts

[Pyto] Ich habe versucht, ein Smartphone als Flick-Tastatur für den PC zu verwenden
Ich habe versucht zu erklären, wozu der Python-Generator so einfach wie möglich ist.
Ich habe versucht, einen Bot für die Ankündigung eines Wiire-Ereignisses zu erstellen
Ich habe versucht, Jojo mit LSTM ein seltsames Zitat zu machen
Ich habe versucht, einen Linebot zu erstellen (Vorbereitung)
Ich habe eine Web-API erstellt
Ich habe einen Docker-Container erstellt, um JUMAN ++, KNP, Python (für pyKNP) zu verwenden.
Ich habe versucht, eine Gesichtsdiagnose-KI für professionelle Golferinnen zu erstellen ①
Ich habe versucht, eine Gesichtsdiagnose-KI für professionelle Golferinnen zu erstellen ②
Ich denke, es ist ein Verlust, den Profiler nicht für die Leistungsoptimierung zu verwenden
Ich habe versucht, eine Super-Resolution-Methode / ESPCN zu erstellen
Ich habe versucht, lightGBM, xg Boost mit Boruta zu verwenden
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
Ich habe versucht, KI für Smash Bra zu machen
Ich habe versucht, eine zufällige Zeichenfolge zu generieren
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
Ich habe versucht, mit Raspeye + Tact Switch eine Schaltfläche für Slack zu erstellen
Ich habe versucht, eine Super-Resolution-Methode / SRCNN build zu erstellen
[Python] Ich habe versucht, den Typnamen als Zeichenfolge aus der Typfunktion abzurufen
Ich habe ein ○ ✕ Spiel mit TensorFlow gemacht
[Python] Ich möchte nur den Index verwenden, wenn ich eine Liste mit einer for-Anweisung schleife
Ich habe versucht, mit Open AI Gym eine verbesserte Lernumgebung für Othello zu schaffen
Als ich nach "as a Service" von AaaS bis ZaaS suchte, sah ich verschiedene Dienste.
Erstellen Sie einen Datensatz mit Bildern, die für das Training verwendet werden sollen
Ich habe versucht, einen "verdammt großen Literaturkonverter" zu machen.
Ich habe versucht zusammenzufassen, wie man Matplotlib von Python verwendet
Ich habe versucht, einen Pseudo-Pachislot in Python zu implementieren
[Go + Gin] Ich habe versucht, eine Docker-Umgebung zu erstellen
Praktisch, um Matplotlib-Unterzeichnungen in for-Anweisungen zu verwenden
Ich habe versucht zusammenzufassen, wie man Pandas von Python benutzt
Ich habe einen einfachen RPA für die Anmeldung mit Selen ausprobiert
Ich habe versucht, ein Konfigurationsdiagramm mit Diagrammen zu zeichnen
Ich habe versucht zu debuggen.
Ich habe versucht, eine Bibliothek (Common Thread) zu verwenden, die die Verwendung des Python-Threading-Pakets vereinfacht
[Git] Ich habe versucht, anhand eines konkreten Beispiels zu verstehen, wie man Git Stash verwendet.
[Für diejenigen, die TPU verwenden möchten] Ich habe versucht, die Tensorflow Object Detection API 2 zu verwenden
Ich habe versucht, mit Quantx eine Linie mit gleitendem Durchschnitt des Volumens zu implementieren
Ich habe versucht, das grundlegende Modell des wiederkehrenden neuronalen Netzwerks zu implementieren
Verwendung von Fujifilm X-T3 als Webcam unter Ubuntu 20.04
Ich habe versucht, den für TensorFlow geschriebenen Code nach Theano zu portieren
Ich habe versucht, automatisch einen Bericht mit der Markov-Kette zu erstellen
[Markov-Kette] Ich habe versucht, die Zitate in Python einzulesen.
Ich habe versucht, Tensorboard zu verwenden, ein Visualisierungstool für maschinelles Lernen
Ich habe versucht, das Problem der Kombinationsoptimierung mit Qiskit zu lösen
Ich habe versucht "Wie man eine Methode in Python dekoriert"
Verwendung von cuML SVC als Gridsearch-CV-Klassifikator
Ich möchte eine virtuelle Umgebung mit Jupyter Notebook verwenden!
Ich wusste nicht, wie ich die [Python] für die Anweisung verwenden sollte
Ich habe versucht, [eine bestimmte Aufgabe] mit einem Raspeltorte zu automatisieren
Ich bin gestolpert, als ich versucht habe, Basemap zu installieren, also ein Memorandum
Ich habe versucht, eine zufällige FizzBuzz-Spalte mit Blasensortierung zu sortieren.
Ich habe eine Stoppuhr mit tkinter mit Python gemacht
So verwenden Sie eine andere Datei als .fabricrc als Konfigurationsdatei
Ich habe versucht, in einem tief erlernten Sprachmodell zu schreiben
Ich habe mit PyQt einen einfachen Texteditor erstellt
Verwenden Sie eine Skriptsprache für ein komfortables C ++ - Leben - OpenCV-Port Python zu C ++ -