Russian Qt Forum

Qt => Общие вопросы => Тема начата: taifun от Декабрь 22, 2009, 13:30



Название: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 22, 2009, 13:30
Здраствуйте! Есть функция:
Код:
void MainWindow::keyPressEvent(QKeyEvent* event)
{

  switch(event->key())
  {
   case Qt::Key_Up:
      QMessageBox msgBox;
      msgBox.setWindowTitle(trUtf8("Внимание!"));
      msgBox.setText(trUtf8("Уведомление:"));
      msgBox.setInformativeText(trUtf8("Нажата кнопка ВВЕРХ."));
      msgBox.setIcon(QMessageBox::Information);
      msgBox.exec();
      break;

  }
}
ошибок не выдает, все собирается и компилируется, но при нажатии на кнопку со стрелочкой вверх ничего не происходит  ???


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: BRE от Декабрь 22, 2009, 14:00
Скорее всего кто-то из детей это событие обрабатывает.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 22, 2009, 14:12
Скорее всего кто-то из детей это событие обрабатывает.

Спасибо, но не помогло.... почему кто-то из детей? что не так?


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: BRE от Декабрь 22, 2009, 14:32
Спасибо, но не помогло.... почему кто-то из детей? что не так?
Да все так.  :)
Такие события сначала доставляются виджетам имеющим фокус ввода, и скорее всего он его обрабатывает. Поэтому, до MainWindow оно и не доходит.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 22, 2009, 15:53
На форме есть только одна кнопка и виджет, в котором я рисую. События мыши обрабатываются нормально, а от клавиатуры вообще не как  ???


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: BRE от Декабрь 22, 2009, 16:16
void QWidget::keyPressEvent ( QKeyEvent * event )   [virtual protected]

This event handler, for event event, can be reimplemented in a subclass to receive key press events for the widget.

A widget must call setFocusPolicy() to accept focus initially and have focus in order to receive a key press event.

If you reimplement this handler, it is very important that you call the base class implementation if you do not act upon the key.

The default implementation closes popup widgets if the user presses Esc. Otherwise the event is ignored, so that the widget's parent can interpret it.

Note that QKeyEvent starts with isAccepted() == true, so you do not need to call QKeyEvent::accept() - just do not call the base class implementation if you act upon the key.

See also keyReleaseEvent(), setFocusPolicy(), focusInEvent(), focusOutEvent(), event(), QKeyEvent, and Tetrix Example.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: BRE от Декабрь 22, 2009, 16:31
Вот простейший рабочий код:
Код
C++ (Qt)
class MainWindow : public QMainWindow
{
Q_OBJECT
 
public:
MainWindow();
 
protected:
void keyPressEvent( QKeyEvent *event );
};
 
MainWindow::MainWindow()
: QMainWindow( 0 )
{
QWidget *widget = new QWidget( this );
setCentralWidget( widget );
}
 
void MainWindow::keyPressEvent( QKeyEvent *event )
{
switch( event->key() )
{
case Qt::Key_Up:
qDebug() << "Key Up pressed";
break;
 
default:
qDebug() << "Key pressed:" << event->key();
break;
}
}
 


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: panAlexey от Декабрь 22, 2009, 16:47
На форме есть только одна кнопка и виджет, в котором я рисую. События мыши обрабатываются нормально, а от клавиатуры вообще не как  ???
скорее всего у тебя клавиатурные события получает фокусный (тот на котором фокус) виджет.
И это скорее всего кнопка.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Igors от Декабрь 22, 2009, 17:01
exec крутит свой EventLoop и до MainWindow дело не доходит. Тот же обработчик но для msgBox получит keyPressed 


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 23, 2009, 12:11
Более менее разобрался, покрайней мере достиг нужного результат спасибо! Но хочу спросить вот что:
есть у меня mainwindow.cpp (класс диалогового окна) и gltest.cpp (тут рисую с помощью OpenGL). В mainwindow.cpp в конструкторе пишу

Код:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    wgOpenGL = new glTest(ui->ViewOpenGl);
    ui->ViewOpenGl->setFocusPolicy(Qt::StrongFocus);
    ui->ViewOpenGl->setFocus(Qt::ActiveWindowFocusReason);
}

и обработка событий клавиш
Код:
void MainWindow::keyPressEvent( QKeyEvent *event )
{
    wgOpenGL->keyPressEvent(event);

}

а в gltest.cpp уже обрабатываю:

Код:
void glTest::keyPressEvent(QKeyEvent* event)
{

  switch(event->key())
  {
   case Qt::Key_Up:
    qDebug() << "Key Up pressed!";
        setXRotation(xRot + 5);
    qDebug() << trUtf8("Объект повернут на 10 градусов по оси Х");
    break;

   case Qt::Key_Down:
    qDebug() << "Key Down pressed!";
    setXRotation(xRot - 5);
    break;

   case Qt::Key_Left:
    qDebug() << "Key Left pressed!";
    setYRotation(yRot + 5);
    break;

   case Qt::Key_Right:
    qDebug() << "Key Right pressed!";
    setYRotation(yRot - 5);
    break;

  }

  updateGL();

}

Вот мне кажется, что я чет намудрил, можно проще или нет? можно ли обойтись без этого
Код:
void MainWindow::keyPressEvent( QKeyEvent *event )
{
    wgOpenGL->keyPressEvent(event);
}


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 23, 2009, 16:35
Да, переопределить keyPressedEvent() не у MainWindow, а у glTest.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 23, 2009, 16:40
Да, переопределить keyPressedEvent() не у MainWindow, а у glTest.
а как это сделать  ???


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 23, 2009, 16:44
Убрать void keyPressEvent(QEvent*) в обьявлении MainwWindow и добавить в обьявлении glTest.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 23, 2009, 17:01
Убрать void keyPressEvent(QEvent*) в обьявлении MainwWindow и добавить в обьявлении glTest.

я закоментировал
Код:
void MainWindow::keyPressEvent( QKeyEvent *event )
{
    wgOpenGL->keyPressEvent(event);
}

и void keyPressEvent() в .h файле, а в glTest мне ничего не надо добавлять там и так все написано ......
после это перестало работать...
может я не так Вас понял?


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 23, 2009, 17:05
Понимаете, плохое знание C++ вместе с описаниями вроде "перестало работать" никак не способствуют чтобы вам помогли. Телепаты, увы, в отпуске.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 23, 2009, 17:24
Понимаете, плохое знание C++ вместе с описаниями вроде "перестало работать" никак не способствуют чтобы вам помогли. Телепаты, увы, в отпуске.

Да я считаю, что у меня чертовспи плохое знание С++ и я пытаюсь исправить это ...
Извиняюсь за "перестало работать".  Я хотел сказать, что программа перестала реагировать на нажатия кнопок клавиатуры, после того как я удалил в MainWindow.cpp функцию keyPressEvent()


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Igors от Декабрь 23, 2009, 17:41
Я хотел сказать, что программа перестала реагировать на нажатия кнопок клавиатуры, после того как я удалил в MainWindow.cpp функцию keyPressEvent()
Значит потеряли фокус, ищите. Попробуйте кликнуть на wgOpeGL поможет ли это с клавиатурой?


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 23, 2009, 17:59
Думаю так же, скорее всего фокус был на одном из элементов управления рядом с wgOpenGL (кнопке?), которая игнорировала кливишу и отправляла событие в MainWindow. Если смотреть с этой точки зрения - ваш оригинальный код вполне имеет право на жизнь.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 24, 2009, 14:28
Я вот тут поигрался немного, написал код так:
Код:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    wgOpenGL = new glTest(ui->ViewOpenGl);
    qDebug() << "ViewOpenGl have focus - " << ui->ViewOpenGl->hasFocus();
    ui->ViewOpenGl->setFocusPolicy(Qt::StrongFocus);
    ui->ViewOpenGl->setFocus(Qt::MouseFocusReason);
    qDebug() << "ViewOpenGl have focus - " << ui->ViewOpenGl->hasFocus();
}

void MainWindow::keyPressEvent( QKeyEvent *event )
{
       qDebug() << "************************************************************";
       qDebug() << "ViewOpenGl have focus - "       << ui->ViewOpenGl->hasFocus();
       qDebug() << "centralWidget have focus - "    << ui->centralWidget->hasFocus();
       qDebug() << "Exit have focus - "             << ui->Exit->hasFocus();
       qDebug() << "mainToolBar have focus - "      << ui->mainToolBar->hasFocus();
       qDebug() << "menuBar have focus - "          << ui->menuBar->hasFocus();
       qDebug() << "statusBar have focus - "        << ui->statusBar->hasFocus();
       qDebug() << "************************************************************";

       wgOpenGL->keyPressEvent(event);

}


и увидел вот что:
Код:
ViewOpenGl have focus -  false 
ViewOpenGl have focus -  false
************************************************************
ViewOpenGl have focus -  true
centralWidget have focus -  false
Exit have focus -  false
mainToolBar have focus -  false
menuBar have focus -  false
statusBar have focus -  false
************************************************************
Key Up pressed!

Я вот не понял почему после ui->ViewOpenGl->setFocus(Qt::MouseFocusReason);     ViewOpenGl - не получил фокус. а после того как нажал на кнопку фокус уже есть у него. Я ж задал ему фокус ...

