Question

J'ai un problème similaire à celui de ce post

c, déchets apparaissant à l'écran avec des malédictions

Cependant, j'utilise Python. J'ai écrit une classe d'écran de wrapper qui enveloppe le module de malédiction de manière plus pratique. J'ai un getch comme ça

def getKeyCode(self):                                                                                                                         
    with self._curses_lock:                                                                                                                   
        self._curses_screen.nodelay(False)                                                                                                    

    c = self._curses_screen.getch()                                                                                                           
    if c == 27:                                                                                                                               
        with self._curses_lock:                                                                                                               
            self._curses_screen.nodelay(True)                                                                                                 
        next_c = self._curses_screen.getch()                                                                                                  

        with self._curses_lock:                                                                                                               
            self._curses_screen.nodelay(False)                                                                                                

    return c          

et une écriture qui se résume à cette

        with self._curses_lock:                                                                                                               
            self._curses_screen.addstr(y, x, out_string, attr)

Le getkeycode est appelé par un fil de python séparé qui attend dans la godet pendant la plupart du temps, et lorsqu'une touche est enfoncée, elle est ajoutée à une file d'attente. Sur l'autre thread (principal), j'ai une boucle d'événement qui obtient les événements de la file d'attente, effectue des repeignes et rafraîchir l'écran.

Comme je sais que les ncurses contiennent un état partagé, j'ai ajouté une bande de filetage.Locks afin d'empêcher les conditions de race, mais si je continue à appuyer sur la touche fléchée, je reçois parfois des ordures. Je suppose que cela est dû à Getch d'être libéré à l'intérieur des ncurses alors qu'un repeint se passe de l'autre fil. Cela décède l'état de la repeinte, donnant des résultats étranges. Je ne peux évidemment pas avoir mon filetage de code Gekekey pour tenir la serrure, car cela signifierait d'empêcher de repeindre le tout jusqu'à ce que le Getch revienne, ni je ne souhaite qu'un getch non-blocage, car je ne voudrais pas vraiment résoudre le problème et 2) Demandez à un enferment en cours d'exécution qui permettrait de pomper la consommation de la CPU à 100%. Comment puis-je résoudre ce problème?

Était-ce utile?

La solution

J'ai résolu le problème, comme ça.J'ai défini getch non-blocking avec

self._curses_screen.nodelay(True) 

Ensuite, je fais l'attente de la malédiction, mais avec une sélection sur STDIN.Lorsque la sélection de SELECT est disponible, certaines choses sont disponibles et je peux verrouiller et obtenir un accès exclusif au backend NCurses, garanti que je reviendrais immédiatement avec ce qui est disponible et relâchez la serrure.

def getKeyCode(self):                                                                                                                         
    select.select([sys.stdin], [], [])                                                                                                        

    with self._curses_lock:                                                                                                                   

        c = self._curses_screen.getch()                                                                                                       
        if c == 27:                                                                                                                           
            next_c = self._curses_screen.getch()                                                                                              

    return c

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top