PDA

View Full Version : keyboard - detecting key pressed



Tomasz
18th April 2011, 19:04
Hello!

I've got simple application in which I need to use 4 keyboard keys (arrows) to move point on my widget. I've got something like this in main window:



void MainWindow::keyPressEvent( QKeyEvent *k )
{
switch ( k->key() )
{
case Qt::Key_Up:
qDebug() << "UP";
break;
case Qt::Key_Down:
qDebug() << "DOWN";
break;
case Qt::Key_Left:
qDebug() << "LEFT";
break;
case Qt::Key_Right:
qDebug() << "RIGHT";
break;
default:
qDebug() << k->key() << endl;
break;
}
}


Inside I wanted to put function which changes coordinates of point inside widget. But only up/down keys works (prompt goes to first text edit window). How can I make it other way? I've read about qshortcuts but I don't know if I can use it (it can by shortcuts to real buttons on my application - then I'll make them).

thanks in advance
best regards
Tomasz

wysota
18th April 2011, 19:10
Could you explain what you mean by this sentence?

But only up/down keys works (prompt goes to first text edit window).

Tomasz
18th April 2011, 20:30
I've got two text QLineEdit fields. At start of application when I press UP or DOWN cursor/prompt goes to first field and stays there. Up/Down arrows works but when I press other keys (Left/Right or letters) I can't see qDebug() message - cursor stays in that field and It goes to right or left or writes letter which I pressed.
I've got idea to use 4 QButton instead of keyboard but keyboard is more comfortable (maybe I should use 4 QButton and QShorcut? - but I don't know how to use it with that buttons or if It's even possible).

thanks in advance
best regards
Tomasz

wysota
18th April 2011, 20:37
Up/Down arrows works but when I press other keys (Left/Right or letters) I can't see qDebug() message - cursor stays in that field and It goes to right or left or writes letter which I pressed.
That's because the line edit consumes the event before it reaches the window object.


I've got idea to use 4 QButton instead of keyboard but keyboard is more comfortable (maybe I should use 4 QButton and QShorcut? - but I don't know how to use it with that buttons or if It's even possible).

I don't understand what you want but if you want to intercept key events before they reach their destinations, you need to use event filters.

Tomasz
18th April 2011, 20:57
That's because the line edit consumes the event before it reaches the window object.
I don't understand what you want but if you want to intercept key events before they reach their destinations, you need to use event filters.

I've wrote my event filter, it looks like this:



class KeyboardFilter : public QObject
{
Q_OBJECT

public:
KeyboardFilter( QObject *parent = 0 ) : QObject( parent ) {}

signals:
void up_arrow();
void down_arrow();
void left_arrow();
void right_arrow();

protected:
bool eventFilter( QObject *dist, QEvent *event )
{
if( event->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );

if( QString("1234567890").indexOf( keyEvent->text() ) == -1 ) return true;
else if ( keyEvent->key() == Qt::Key_Up ) {emit up_arrow(); return true;}
else if ( keyEvent->key() == Qt::Key_Down ) {emit down_arrow(); return true;}
else if ( keyEvent->key() == Qt::Key_Left ) {emit left_arrow(); return true;}
else if ( keyEvent->key() == Qt::Key_Right ) {emit right_arrow(); return true;}
}

return false;
}
};


Almost everything works fine except Backspace key. How can I make It work in that text field on which that filter is installed?

thanks in advance
best regards
Tomasz

wysota
18th April 2011, 23:59
How can I make It work in that text field on which that filter is installed?
Try to avoid using words such as "it" and "that" if you're not sure it is clear what they refer to. I have no idea what you want. I would say line #28 of your snippet is wrong, though. You should probably call the base class implementation instead of returning false.

Tomasz
19th April 2011, 00:55
Try to avoid using words such as "it" and "that" if you're not sure it is clear what they refer to. I have no idea what you want. I would say line #28 of your snippet is wrong, though. You should probably call the base class implementation instead of returning false.

I want my filter not response to backspace key (so clearing text in text field would be possible). I still don't get events thing very well. Probably You're right about base class implementation, but what it would be in that case? QLineEdit::keyPressEvent?

thanks in advance
best regards
Tomasz

wysota
19th April 2011, 01:35
I want my filter not response to backspace key (so clearing text in text field would be possible).
Then don't return true from the event filter for the backspace key.


Probably You're right about base class implementation, but what it would be in that case? QLineEdit::keyPressEvent?
No, the base class implementation of the method you're currently implementing - eventFilter().

Tomasz
19th April 2011, 13:02
How should I call eventFilter in that case?



class KeyboardFilter : public QObject
{
Q_OBJECT

public:
KeyboardFilter( QObject *parent = 0 ) : QObject( parent ) {}

signals:
void up_arrow();
void down_arrow();
void left_arrow();
void right_arrow();

protected:
bool eventFilter( QObject *dist, QEvent *event )
{
if( event->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );

if( QString("1234567890").indexOf( keyEvent->text() ) == -1 ) return true;
else if ( keyEvent->key() == Qt::Key_Backspace ) eventFilter(dist, event);
else if ( keyEvent->key() == Qt::Key_Up ) {emit up_arrow(); return true;}
else if ( keyEvent->key() == Qt::Key_Down ) {emit down_arrow(); return true;}
else if ( keyEvent->key() == Qt::Key_Left ) {emit left_arrow(); return true;}
else if ( keyEvent->key() == Qt::Key_Right ) {emit right_arrow(); return true;}

}

return false;

}
};


Should It be called for existing object (myLineEdit->eventFilter) or in different way?

thanks in advance
best regards
Tomasz

wysota
19th April 2011, 13:41
The convention is:

ParentClassName::methodName(arguments);

Since you're not handling backspace yourself then you certainly shouldn't add an entry for it in your code. Just call the base class implementation instead of returning false although since your base class is QObject that doesn't do any filtering of its own return false should be fine too. I have no idea what you are trying to do but I have to admit your implementation is... odd. Especially the part where you consume the event if the text of the event doesn't contain a number. It is obvious none of the if blocks below will ever fire as none of the keys will generate a digit when pressed. I think you might be misinterpreting what QKeyEvent::text() does. Are you sure QIntValidator is not what you're after?