А теперь я сейчас удалю void MainWindow::keyPressEvent( QKeyEvent *event ), а куда мне написать код вывода информации кто имеет фокус, а кто нет? - Таким образом хочу отследить кто фокус все-таки получает, раз я его теряю


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 24, 2009, 14:32
qApp->focusWidget()


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 24, 2009, 15:33
qApp->focusWidget()

Код:
qDebug() << "Widget have focus - " << qApp->focusWidget()->objectName();
Безусловно меньше кода, но куда мне поместить эту строку(функцию keyPressEvent в MainWindow.cpp закоментировал), вставлять в конструктор MainWindow нет смысла(но я все равно попробывал - интересно было - результат: "The program has unexpectedly finished.") Куда же я могу эту функцию поместить, что бы увидеть у какого виджета фокус?


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 24, 2009, 15:38
В слот, подсоединённый к QApplication::focusChanged().


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 24, 2009, 16:24
вот так написал ...
Код:
void MainWindow::init()
{
     QObject::connect(qApp, SIGNAL(focusChanged()), this, SLOT(findFW()));
}

void MainWindow::findFW()
{
    qDebug() << "Widget have focus - " << qApp->focusWidget()->objectName();
}


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void init();

public slots:
    void findFW();

protected:
    //void keyPressEvent( QKeyEvent *event );

private:
    glTest *wgOpenGL;
    Ui::MainWindow *ui;

};
эээх... ошибки нет, но и не работает


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 24, 2009, 16:43
После показа окна оно само расставляет фокусы, думаю, из конструктора setFocus() нужно вынести куда-либо ещё, например в обработку события showEvent().


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Igors от Декабрь 24, 2009, 17:08
Не вижу ничего плохого в том что MainWindow отдает какие-то нажатия клавиш wgOpenGL (даже если он не в фокусе). А если уж привязываться к фокусу то надо как-то это показать в самом  wgOpenGL (напр. толстая рамка в фокусе, тонкая - без). Это и в UI по делу и с отладкой легче  :) 


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 25, 2009, 11:38
Не вижу ничего плохого в том что MainWindow отдает какие-то нажатия клавиш wgOpenGL (даже если он не в фокусе). А если уж привязываться к фокусу то надо как-то это показать в самом  wgOpenGL (напр. толстая рамка в фокусе, тонкая - без). Это и в UI по делу и с отладкой легче  :) 
То же не вижу ... но теперь уже хочется разобраться что да как, ведь пригодится в будущем.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 25, 2009, 12:23
для быстроты  и наглядности сделал так:
Код:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    wgOpenGL = new glTest(ui->ViewOpenGl);
    qDebug() << "ViewOpenGl have focus - " << ui->ViewOpenGl->hasFocus();
    ui->ViewOpenGl->setFocusPolicy(Qt::TabFocus);
    ui->ViewOpenGl->setFocus(Qt::TabFocusReason);
    qDebug() << "ViewOpenGl have focus - " << ui->ViewOpenGl->hasFocus();
}

void MainWindow::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "*****************************************************";
    qDebug() << "ViewOpenGl have focus - " << ui->ViewOpenGl->hasFocus();
    qDebug() << "Widget have focus - " << qApp->focusWidget()->objectName();
    qDebug() << "*****************************************************";
}

в ответ получаю:
Код:
ViewOpenGl have focus -  false 
ViewOpenGl have focus -  false
*****************************************************
ViewOpenGl have focus -  true
Widget have focus -  "ViewOpenGl"
*****************************************************
нажимаю кнопочки на клавиатуре и не какой реакции  ???


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Dendy от Декабрь 25, 2009, 12:37
Если не сложно - запакуйте и выложите код.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 25, 2009, 12:40
Если не сложно - запакуйте и выложите код.


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Igors от Декабрь 26, 2009, 16:26
С фокусом Вы заблудились в 3 соснах - поставили его не на сам OGLWidget а на виджет в который он вставлен  :). Ну и я подправил по мелочам (attachment), но, конечно, там еще пахать и пахать 


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: taifun от Декабрь 28, 2009, 16:03
С фокусом Вы заблудились в 3 соснах - поставили его не на сам OGLWidget а на виджет в который он вставлен  :). Ну и я подправил по мелочам (attachment), но, конечно, там еще пахать и пахать 

точно  в трех соснах запутался ... блин ...
А вот то что часть кода оказалась в блоке namespace { .... },  что это означает ...


Название: Re: обработка нажатий клавишь клавиатуры
Отправлено: Igors от Декабрь 28, 2009, 17:16
А вот то что часть кода оказалась в блоке namespace { .... },  что это означает ...
"anonymys namespace", эффект тот же что написать static для каждой ф-ции /переменной (т.е. доступна только в этом файле)