using QKeyEvents
-
Can you provide a minimal compilable example that shows the behaviour ?
Si au can check on my side what is going on. -
Can you provide a minimal compilable example that shows the behaviour ?
Si au can check on my side what is going on.keypress.h
#ifndef KEYPRESS_H #define KEYPRESS_H #include <QWidget> #include <QtGui> class KeyPress : public QObject { Q_OBJECT public: explicit KeyPress(QWidget *parent = nullptr); protected: bool eventFilter(QObject *obj, QEvent *ev) override; signals: void keyEvent(QEvent event, int key); }; #endif // KEYPRESS_H
keypress.cpp
#include "keypress.h" KeyPress::KeyPress(QWidget *parent) : QObject (parent) { } bool KeyPress::eventFilter(QObject *obj, QEvent *ev) { Q_UNUSED(obj) bool rc = false; int key; QKeyEvent *qke; if (ev->type() == QEvent::ShortcutOverride || ev->type() == QEvent::KeyRelease) { qke = static_cast<QKeyEvent *>(ev); key = qke->key(); // don't bother signaling when the key isn't meaningful to us. if (key == 'c' || key == 'C' || key == 'd' || key == 'D') { emit keyEvent(*ev, key); } rc = true; } else { rc = QObject::eventFilter(obj, ev); } return rc; }
Let me know if there's something more you want to look at...thanks.
-
A minimal widget that you install that filter on would be nice :-)
-
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include "keypress.h" namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT private: Ui::Widget *ui; KeyPress *m_keyPress = nullptr; bool C_pressed = false; bool D_pressed = false; public: explicit Widget(QWidget *parent = nullptr); ~Widget(); private slots: void on_pushButtonQuit_clicked(); void on_pushButtonNics_clicked(); void handleKeyEvent(QEvent event, int key); signals: void quitButtonPushed(int rc); }; #endif // WIDGET_H
widget.cpp
#include <iostream> #include <sstream> #include <stdio.h> #include <QDebug> #include "editdialog.h" #include "nics.h" #include "widget.h" #include "ui_widget.h" using namespace std; Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 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); } Widget::~Widget() { delete ui; } void Widget::on_pushButtonQuit_clicked() { emit quitButtonPushed(0); } void Widget::handleKeyEvent(QEvent event, int key) { if (event.type() == QEvent::ShortcutOverride) { if (key == 'c' || key == 'C') { C_pressed = true; } else if ((key == 'd' || key == 'D')) { D_pressed = true; } } else if (event.type() == QEvent::KeyRelease) { if (key == 'c' || key == 'C') { C_pressed = false; } else if ((key == 'd' || key == 'D')) { D_pressed = false; } } if (C_pressed && D_pressed) { ui->pushButtonNics->setVisible(true); } else { ui->pushButtonNics->setVisible(false); } } void Widget::on_pushButtonNics_clicked() { Nics nics(this); nics.exec(); }
You'll want to connect the Widget signal to something. Sorry...this was as compact as I dared make it.
Thanks for looking at this.
-
Since I don't have the .ui file I modified the code a bit.
I created a QPushButton and did an explicit connection and it worked was expected.
-
Since I don't have the .ui file I modified the code a bit.
I created a QPushButton and did an explicit connection and it worked was expected.
-
By explicit I meant writing the connect statement. Currently you are using the connectSlotsByName feature that is called as part of setupUi.
-
OK...I added the explicit connection in widget.cpp:
connect(ui->pushButtonNics, &QPushButton::clicked, this, &Widget::on_pushButtonNics_clicked);
Here's my widget.ui:
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Widget</class> <widget class="QWidget" name="Widget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>320</width> <height>160</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>320</width> <height>160</height> </size> </property> <property name="windowTitle"> <string>Discovery Utility</string> </property> <widget class="QPushButton" name="pushButtonNics"> <property name="geometry"> <rect> <x>130</x> <y>50</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>NICs</string> </property> </widget> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui>
And, just for good measure, here's main.cpp:
#include <QApplication> #include <stdio.h> #include "widget.h" using namespace std; int main(int argc, char *argv[]) { int rc; QApplication a(argc, argv); Widget *widget; widget = new Widget(); widget->show(); rc = a.exec(); return rc; }
This is my entire project, except for the pro file itself:
QT += core gui network serialport xml greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = discovery_utility_test DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ keypress.cpp \ main.cpp \ nics.cpp \ widget.cpp HEADERS += \ keypress.h \ nics.h \ widget.h \ FORMS += \ nics.ui \ widget.ui
Could it possibly be due to the way that I'm building it? Or, maybe a Windows issue (you're testing on Linux, right)?
Thanks...
-
This problem has to do with setting the button's visibility. If I disable this line in my widget c'tor:
// ui->pushButtonNics->setVisible(false);
My slot receives the signal, and opens the Nics dialog. After the dialog closes, I set the button to not visible, and the problem recurs.
This problem exists on Windows 10, but not on MacOS. Could it be a bug?
-
One silly test, did you try to make the button invisible after calling
connect
. AFAIK, it should have no relation but it's worth a shot. -
One silly test, did you try to make the button invisible after calling
connect
. AFAIK, it should have no relation but it's worth a shot.@SGaist yes, that's how I had it:
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // create and connect a KeyPress object. m_keyPress = new KeyPress(this); connect(m_keyPress, &KeyPress::keyEvent, this, &Widget::handleKeyEvent); connect(ui->pushButtonNics, &QPushButton::clicked, this, &Widget::on_pushButtonNics_clicked); installEventFilter(m_keyPress); // hide the button for the NICs window. // ui->pushButtonNics->setVisible(false); }
-
Update: I submitted a bug report on this; no movement on it yet.
One of my users noticed that the application is now rather CPU-intensive. I verified that it was the key filter by disabling this code in my main widget:
m_keyPress = new KeyPress(this); connect(m_keyPress, &KeyPress::keyEvent, this, &Widget::handleKeyEvent); installEventFilter(m_keyPress);
Here's the filter:
bool KeyPress::eventFilter(QObject *obj, QEvent *ev) { Q_UNUSED(obj) bool rc = false; int key; QKeyEvent *qke; QEvent::Type type = ev->type(); if (type == QEvent::ShortcutOverride || type == QEvent::KeyRelease) { qke = static_cast<QKeyEvent *>(ev); key = qke->key(); // don't bother signaling when the key isn't meaningful to us. if (key == 'c' || key == 'C' || key == 'd' || key == 'D') { emit keyEvent(*ev, key); } rc = true; } else { rc = QObject::eventFilter(obj, ev); } return rc; }
I don't see anything really inefficient in my code, but with this enabled, the app uses ~15% of my CPU (on an i3) at idle. Is this to be expected, or am I doing something wrong?
Thanks...
-
What type of widgets are you checking ?
You can add an additional check for the obj parameter class to avoid further checks. -
What type of widgets are you checking ?
You can add an additional check for the obj parameter class to avoid further checks. -
What type of widgets are you checking ?
You can add an additional check for the obj parameter class to avoid further checks. -
-
@JonB I suspect I'm doing something wrong with my use of the filter, but I'm not sure what to change. I think my filterEvent() is being called for all events, not just for key events.
@mzimmers said in using QKeyEvents:
I think my filterEvent() is being called for all events, not just for key events.
I suspect that is more like it ;-) I would worry about that before anything else :)
Use a debugger or
qDebug()
s to at least see when your filter is being hit, when the user isn't doing anything? -
@mzimmers said in using QKeyEvents:
I think my filterEvent() is being called for all events, not just for key events.
I suspect that is more like it ;-) I would worry about that before anything else :)
Use a debugger or
qDebug()
s to at least see when your filter is being hit, when the user isn't doing anything? -
qDebug() << QTime::currentTime().toString();
Got about 6000 hits in ~2 seconds of run time. That explains the CPU usage.
I have no idea what could possibly be generating that many events, though.
-
@JonB the great majority were:
QEvent::UpdateRequest
QEvent::PaintUPDATE: I managed to eliminate the flood of events, but...that didn't have an effect on my CPU usage. The problem is definitely in the KeyEvent class -- when I comment it out, CPU usage is nil. Anyone have any ideas?