2016-12-05 4 views
0

私は何をすべきかに固執しています。私は、Qtアプリケーションにフォーカスがないときにxlibがキーを押すのを読むためのwhileループを持っています。これは、ubuntu 16.04 python3-xlibパッケージ/usr/share/doc/python3-xlib/examples/record_demo.pyのコピー貼りです。しかしこれはQtアプリケーションの機能を混乱させます。なぜなら、それはキープレスを読み込み、Qtのイベントループを処理しないからです。このQtアプリケーションに2番目のスレッドを作成させるべきですか?または、xlibのループをQtのループにフックできますか?Qtに独自のループを追加するには?

私はpython3、pyqt5、およびpython3-xlibを使用しています。以下は

#!/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

すべてのGUIフレームワークには定期的に関数を実行できる 'Timer'クラスがあり、' while True'や他のループの代わりに使うことができます。 – furas

+0

私はあなたが必要とするすべてのものが 'QThread'であり、' run'メソッドが再実装されていると言います。 whileループを 'run'メソッドの中に入れて、必要に応じてスレッドを開始してください。 –

+0

デモコードでライブラリがすでにすべてのキー押下を自動的に記録しているかどうかはわかりません。単純にループを使用してキューを印刷します。 – user1766555

答えて

2

Qtのイベントループ/usr/share/doc/python3-xlib/examples/record_demo.pyファイルです Xのイベントループです。あなたは別のものは必要ありません。

イベントループからのコールバックとして情報を取得しているので、これは「うまくいく」でしょう:Qtが使用する同じxcbライブラリを使用し、そこにコールバックを登録する限り、コールバックが呼び出されます。

イベントとして情報を取得している場合は、アプリケーションに到着するすべてのネイティブXイベントをフィルタリングできます(QCoreApplication::installNativeEventFilter)。 QAbstractNativeEventFilterの具体的な実装では、xcb_generic_event_tへのポインタとしてネイティブイベントを受け取ります。the documentationを参照してください。

イベントの場合、Pythonとの相互運用は少し複雑です。 C++でイベントフィルタを実装し、Pythonに公開する必要があるかもしれません。

+0

これは、アプリケーションにフォーカスがないときにイベントが生成されないため、Qtアプリケーションにフォーカスがある場合にのみ機能しますか? Qtアプリケーションにフォーカスがないときにキーを読み取ろうとしています。 – user1766555

+1

あなたが言及しているAPIはPyQtでサポートされています。しかし、アプリケーション*がフォーカスを持っていない場合(これはOPが興味を持っている)、修飾キーの押下だけを捕捉します。だから私はそれが多くの助けになるとは思わない。 – ekhumoro

+1

@ user1766555私は、最も簡単な解決策は、別のスレッドを使用して、メインスレッドにシグナルを送り返すことです。 – ekhumoro

関連する問題