2016-12-05 1 views
0

Je suis coincé sur ce qu'il faut faire. J'ai une boucle while pour xlib pour lire les pressions sur les touches quand mon application Qt n'est pas au point. Ceci est un copier coller du paquet python3-xlib d'ubuntu 16.04 /usr/share/doc/python3-xlib/examples/record_demo.py. Mais cela perturbe la fonctionnalité de l'application Qt car elle ne lit que les touches et ne gère pas les boucles d'événements de Qt. Est-ce que je devrais faire en sorte que mon application Qt ait un deuxième thread pour cela? Ou puis-je accrocher la boucle de xlib sur les boucles de Qt?Comment ajouter votre propre boucle à Qt?

Je travaille avec python3, pyqt5 et python3-xlib.

est Ci-dessous le fichier /usr/share/doc/python3-xlib/examples/record_demo.py

#!/usr/bin/python3 
# 
# examples/record_demo.py -- demonstrate record extension 
# 
# Copyright (C) 2006 Alex Badea <[email protected]> 
# 
# This program is free software; you can redistribute it and/or modify 
# it under the terms of the GNU General Public License as published by 
# the Free Software Foundation; either version 2 of the License, or 
# (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with this program; if not, write to the Free Software 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

# Simple demo for the RECORD extension 
# Not very much unlike the xmacrorec2 program in the xmacro package. 

import sys 
import os 

# Change path so we find Xlib 
sys.path.insert(1, os.path.join(sys.path[0], '..')) 

from Xlib import X, XK, display 
from Xlib.ext import record 
from Xlib.protocol import rq 

local_dpy = display.Display() 
record_dpy = display.Display() 

def lookup_keysym(keysym): 
    for name in dir(XK): 
     if name[:3] == "XK_" and getattr(XK, name) == keysym: 
      return name[3:] 
    return "[%d]" % keysym 

def record_callback(reply): 
    if reply.category != record.FromServer: 
     return 
    if reply.client_swapped: 
     print("* received swapped protocol data, cowardly ignored") 
     return 
    if not len(reply.data) or reply.data[0] < 2: 
     # not an event 
     return 

    data = reply.data 
    while len(data): 
     event, data = rq.EventField(None).parse_binary_value(data, record_dpy.display, None, None) 

     if event.type in [X.KeyPress, X.KeyRelease]: 
      pr = event.type == X.KeyPress and "Press" or "Release" 

      keysym = local_dpy.keycode_to_keysym(event.detail, 0) 
      if not keysym: 
       print("KeyCode%s %s" % (pr, event.detail)) 
      else: 
       print("KeyStr%s %s" % (pr, lookup_keysym(keysym))) 

      if event.type == X.KeyPress and keysym == XK.XK_Escape: 
       local_dpy.record_disable_context(ctx) 
       local_dpy.flush() 
       return 
     elif event.type == X.ButtonPress: 
      print("ButtonPress %s" % event.detail) 
     elif event.type == X.ButtonRelease: 
      print("ButtonRelease %s" % event.detail) 
     elif event.type == X.MotionNotify: 
      print("MotionNotify %i %i" % (event.root_x, event.root_y)) 


# Check if the extension is present 
if not record_dpy.has_extension("RECORD"): 
    print("RECORD extension not found") 
    sys.exit(1) 
r = record_dpy.record_get_version(0, 0) 
print("RECORD extension version %d.%d" % (r.major_version, r.minor_version)) 

# Create a recording context; we only want key and mouse events 
ctx = record_dpy.record_create_context(
     0, 
     [record.AllClients], 
     [{ 
       'core_requests': (0, 0), 
       'core_replies': (0, 0), 
       'ext_requests': (0, 0, 0, 0), 
       'ext_replies': (0, 0, 0, 0), 
       'delivered_events': (0, 0), 
       'device_events': (X.KeyPress, X.MotionNotify), 
       'errors': (0, 0), 
       'client_started': False, 
       'client_died': False, 
     }]) 

# Enable the context; this only returns after a call to record_disable_context, 
# while calling the callback function in the meantime 
record_dpy.record_enable_context(ctx, record_callback) 

# Finally free the context 
record_dpy.record_free_context(ctx) 
+1

chaque cadre GUI a une classe 'Timer' qui vous permet d'exécuter la fonction périodiquement et vous pouvez l'utiliser à la place de' while True' ou d'une autre boucle. – furas

+0

Je dirais que tout ce dont vous avez besoin est un 'QThread' avec la méthode' run' réimplémentée. Emballez votre boucle while dans la méthode 'run' et lancez le thread lorsque vous en avez besoin. –

+0

Je ne suis pas sûr que ce code de démonstration ait déjà enregistré automatiquement toutes les touches de la bibliothèque et utilise simplement la boucle pour imprimer la file d'attente. – user1766555

Répondre

2

boucle d'événement de Qt est une boucle d'événement X. Vous n'avez pas besoin d'un autre. Comme vous recevez les informations en tant que rappels de la boucle d'événements, cela fonctionnera: tant que vous utiliserez la même bibliothèque que celle utilisée par Qt et que vous y enregistrerez le rappel, votre rappel sera appelé.

Si vous obtenez les informations en tant qu'événements, vous pouvez filtrer tous les événements X natifs arrivant à votre application: utilisez QCoreApplication::installNativeEventFilter. Votre implémentation concrète de QAbstractNativeEventFilter recevra des événements natifs sous forme de pointeurs vers xcb_generic_event_t, voir the documentation.

L'interopérabilité avec Python sera toutefois un peu compliquée en cas d'événement. Vous devrez peut-être implémenter le filtre d'événements en C++ et l'exposer à Python.

+0

Cela ne fonctionne-t-il pas uniquement si l'application Qt est active, car aucun événement n'est généré lorsque l'application n'est pas active? J'essaie de lire les touches lorsque l'application Qt n'est pas au point. – user1766555

+1

Les API que vous mentionnez sont prises en charge dans PyQt. Mais lorsque l'application * n'a pas le focus (ce qui intéresse le PO), elle n'attrape que les touches de modification. Donc, je ne pense pas que ça va beaucoup aider. – ekhumoro

+1

@ user1766555. Je pense que la solution la plus simple peut être d'utiliser un thread séparé et d'envoyer des signaux au thread principal. – ekhumoro