Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. using QKeyEvents
Forum Updated to NodeBB v4.3 + New Features

using QKeyEvents

Scheduled Pinned Locked Moved Solved General and Desktop
40 Posts 4 Posters 5.8k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SGaistS SGaist

    Can you provide a minimal compilable example that shows the behaviour ?
    Si au can check on my side what is going on.

    mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #21

    @SGaist

    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.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #22

      A minimal widget that you install that filter on would be nice :-)

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on last edited by
        #23

        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.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #24

          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.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          mzimmersM 1 Reply Last reply
          0
          • SGaistS SGaist

            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.

            mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by
            #25

            @SGaist well, doesn't that tear the rag right off the bush.

            What exactly did you mean by "explicit" connection?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #26

              By explicit I meant writing the connect statement. Currently you are using the connectSlotsByName feature that is called as part of setupUi.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by
                #27

                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...

                1 Reply Last reply
                0
                • mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on last edited by
                  #28

                  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?

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #29

                    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.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    mzimmersM 1 Reply Last reply
                    0
                    • SGaistS SGaist

                      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.

                      mzimmersM Offline
                      mzimmersM Offline
                      mzimmers
                      wrote on last edited by
                      #30

                      @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);
                      }
                      
                      1 Reply Last reply
                      0
                      • mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #31

                        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...

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #32

                          What type of widgets are you checking ?
                          You can add an additional check for the obj parameter class to avoid further checks.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          JonBJ mzimmersM 2 Replies Last reply
                          0
                          • SGaistS SGaist

                            What type of widgets are you checking ?
                            You can add an additional check for the obj parameter class to avoid further checks.

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by
                            #33

                            @SGaist
                            If @mzimmers says:

                            but with this enabled, the app uses ~15% of my CPU (on an i3) at idle

                            assuming "idle" means not pressing any key, why is this KeyPress::eventFilter() being hit at all, let alone loads of times to use that CPU?

                            mzimmersM 1 Reply Last reply
                            0
                            • SGaistS SGaist

                              What type of widgets are you checking ?
                              You can add an additional check for the obj parameter class to avoid further checks.

                              mzimmersM Offline
                              mzimmersM Offline
                              mzimmers
                              wrote on last edited by
                              #34

                              @SGaist well, maybe that's my problem -- I'm checking the entire QWidget. (The idea was to reveal hidden buttons when certain keys were pressed.) Given that, I'm not sure there's any meaningful obj parameter checking I can do.

                              1 Reply Last reply
                              0
                              • JonBJ JonB

                                @SGaist
                                If @mzimmers says:

                                but with this enabled, the app uses ~15% of my CPU (on an i3) at idle

                                assuming "idle" means not pressing any key, why is this KeyPress::eventFilter() being hit at all, let alone loads of times to use that CPU?

                                mzimmersM Offline
                                mzimmersM Offline
                                mzimmers
                                wrote on last edited by
                                #35

                                @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.

                                JonBJ 1 Reply Last reply
                                0
                                • mzimmersM mzimmers

                                  @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.

                                  JonBJ Offline
                                  JonBJ Offline
                                  JonB
                                  wrote on last edited by
                                  #36

                                  @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?

                                  mzimmersM 1 Reply Last reply
                                  0
                                  • JonBJ JonB

                                    @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?

                                    mzimmersM Offline
                                    mzimmersM Offline
                                    mzimmers
                                    wrote on last edited by
                                    #37

                                    @JonB

                                        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.

                                    JonBJ 1 Reply Last reply
                                    0
                                    • mzimmersM mzimmers

                                      @JonB

                                          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.

                                      JonBJ Offline
                                      JonBJ Offline
                                      JonB
                                      wrote on last edited by
                                      #38

                                      @mzimmers
                                      Start by debugging out ev->type()!

                                      mzimmersM 1 Reply Last reply
                                      0
                                      • JonBJ JonB

                                        @mzimmers
                                        Start by debugging out ev->type()!

                                        mzimmersM Offline
                                        mzimmersM Offline
                                        mzimmers
                                        wrote on last edited by mzimmers
                                        #39

                                        @JonB the great majority were:

                                        QEvent::UpdateRequest
                                        QEvent::Paint

                                        UPDATE: 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?

                                        1 Reply Last reply
                                        0
                                        • mzimmersM Offline
                                          mzimmersM Offline
                                          mzimmers
                                          wrote on last edited by
                                          #40

                                          Update on this, documented here

                                          The behaviour is different because clicked is emitted on button down on macOS, but on button up on the other two[Windows and Linux]. While the keyboard keys are down, the QPushButton stays down. That's a UX difference caused by how the OS itself behaves.

                                          So, my idea for using the keys goes out the window...I'll think of something else.

                                          The performance issue is a mystery, but I'm going to open a new thread on that. Thanks to everyone for looking.

                                          1 Reply Last reply
                                          1

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved