PDA

View Full Version : How to write correctly an event handler



franco.amato
3rd December 2009, 05:55
Hi to all,
I would know how to correctly write an event handler for example a keyPressEvent.

I wrote this event that I would catch when I press the space key:


void WaveWidget::keyPressEvent( QKeyEvent* pe )
{
switch( pe->key() )
{
case Qt::Key_Space:
{
pe->accept();
qDebug() << "Space pressed";
m_wave->playSound();
}
break;

default:
pe->ignore();
break;
}
QWidget::keyPressEvent(pe);
}

This is the correct way to write it? Must I accept the event with the right key and ignore in other case? And must I pass the event to the base class?

I don't know why in my case in doesn't work.

Best

Tanuki-no Torigava
3rd December 2009, 06: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.

Tanuki-no Torigava
3rd December 2009, 06:20
And this was taken from an example tetrix. You should have it somewhere.



void TetrixBoard::keyPressEvent(QKeyEvent *event)
{
if (!isStarted || isPaused || curPiece.shape() == NoShape) {
QFrame::keyPressEvent(event);
return;
}

switch (event->key()) {
case Qt::Key_Left:
tryMove(curPiece, curX - 1, curY);
break;
case Qt::Key_Right:
tryMove(curPiece, curX + 1, curY);
break;
case Qt::Key_Down:
tryMove(curPiece.rotatedRight(), curX, curY);
break;
case Qt::Key_Up:
tryMove(curPiece.rotatedLeft(), curX, curY);
break;
case Qt::Key_Space:
dropDown();
break;
case Qt::Key_D:
oneLineDown();
break;
default:
QFrame::keyPressEvent(event);
}
}

franco.amato
3rd December 2009, 06:24
And this was taken from an example tetrix. You should have it somewhere.



void TetrixBoard::keyPressEvent(QKeyEvent *event)
{
if (!isStarted || isPaused || curPiece.shape() == NoShape) {
QFrame::keyPressEvent(event);
return;
}

switch (event->key()) {
case Qt::Key_Left:
tryMove(curPiece, curX - 1, curY);
break;
case Qt::Key_Right:
tryMove(curPiece, curX + 1, curY);
break;
case Qt::Key_Down:
tryMove(curPiece.rotatedRight(), curX, curY);
break;
case Qt::Key_Up:
tryMove(curPiece.rotatedLeft(), curX, curY);
break;
case Qt::Key_Space:
dropDown();
break;
case Qt::Key_D:
oneLineDown();
break;
default:
QFrame::keyPressEvent(event);
}
}


Hi sorry but I didn't understand.
My class inherits from QWidget. Where my code is wrong? And why it don't catch
key event?

Best

Tanuki-no Torigava
3rd December 2009, 06:34
Ok. Looks like logic error



void WaveWidget::keyPressEvent( QKeyEvent* pe )
{
switch( pe->key() )
{
case Qt::Key_Space:
{
pe->accept();
qDebug() << "Space pressed";
m_wave->playSound();
}
break;

default:
pe->ignore(); // Do you ignore everything here?
break;
}
QWidget::keyPressEvent(pe); // so why do you call the handler for all events you receive?
}


Just trave the sequence of event.

franco.amato
3rd December 2009, 06:40
Ok. Looks like logic error



Just trave the sequence of event.

So when I have to call the ignore method?

Tanuki-no Torigava
3rd December 2009, 07:11
I wonder which keys you need to process? If all - just remove the last call to parent handler instance, if not - don't ignore.

Tanuki-no Torigava
3rd December 2009, 07:14
And please look at this once again:


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

Did you call setFocusPolicy?

Lykurg
3rd December 2009, 07:23
And please look at this once again:



Did you call setFocusPolicy?


Guys read the docs carefully! First ignore() and accept() are not necessary! and setFocusPolicy is also not required. The user can activate the widget himself using the mouse or tab...

So a simple implementation would be:

// eats space
void WaveWidget::keyPressEvent( QKeyEvent* pe )
{
switch( pe->key() )
{
case Qt::Key_Space:
{
qDebug() << "Space pressed";
m_wave->playSound();
}
break;

default:
QWidget::keyPressEvent(pe);
break;
}
}

// just plays a sound whenever space is pressed
void WaveWidget::keyPressEvent( QKeyEvent* pe )
{
switch( pe->key() )
{
case Qt::Key_Space:
{
qDebug() << "Space pressed";
m_wave->playSound();
}
break;

default:
break;
}
QWidget::keyPressEvent(pe);
}


assuming QWidget is your base class. And such problems should be better posted in the Newbie section.

franco.amato
3rd December 2009, 07:32
Guys read the docs carefully! First ignore() and accept() are not necessary! and setFocusPolicy is also not required. The user can activate the widget himself using the mouse or tab...

So a simple implementation would be:

// eats space
void WaveWidget::keyPressEvent( QKeyEvent* pe )
{
switch( pe->key() )
{
case Qt::Key_Space:
{
qDebug() << "Space pressed";
m_wave->playSound();
}
break;

default:
QWidget::keyPressEvent(pe);
break;
}
}

// just plays a sound whenever space is pressed
void WaveWidget::keyPressEvent( QKeyEvent* pe )
{
switch( pe->key() )
{
case Qt::Key_Space:
{
qDebug() << "Space pressed";
m_wave->playSound();
}
break;

default:
break;
}
QWidget::keyPressEvent(pe);
}


assuming QWidget is your base class. And such problems should be better posted in the Newbie section.

Sorry but in the second case I always pass the event to the base class and in the first one only in the default case...which is the difference?

Lykurg
3rd December 2009, 07:52
Sorry but in the second case I always pass the event to the base class and in the first one only in the default case...which is the difference?

If you have a QWidget as base class: No difference. But e.g. your base class is a QLineEdit, then in the first case the user can not write a space in the line edit. Which one you use depends on your requirements I don't know.