QT: обработка нажатий клавиш
Казалось бы, обычный вопрос... но вызвал сегодня вопросы, раз так, кину для памяти пример.
В принципе, достаточно в своём приложении (виджете) унаследоваться от QWidget
и реализовать в коде метод keyPressEvent
- обработку событий от клавиатуры.
На самом деле, в QWidget
есть ещё много чего, просто Qt - не Studio или Builder, не всегда нужное событие "находится в списке":
paintEvent()
возникает, когда есть необходимость в перерисовке виджета. Любой виджет, отображающий пользовательский контент, должен его реализовать такой обработчик. Перерисовка, использующаяQPainter
, может происходить только вpaintEvent()
или в функциях, вызываемых изpaintEvent()
.resizeEvent()
возникает, когда виджет изменил размеры.mousePressEvent()
возникает, если нажата кнопка мыши в тот момент, когда мышь находилась внутри виджета, или если он захвачен мышкой с помощьюgrabMouse()
. Нажатие кнопки мыши без отпускания - это фактически то же самое, что и вызовgrabMouse()
.mouseReleaseEvent()
возникает, когда кнопка мыши отпускается. Виджет получит событие отпускания кнопки мыши, если до этого он получил событие нажатие кнопки мыши. Это означает, что усли пользователь нажал кнопку мыши внутри вашего виджета, затем переместил мышку куда-нибудь и там отпустил кнопку, то ваш виджет получит событие отпускания мыши. Существует одно исключение: если при нажатии кнопки появляется всплывающее меню, оно немедленно перехватит события от мыши.mouseDoubleClickEvent()
возникает, когда пользователь дважды щелкнет по виджету. Если пользователь использовал двойной щелчок, виджет получит событие нажатия кнопки, событие отпускания кнопки и в заключение событие о втором щелчке (несколько событий о перемещении мыши могут прийти, если пользователь во время операции не удержал мышку на месте). Невозможно отличить одинарный щелчок от двойного, пока не произойдёт второй щелчок. Это одна из причин, почему многие книги о разработке пользовательского интерфейса рекомендуют, чтобы двойной щелчок был предпочтительнее, чем одинарный, при переключении между различными операциями.
У виджетов, которые разрешают ввод с клавиатуры, нужно переопределить немного больше функций:
keyPressEvent()
возникает, когда клавиша была нажата, и ещё раз, когда клавиша удерживается для автоповтора. Нажатие клавишиTab
и сочетанияShift+Tab
передается виджету только если он не использует механизм смены фокуса. Для перехвата нажатия этих клавишей вы должны переопределитьQWidget::event()
.focusInEvent()
возникает, когда виджет получает фокус ввода с клавиатуры (если вы вызвалиsetFocusPolicy()
). Хорошо написанные виджеты показывают, что они получили фокус ввода с клавиатуры в ясной и простой форме.focusOutEvent()
возникает, когда виджет теряет фокус ввода с клавиатуры.
Вам может потребоваться переопределить несколько менее распространенных обработчиков событий:
mouseMoveEvent()
возникает, когда мышка перемещается с нажатой кнопкой. Это может быть полезно при выполнении операции перетаскивания. Если вы вызвалиsetMouseTracking(true)
, вы будете получать события перемещения мыши, даже если ее кнопка не нажата.keyReleaseEvent()
возникает, когда клавиша отпущена и пока она нажата (если это клавиша с автоповтором). В этом случае виджет получит два события об отпускании и нажатии клавиши для каждого повтора. Нажатие клавишиTab
и сочетанияShift+Tab
передается виджету только если он не использует механизм смены фокуса. Для перехвата нажатия этих клавишей вы должны переопределитьQWidget::event()
.wheelEvent()
возникает, если пользователь вращает колесико мыши в то время, как виджет получил фокус.enterEvent()
возникает, когда мышка попадает в пространство, занимаемое виджетом на экране (исключая пространство, занятое дочерними виджетами).leaveEvent()
возникает, когда мышка покидает пространство виджета. Когда мышка переходит в пространство, занимаемое дочерним виджетом, событиеleaveEvent()
не происходит.moveEvent()
возникает, когда виджет перемещается относительно своего родителя.closeEvent()
возникает, когда пользователь закрывает виджет (или когда вызывается функцияclose()
).
Ну есть ещё всякая экзотика, которую пропустим.
А вот пример. Виджет располагает метку QLabel
на всё своё окно, а мы можем вводить в неё с клавиатуры целое число, ставить перед ним знак "-" или "+", стирать последний символ нажатием BackSpace или стирать всё нажатием Delete. Максимальная длина ввода ограничена 16 символами.
Файл main.cpp
#include "widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.setWindowTitle("KeyPress Demo"); w.resize(300,100); w.setFixedSize(300,100); w.show(); return a.exec(); }
Файл widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QGridLayout> #include <QLabel> #include <QKeyEvent> #include <Qt> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); private: QGridLayout *myLayout; QLabel *label1; protected: virtual void keyPressEvent(QKeyEvent *event); }; #endif // WIDGET_H
Файл widget.cpp
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { label1 = new QLabel(""); label1->setStyleSheet("font-size: 30px"); myLayout = new QGridLayout; myLayout->addWidget(label1, 0, 0, 1, 1); setLayout(myLayout); } void Widget::keyPressEvent(QKeyEvent *event) { QString oldText = label1->text(); int key=event->key();//event->key() - целочисленный код клавиши QString str = QString(QChar(key)); if (key>=Qt::Key_0 && key<=Qt::Key_9) { //Цифровые клавиши 0..9 label1->setText(oldText+str); } else if (key==Qt::Key_Backspace) { //BackSpace стирает символ label1->setText(oldText.left(oldText.length()-1)); } else if (key==Qt::Key_Delete) { //Delete стирает всё label1->setText(""); } else if (key==Qt::Key_Plus || key==Qt::Key_Minus) { if (oldText.startsWith("-") || oldText.startsWith("+")) oldText = oldText.right(oldText.length()-1); label1->setText(str+oldText); } oldText = label1->text(); if (oldText.length()>=16) //ограничение на длину вводимой строки label1->setText(oldText.left(16)); }
Скачать этот проект QT5 в архиве .zip, развернуть, не создавая новой папки (2 Кб)
Этот пример лишь иллюстрирует обработку события, для фильтрации ввода в текстовые поля лучше применять валидаторы.
18.04.2015, 22:06 [65274 просмотра]