using QKeyEvents
-
Hi all -
I'm experimenting with handling key events in an app, and (as usual) I'm having beginner's difficulties. I've read a couple pages on this, and there seems to be a few different ways to do it. I chose one that made the most sense to me.
I created a KeyPress class:
class KeyPress : public QWidget { Q_OBJECT public: explicit KeyPress(QWidget *parent = nullptr); protected: void keyPressEvent (QKeyEvent *ev); void keyReleaseEvent(QKeyEvent *ev); signals: void keyEvent(int event, int key); };
And in my main widget, I do this in the c'tor:
// create and connect a KeyPress object. m_keyPress = new KeyPress(this); connect(m_keyPress, &KeyPress::keyEvent, this, &Widget::handleKeyEvent); m_keyPress->installEventFilter(this);
And I overrode the event filter:
bool eventFilter(QObject *obj, QEvent *ev) override; ... bool Widget::eventFilter(QObject *obj, QEvent *ev) { bool rc = false; if (obj == m_keyPress) { if (ev->type() == QEvent::KeyPress) { rc = true; qDebug() << ev; } } return rc; }
I realize this isn't functional yet, but I thought I'd at least catch a key press. I'm not, though. Can someone tell me what I'm missing?
Thanks...
-
Why do you need the KeyEvent Class?
You can do following:
Subclass the widget where you want the keyevents to be catched.
Then add a definition forvoid YourWidget::keyPressEvent(QKeyEvent *event)
that looks something like this:
void YourWidget::keyPressEvent(QKeyEvent *event) { if(event->key() == Qt::Key_A) { doAKeyPressStuff(); } else { doAnyOtherKeyPressStuff(); } }
-
Why do you need the KeyEvent Class?
You can do following:
Subclass the widget where you want the keyevents to be catched.
Then add a definition forvoid YourWidget::keyPressEvent(QKeyEvent *event)
that looks something like this:
void YourWidget::keyPressEvent(QKeyEvent *event) { if(event->key() == Qt::Key_A) { doAKeyPressStuff(); } else { doAnyOtherKeyPressStuff(); } }
-
Hi,
It's the other way around, you need to install KeyPress in your QMainWindow.
-
@SGaist not using QMainWindow; using QWidget.
class Widget : public QWidget { Q_OBJECT ...
Same thing, though?
And by "install KeyPress" I assume you mean more than create an object of that class, since I'm already doing that.
m_keyPress = new KeyPress(this); connect(m_keyPress, &KeyPress::keyEvent, this, &Widget::handleKeyEvent); m_keyPress->installEventFilter(this);
I'm missing a step here, aren't I?
-
You're not missing a step, you are doing one in the wrong direction. The object on the left of installEventFilter is the one that is going to be monitored so just call
installEventFilter(m_keyPress);
See the installEventFilter documentation.
-
OK...made that change; still not seeing what I expect.
// create and connect a KeyPress object. m_keyPress = new KeyPress(this); connect(m_keyPress, &KeyPress::keyEvent, this, &Widget::handleKeyEvent); installEventFilter(m_keyPress);
Here's my event routine:
void KeyPress::keyPressEvent(QKeyEvent *ev) { int key; key = ev->key(); if (key == Qt::Key_Alt) { emit keyEvent(QEvent::KeyPress, key); } }
I'm never hitting a breakpoint in there.
-
Because an event filter re-implements the eventFilter method and does all there. It does not replace a class original methods.
-
Because an event filter re-implements the eventFilter method and does all there. It does not replace a class original methods.
@SGaist said in using QKeyEvents:
Because an event filter re-implements the eventFilter method and does all there. It does not replace a class original methods.
So, which object needs the eventFilter() method? I've tried adding to both the Widget and the KeyPress -- both compile and run, but neither trigger a breakpoint.
-
Did you check the example I linked to ?
-
@SGaist you're referring to the KeyPressEater class in the QObject::installEventFilter() documentation, right?
Its behavior isn't the same as my KeyPress class, but I can worry about that later. I still don't see why I'm not hitting a breakpoint.
bool KeyPress::eventFilter(QObject *obj, QEvent *ev) { bool rc = false; if (ev->type() == QEvent::KeyPress) { if (obj == this) { rc = true; qDebug() << ev; } } return rc; }
My breakpoint is on my inner "if" and it's never reached.
-
Because as is, your filter will never be the target of a KeyPress event.
The value of obj will be one of the object you installed your filter on. -
Well, I got it partly working -- the problem was that I was deriving my KeyPress class from QWidget instead of QObject.
Now, though, my filter only seems to be trapping "meta keys." Control, alt, etc. all work, but regular keys like A, B, C don't. It appears that these keys generate a ShortcutOverride event. Does this make sense to you?
Thanks...
-
My filter seems to be doing what I want (when two keys are held down, I make a button visible).
if (C_pressed && D_pressed) { ui->pushButtonNics->setVisible(true); } else { ui->pushButtonNics->setVisible(false); }
But when I click on that button, my clicked slot isn't reached. I thought maybe holding down the keys was blocking the button push, but my other buttons work fine. My button is enabled when visible (I checked in the debugger). Any ideas why it's not generating the signal?
Thanks...
-
You are forgetting to call the base class implementation.
-
The last implementation I saw does not call it at all which means that all events are filtered out.
To check, comment out the filter installation and see if it does work correctly.
-
The last implementation I saw does not call it at all which means that all events are filtered out.
To check, comment out the filter installation and see if it does work correctly.
@SGaist let's make sure we're talking about the same thing. Here's where I create the filter:
// create and connect a KeyPress object. m_keyPress = new KeyPress(this); connect(m_keyPress, &KeyPress::keyEvent, this, &Widget::handleKeyEvent); installEventFilter(m_keyPress); // hide the button for the NICs window. // ui->pushButtonNics->setVisible(false);
You'll notice that the last line is commented out. And, it works. So it would seem that it has something to do with the filter...?
-
Can you provide a minimal compilable example that shows the behaviour ?
Si au can check on my side what is going on.