2016-06-29 6 views
0

Итак, у меня есть приложение, где, если какая-то кнопка нажата, она воспроизводит звуковое устройство, когда кнопка отпускается, она останавливает аудиоустройство. Я использую keyPressEvent и KeyReleaseEvent осуществить это, который похож на код ниже: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 функция не работает, как я могу видеть непрерывную печать из key_0 pressed и key_0 released несмотря на то, я не освобожден 0 после того, как я его нажал. Является ли мой код неправильным или что-то еще не так?

Спасибо.

EDIT

Я думаю, что это происходит потому, что MainWindow теряет фокус клавиатуры. Как я могу узнать, какой виджет имеет фокус? Я на самом деле использую некоторые виджеты при нажатии Qt::Key_0, но я думал, что я установил все эти возможные виджеты на Qt::NoFocus, я думаю, что он не работает.

Я пытаюсь узнать, какой виджет имеет фокус, выполнив следующие действия:

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

, но он всегда печатает пустую строку. Как я могу заставить его напечатать имя виджета с фокусом на клавиатуре?

+0

Является ли ваш класс 'MainWindow' или' ConsoleMainWindow'? Похоже, в вашем вопросе есть опечатка – IAmInPLS

+0

Во-вторых, ваш код работает на меня, просто протестировал его. В документе указывается: «Обратите внимание, что если событие является сжатым событием с несколькими ключами, которое частично связано с автоматическим повторением, эта функция может возвращать либо true, либо false indeterminately'. Вы в этом случае? – IAmInPLS

+0

@IAmInPLS Извините, это была опечатка, я изменил ее. Мой класс - MainWindow. –

ответ

0

В любом случае это разрешило.

Проблема была в том, что у меня есть виджет, который является подклассом QGLWidget, который я использую, чтобы показать некоторые изображения дополненной реальности от Kinect. Этот виджет захватывает фокус клавиатуры при нажатии кнопки клавиатуры.

Чтобы решить эту проблему, мне нужно позвонить grabKeyboard функции из класса MainWindow (MainWindow подкласс QMainWindow), так this->grabKeyboard() это линия мне нужно добавить, когда key_0 кнопка нажата, так что MainWindow не потерять фокус клавиатуры, а затем, когда клавиша отпущена, мне нужно было добавить строку this->releaseKeyboard(), чтобы возобновить нормальное поведение, то есть другие виджеты могут иметь фокус клавиатуры.

1

Так как я также наткнулся на эту проблему (и grabKeyboard действительно не помог), я начал копать в qtbase. Он подключается к X11 через xcb, и по умолчанию, в случае повторных ключей, X11 отправляет для каждого повторного ключа событие выпуска, сразу же за которым следует событие нажатия клавиши. Таким образом, удерживание ключа приводит к тому, что последовательность XCB_BUTTON_RELEASE/XCB_BUTTON_PRESS-событий отправляется клиенту (проверьте его с помощью xev или источника в конце this page).

Затем qt (qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp) пытается выяснить из этих событий, независимо от того, был ли он случай автоповтора: когда получен релиз, он использует функцию просмотра, чтобы увидеть, если ее следует прессовать (с близкими временными отметками) и если да, то это предполагает авторепорту.

Это не всегда работает, по крайней мере, на всех платформах. Для моего случая (старый и устаревший медленный ноутбук (Intel® Celeron (R) CPU N2830 @ 2.16GHz × 2), работающий с ubuntu 16.04), он помог просто потушить (500) перед этой проверкой, разрешив пресс-событие после выпуска событие, чтобы прибыть ... это вокруг строки 1525 qxcbkeyboard.каст:

// 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.

Nb: Поведение X может быть изменен с помощью

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

Тогда он не будет посылать этот релиз-пресс-последовательности в случае зажать клавишу, но используя для этого потребуется больше изменений в автоповторе -detection-логика.