Russian Qt Forum

Qt => Вопросы новичков => Тема начата: alex_beginner от Январь 13, 2012, 13:38



Название: Переход к следующему виджету по Enter
Отправлено: alex_beginner от Январь 13, 2012, 13:38
Не пойму, как мне сделать переход к следующему виджету по Enter (вместо Tab).
У некоторых виджетов есть сигнал ReturnPressed, а у других-то нет.
Ну и даже если есть сигнал, как мне устанавливать не фокус конкретного виджета, а именно сказать "перейди к следующему"?


Название: Re: Переход к следующему виджету по Enter
Отправлено: Пантер от Январь 13, 2012, 13:41
Начинай отсюда читать http://doc.qt.nokia.com/4.8-snapshot/qkeyevent.html.


Название: Re: Переход к следующему виджету по Enter
Отправлено: alex_beginner от Январь 13, 2012, 20:40
Мда, "Уж послала, так послала..." (с)  ;D

Ну, зато закаляет характер. А для лентяев (коим и сам я являюсь) опишу, как я это сделал. Может не оптимально, но работает.

1. Создаем фильтр событий окна. Там интуитивно по названию закорючек всё примерно понятно (даже мне). Это я честно списал у кого-то в инете:
Код:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() != QEvent::KeyPress)
    {
        return QObject::eventFilter(obj, event);
    }
    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
    switch (keyEvent->key()) {
    case Qt::Key_Return:
    case Qt::Key_Enter:
        if (focusNextChild()) {
            return true;
        }
        return false;
    default:
        return QObject::eventFilter(obj, event);
    }
}
2. Теперь надо инсталлировать этот фильтр для каждого нужного нам виджета (у которого д.б. такое поведение). Как сделать - на любителя, я себе написал функцию такого вида:
Код:
void MainWindow::InstallEventFilters(QObject * obj,...)
{
    va_list args;
    for(va_start(args,obj);obj;obj->installEventFilter(this),obj = va_arg(args,QObject *));
}
Ей передаётся любое число указателей на виджеты (но не меньше одного), которым надо инсталлировать обработчик. Последним элементом (признаком конца) в передаваемом списке должен быть NULL

3. В конструкторе формы вызываем что-то вроде этого:
Код:
InstallEventFilters(ui->DateCreateBegin,ui->DateCreateEnd,ui->TimeCreateBegin,ui->TimeCreateEnd,NULL);

Всё - перечисленные в вызове виджеты приобретают нужное нам поведение. Пока вроде работает.


Название: Re: Переход к следующему виджету по Enter
Отправлено: alex_beginner от Январь 13, 2012, 21:12
... однако, не всё так уж замечательно.
Если при переходе по Tab прорисовка радиокнопок и чекбоксов нормальная, то при переходе по Enter почему-то у них не появляется никакая рамочка, как будто фокус не установлен. Хотя реально установлен.
А если по форме хотя бы раз пройтись TABом, то потом уже и Enter-ом ходит нормально. Странно это.

Почему так, и как бороться? Можно ли как-то просто подменить код нажатой клавиши (чтоб он думал, что я просто TAB нажимаю)?  Если да, где это сделать и как?


Название: Re: Переход к следующему виджету по Enter
Отправлено: andrew.k от Январь 13, 2012, 23:37
Вот написал тестовый проект.
Нажатый ентер заменяется на таб.

Код
C++ (Qt)
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
   if(event->type() == QEvent::KeyPress)
   {
       QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
       if(keyEvent->key() == Qt::Key_Return)
       {
           QKeyEvent ke(QEvent::KeyPress,Qt::Key_Tab,Qt::NoModifier);
           //QCoreApplication::sendEvent(this,&ke);
           QWidget::event(&ke);
           return true;
       }
   }
   return QWidget::eventFilter(watched,event);
}
 

Работают оба варианта кстати.
Теоретически QWidget::event наверное быстрее будет работать?
Или вообще не стоит так делать? Вопрос к знатокам.
Код
C++ (Qt)
           //QCoreApplication::sendEvent(this,&ke);
           QWidget::event(&ke);
 


Название: Re: Переход к следующему виджету по Enter
Отправлено: alex_beginner от Январь 14, 2012, 13:27
Вот этот вариант:
Код:
QCoreApplication::sendEvent(this,&ke);
у меня работает нормально, и рамочки вокруг кнопок рисуются как надо.
А вот этот
Код:
QWidget::event(&ke);
работает так же, как и мой пример - немного косяково.
Ну это может особенности Windows, в других средах пока не смотрел, как оно там.

Спасибо. То, что надо.