Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: tim474 от Январь 31, 2010, 04:28



Название: Вопросы по навигации по виджетам с помощью клавиатуры
Отправлено: tim474 от Январь 31, 2010, 04:28
Возможно вопрос тупой, но документация по Qt слишком обширная, поэтому сразу найти нужное затруднительно, тем более языковой барьер мешает. А я только начал учиться программированию с использованием Qt.
Допустим, я хочу написать программу, управляемую только с помощью клавиатуры, геймпада или пульта ДУ. Для начала возникает проблема навигации по виджетам, в частности, "ползункам" QSlider и Phonon::VolumeSlider. Я хочу, чтобы, допустим, клавишами up и down переключался виджет, на котором фокус, а кнопками left и right непосредственно передвигать эти слайдеры.
На предмет чего изучать документацию, чтобы сделать это?


Название: Re: Вопросы по навигации по виджетам с помощью клавиатуры
Отправлено: DS_tm от Январь 31, 2010, 13:03
У каждого виджета есть протектные виртуальные функции обработки сообщений, к примеру:

Код
C++ (Qt)
virtual void keyPressEvent ( QKeyEvent * event )
virtual void keyReleaseEvent ( QKeyEvent * event )
virtual void mouseDoubleClickEvent ( QMouseEvent * event )
virtual void mouseMoveEvent ( QMouseEvent * event )
virtual void mousePressEvent ( QMouseEvent * event )
virtual void mouseReleaseEvent ( QMouseEvent * event )
 

Соответстыенно можно переопределить нужную функцию, и используя функции QEvent классов (QKeyEvent::key()) понять, что нажал пльзователь.

Альтернативный вариант, это фильтрация сообщений, с помощью функций QObject::installEventFilter(), QObject::eventFilter().

По поводу фокуса, тут тоже есть два варианта: во-первых можно вызвать функцию setFocus() для виджета, на который должен перейти фокус; во-вторых можно вызвать в родительсом виджете функцию focusNextChild (), но при этом должна быть правильно расставлена последовательность табов (мне этот вариант кажеться более правильным, так как не меняет логики интерфейса).


Название: Re: Вопросы по навигации по виджетам с помощью клавиатуры
Отправлено: SABROG от Январь 31, 2010, 14:32
В качестве альтернативного варианта можно посмотреть в сторону QStateMachine, а именно на классы QKeyEventTransition или QEventTransition. Несмотря на кажущийся оверхед и возможность пойти простым путем используя переопределение keyPressEvent у подхода состояний есть преимущество. Если зажать какую-либо клавишу, то keyPressEvent будет вызываться очень часто, при этом как определить, что это не мы так часто долбим по клавише, а просто зажали кнопку и держим? Из-за того, что QStateMachine разделяет состояния после первого же нажатия на кнопку будет установлено новое состояние, при этом последующие приходы QKeyEvent (если мы зажали кнопку) будут естественно проигнорированы. В случае с переопределением keyPressEvent() пришлось бы каждый раз проверять какую команду обрабатывает в данный момент наша программа (если предположить многопоточный вариант приложения), а если однопоточный, то при долгой обработки одного нажатия (при зажатой клавише) в очереди их скопится столько, что на экране можно будет наблюдать медленное перемещение чего-либо (выделения, элемента), которое нельзя будет остановить нажав клавишу влево например, если перемещение идет вправо. Т.е. это как скользить по льду, ты разогнался и скользишь, а обратно скользить сможешь только когда достигнешь конца или не остановишься под силой трения. Такое поведение очень часто можно наблюдать в винде, когда она дико тормозит. Ты выбрал элемент меню и зажал вниз, чтобы выбрать другой элемент, а ничего не происходит (выделение не двигается), а когда винда отлагает ты начинаешь наблюдать анимацию - все что ты нажимал, кликал - все начинает обрабатываться и остановить это нельзя.