2016-12-05 12 views
0

나는 무엇을 해야할지 붙어 있습니다. 내 Qt 응용 프로그램에 포커스가 없을 때 xlib가 키 누름을 읽는 동안 while 루프가 있습니다. 이것은 우분투 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 프레임 워크에는 주기적으로 함수를 실행하고'while True' 또는 다른 루프 대신 사용할 수있는 'Timer' 클래스가 있습니다. – furas

+0

필요한 모든 것은'run' 메소드를 다시 구현 한'QThread'라고 말하고 싶습니다. while 루프를'run' 메소드 안에 넣고 필요할 때 스레드를 시작하십시오. –

+0

데모 코드가 라이브러리에 이미 모든 키 누름을 자동으로 기록하고 루프를 사용하여 큐를 인쇄하는 경우 확실하지 않습니다. – user1766555

답변

2

Qt의 이벤트 루프 입니다는 X 이벤트 루프 /usr/share/doc/python3-xlib/examples/record_demo.py 파일입니다. 너는 다른 것을 필요로하지 않는다.

이벤트 루프에서 콜백 정보를 얻었으므로 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