БлогNot. QT: обработка нажатий клавиш

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 Кб)

Этот пример лишь иллюстрирует обработку события, для фильтрации ввода в текстовые поля лучше применять валидаторы.


теги: c++ qt памятка

18.04.2015, 22:06; рейтинг: 42341