События клавиатуры

События клавиатуры очень часто обрабатываются внутри приложений. Например, при нажатии клавиши <F1> можно вывести справочную информацию, при нажатии клавиши <Enter> в однострочном текстовом поле перенести фокус ввода на другой компонент и т. д. Рассмотрим события клавиатуры подробно.

Установка фокуса ввода

В один момент времени только один компонент (или вообще не одного) может иметь фокус ввода. Для управления фокусом ввода предназначены следующие методы из класса QWidget:

  • setFocus() — устанавливает фокус ввода, если компонент находится в активном окне. Прототипы метода (первый прототип является слотом):
void setFocus()
void setFocus(Qt::FocusReason reason)

В параметре reason можно указать причину изменения фокуса ввода. Указываются следующие константы:

  • Qt::MouseFocusReason — фокус изменен с помощью мыши;
  • Qt::TabFocusReason — нажата клавиша <Tab>;
  • Qt::BacktabFocusReason — нажата комбинация клавиш <Shift>+<Tab>;
  • Qt::ActiveWindowFocusReason — окно стало активным или неактивным;
  • Qt::PopupFocusReason — открыто или закрыто всплывающее окно;
  • Qt::ShortcutFocusReason — нажата комбинация клавиш быстрого доступа;
  • Qt::MenuBarFocusReason — фокус изменился из-за меню;
  • Qt::OtherFocusReason — другая причина;
  • clearFocus() — убирает фокус ввода с компонента. Прототип метода:
void clearFocus()
  • hasFocus() — возвращает значение true, если компонент находится в фокусе ввода, и false — в противном случае. Прототип метода:
bool hasFocus() const
  • focusWidget() — возвращает указатель на последний компонент, для которого вызывался метод setFocus(). Для компонентов верхнего уровня возвращается указатель на компонент, который получит фокус после того, как окно станет активным. Прототип метода:
QWidget *focusWidget() const
  • setFocusProxy() — позволяет передать указатель на компонент, который будет получать фокус ввода вместо текущего компонента. Прототип метода:
void setFocusProxy(QWidget *w)
  • focusProxy() — возвращает указатель на компонент, который обрабатывает фокус ввода вместо текущего компонента. Если компонента нет, то метод возвращает нулевой указатель. Прототип метода:
QWidget *focusProxy() const
  • focusNextChild() — находит следующий компонент, которому можно передать фокус и передает фокус. Аналогично нажатию клавиши <Tab>. Метод возвращает значение true, если компонент найден, и false — в противном случае. Прототип метода:
protected:
   bool focusNextChild()
  • focusPreviousChild() — находит предыдущий компонент, которому можно передать фокус и передает фокус. Аналогично нажатию комбинации клавиш <Shift>+<Tab>. Метод возвращает значение true, если компонент найден, и false — в противном случае. Прототип метода:
protected:
   bool focusPreviousChild()
  • focusNextPrevChild() — если в параметре указано значение true, то метод аналогичен методу focusNextChild(). Если в параметре указано значение false, то метод аналогичен методу focusPreviousChild(). Метод возвращает значение true, если компонент найден, и false — в противном случае. Прототип метода:
protected:
   virtual bool focusNextPrevChild(bool next)
  • setTabOrder() — позволяет задать последовательность смены фокуса при нажатии клавиши <Tab>. Метод является статическим. Прототип метода:
static void setTabOrder(QWidget *first, QWidget *second)

В параметре second передается указатель на компонент, на который переместится фокус с компонента first. Если компонентов много, то метод вызывается несколько раз. Пример указания цепочки перехода widget1 -> widget2 -> widget3 -> widget4:

QWidget::setTabOrder(widget1, widget2)
QWidget::setTabOrder(widget2, widget3)
QWidget::setTabOrder(widget3, widget4)
  • setFocusPolicy() — задает способ получения фокуса компонентом. Прототип метода:
void setFocusPolicy(Qt::FocusPolicy policy)

В качестве параметра указываются следующие константы:

  • Qt::NoFocus — компонент не может получать фокус;
  • Qt::TabFocus — получает фокус с помощью клавиши <Tab>;
  • Qt::ClickFocus — получает фокус с помощью щелчка мышью;
  • Qt::StrongFocus — получает фокус с помощью клавиши <Tab> и щелчка мышью;
  • Qt::WheelFocus — получает фокус с помощью клавиши <Tab>, щелчка мышью и колесика мыши;
  • focusPolicy() — возвращает текущий способ получения фокуса. Прототип метода:
Qt::FocusPolicy focusPolicy() const
  • grabKeyboard() — захватывает ввод с клавиатуры. Другие компоненты не будут получать события клавиатуры, пока не будет вызван метод releaseKeyboard();. Прототип метода:
void grabKeyboard()
  • releaseKeyboard() — освобождает захваченный ранее ввод с клавиатуры. Прототип метода:
void releaseKeyboard()

Получить указатель на компонент, находящийся в фокусе ввода, позволяет статический метод focusWidget() из класса QApplication. Прототип метода:

static QWidget *focusWidget()

Если ни один компонент не имеет фокуса ввода, то метод возвращает нулевой указатель. Не путайте этот метод с одноименным методом из класса QWidget.

Обработать получение и потерю фокуса ввода позволяют следующие методы:

  • focusInEvent() — вызывается при получении фокуса ввода. Прототип метода:
virtual void focusInEvent(QFocusEvent *event)
  • focusOutEvent() — вызывается при потере фокуса ввода. Прототип метода:
virtual void focusOutEvent(QFocusEvent *event)

Через параметр доступен экземпляр класса QFocusEvent, который содержит следующие методы:

  • gotFocus() — возвращает значение true, если тип события QEvent::FocusIn, и false — в противном случае. Прототип метода:
bool gotFocus() const
  • lostFocus() — возвращает значение true, если тип события QEvent::FocusOut, и false — в противном случае. Прототип метода:
bool lostFocus() const
  • reason() — возвращает причину установки фокуса. Значение аналогично значению параметра reason в методе setFocus(). Прототип метода:
Qt::FocusReason reason() const

Создадим окно с кнопкой и двумя однострочными полями ввода. Для полей ввода обработаем получение и потерю фокуса ввода, а при нажатии кнопки установим фокус ввода на второе поле. Кроме того, зададим последовательность перехода при нажатии клавиши <Tab>. Содержимое файла mylineedit.h приведено в листинге 4.30, файла mylineedit.cpp — в листинге 4.31, файла widget.h — в листинге 4.32, файла widget.cpp — в листинге 4.33, а файла main.cpp — в листинге 4.34.

Листинг 4.30. Содержимое файла mylineedit.h

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QWidget>
#include <QLineEdit>
#include <QFocusEvent>

class MyLineEdit : public QLineEdit
{
   Q_OBJECT
public:
   MyLineEdit(int id, QWidget *parent=nullptr);
protected:
   void focusInEvent(QFocusEvent *e) override;
   void focusOutEvent(QFocusEvent *e) override;
private:
   int id_;
};

#endif // MYLINEEDIT_H

Листинг 4.31. Содержимое файла mylineedit.cpp

#include "mylineedit.h"

MyLineEdit::MyLineEdit(int id, QWidget *parent)
   : QLineEdit(parent), id_(id)
{}

void MyLineEdit::focusInEvent(QFocusEvent *e)
{
   qDebug() << "Получен фокус полем" << id_;
   QLineEdit::focusInEvent(e);
}

void MyLineEdit::focusOutEvent(QFocusEvent *e)
{
   qDebug() << "Потерян фокус полем" << id_;
   QLineEdit::focusOutEvent(e);
}

Листинг 4.32. Содержимое файла widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include "mylineedit.h"

class Widget : public QWidget
{
   Q_OBJECT

public:
   Widget(QWidget *parent=nullptr);
   ~Widget();
private:
   MyLineEdit *line1;
   MyLineEdit *line2;
   QPushButton *btn1;
   QVBoxLayout *vbox;
};
#endif // WIDGET_H

Листинг 4.33. Содержимое файла widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
   : QWidget(parent)
{
   line1 = new MyLineEdit(1);
   line2 = new MyLineEdit(2);
   btn1 = new QPushButton("Установить фокус на поле 2");
   vbox = new QVBoxLayout();
   vbox->addWidget(btn1);
   vbox->addWidget(line1);
   vbox->addWidget(line2);
   setLayout(vbox);
   QObject::connect(btn1, SIGNAL(clicked()),
                    line2, SLOT(setFocus()));
   // Задаем порядок обхода с помощью клавиши <Tab>
   QWidget::setTabOrder(line1, line2);
   QWidget::setTabOrder(line2, btn1);
}

Widget::~Widget() {}

Листинг 4.34. Содержимое файла main.cpp

#include "widget.h"

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   Widget window;
   window.setWindowTitle("Установка фокуса ввода");
   window.resize(350, 100);
   window.show();
   return app.exec();
}

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов