2016-06-29 5 views
0

그래서 특정 버튼을 계속 누르고 있으면 오디오 장치가 재생되고 버튼을 놓으면 오디오 장치가 중지되는 응용 프로그램이 있습니다. 내가 발표하지 않은 사실에도 불구하고 key_0 pressedkey_0 released 중 연속 인쇄를 볼 수QKeyEvent isAutoRepeat가 작동하지 않습니까?

void MainWindow::keyPressEvent(QKeyEvent *event) 
{ 
    if(event->isAutoRepeat()) 
    { 
     event->ignore(); 
    } 
    else 
    { 
     if(event->key() == Qt::Key_0) 
     { 
      qDebug()<<"key_0 pressed"<<endl; 
     } 
     else 
     { 
      QWidget::keyPressEvent(event); 
     } 
    } 
} 

void MainWindow::keyReleaseEvent(QKeyEvent *event) 
{ 
    if(event->isAutoRepeat()) 
    { 
     event->ignore(); 
    } 
    else 
    { 
     if(event->key() == Qt::Key_0) 
     { 
      qDebug()<<"key_0 released"<<endl; 
     } 
     else 
     { 
      QWidget::keyReleaseEvent(event); 
     } 
    } 
} 

그러나 분명히 isAutoRepeat 기능이 작동하지 않습니다 : 나는 아래의 코드와 유사하다이를 구현하기 위해 keyPressEventKeyReleaseEvent를 사용 내가 누른 후 0 키. 내 코드가 잘못되었거나 다른 것이 잘못 되었습니까?

감사합니다.

편집

나는 MainWindow가 키보드 포커스를 잃으면 때문에 이런 일이 생각합니다. 실제로 어떤 위젯에 포커스가 있는지를 어떻게 알 수 있습니까? Qt::Key_0을 눌렀을 때 실제로 위젯을 사용하고 있지만, 위젯을 모두 Qt::NoFocus으로 설정했다고 생각합니다. 작동하지 않는 것 같습니다.

내가하는 위젯 알고 노력하고있어 다음을 수행하여 초점이 있습니다

QWidget * wigdet = QApplication::activeWindow(); 
qDebug()<<wigdet->accessibleName()<<endl; 

를하지만 항상 빈 문자열을 인쇄합니다. 키보드 포커스가있는 위젯의 이름을 인쇄하려면 어떻게해야합니까?

+0

클래스가'MainWindow' 또는'ConsoleMainWindow'입니까? 귀하의 질문에 오타가있는 것 같아 – IAmInPLS

+0

둘째, 귀하의 코드는 나를 위해 작동하고 그냥 그것을 테스트했습니다. 문서는 "이벤트가 자동 반복으로 인한 다중 키 압축 이벤트 인 경우이 함수는 true 또는 false로 불확정성을 반환 할 수 있습니다." 이 경우에 당신이 있습니까? – IAmInPLS

+0

@IAmInPLS 미안하지만 오타였습니다. 내 수업은 MainWindow입니다. –

답변

0

어쨌든 해결되었습니다.

문제는 Kinect에서 증강 현실 이미지를 표시하는 데 사용하는 QGLWidget의 하위 클래스 인 위젯이 있다는 것입니다. 이 위젯은 키보드 버튼을 누를 때마다 키보드 포커스를 대신합니다. (MainWindowQMainWindow의 서브 클래스)

이 문제를 해결하기 위해 나는 MainWindow 클래스에서 grabKeyboard 함수를 호출하는 데 필요한, 그래서 this->grabKeyboard() 내가 key_0 버튼을 MainWindow가 손실되지 않습니다 그래서 눌렀을 때 추가하는 데 필요한 행은 키보드 포커스를 누른 다음 키를 놓으면 일반 동작을 다시 시작하기 위해 라인 this->releaseKeyboard()을 추가해야했습니다. 즉, 다른 위젯이 키보드 포커스를 가질 수 있습니다.

1

그래서이 문제 (그리고 grabKeyboard가 실제로 도움이되지 못함)를 발견하자 나는 qtbase를 파기 시작했습니다. 이것은 xcb를 통해 X11에 연결되며 기본적으로 반복되는 키의 경우 X11은 각 반복 키에 대해 release-event와 key-press-event를 즉시 보냅니다. 따라서 키를 누르고 있으면 클라이언트에 XCB_BUTTON_RELEASE/XCB_BUTTON_PRESS- 이벤트가 보내집니다 (xev 또는 this page의 끝에있는 소스로 시도해보십시오).

그런 다음 qt (qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp)는 이러한 이벤트가 자동 반복 여부 (autorepeat case)인지 여부를 알아 내려고합니다. 릴리스가 수신되면 미리보기 기능을 사용하여 프레스 (시간 스탬프가 충분히 근접한 경우) 그렇다면 자동 반복을 가정합니다.

적어도 모든 플랫폼에서 작동하는 것은 아닙니다. 필자의 경우 (우분투 16.04를 실행하는 인텔 ® 셀러론 ® N2830 @ 2.16GHz × 2) 저스트 랩탑 (저번 노트북의 경우)에서는 수표를 받기 전에 수면 상태 (500)를 설정하는 데 도움이되었습니다. 도착할 이벤트 ... qxcbkeyboard의 1525 줄 주변에 있습니다.cpp :

// look ahead for auto-repeat 
    KeyChecker checker(source->xcb_window(), code, time, state); 
    usleep(500); // Added, 100 is to small, 200 is ok (for me) 
    xcb_generic_event_t *event = connection()->checkEvent(checker); 
    if (event) { 
    ... 

이 내용은 QTBUG-57335입니다.

주의 : X의 동작은 실 거예요 누른 키의 경우이 릴리스 프레스 시퀀스를 전송 다음

Display *dpy=...; 
Bool result; 
XkbSetDetectableAutoRepeat (dpy, true, &result); 

를 사용하지만,이 자동 반복 더 많은 변화를 필요로 사용하여 변경할 수 있습니다 탐지 논리.