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. QLineEdit::returnPressed when something else has a Key_Return shortcut

QLineEdit::returnPressed when something else has a Key_Return shortcut

Scheduled Pinned Locked Moved Solved General and Desktop
20 Posts 5 Posters 2.1k Views
  • 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.
  • JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #6

    BTW, how do these shortcuts and keys work? If the focus is in a widget (which accepts input) that gets to handle it first? Only if it does not accept the key does it get passed upward through the widget hierarchy, and the treatment as a shortcut happens somewhere there?

    And while we are here, is that the same order for mouse presses, bottom to top of the hierarchy? I thought I once saw that key events and mouse events are propagated in the opposite order from each other?

    1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by Chris Kawa
      #7

      Either subclass and override event() to handle QEvent::ShortcutOverride or install a filter and check for the same. In either case accept() the event and return true when it's the return key. This will override the shortcut and pass the event through to the widget to handle as usual.

      BTW, how do these shortcuts and keys work?

      With no shortcuts involved it's just a bubble up thing - the click goes to whatever was under the cursor and accepts clicks. If you put a "transparent for clicks" flag on a widget the click goes to whatever is under it and so on all the way to the bottom. With buttons it's similar - focused widget gets it first and if it doesn't accept keyboard the event bubbles up through parents until something handles it.

      How shortcuts work depends on the scope. Assuming you have the default window scope when a button is pressed the widget that has focus gets ShortcutOverride event first. If it rejects it (the default) the shortcut swallows the button. If it accepts it the shortcut is overriden and the press is handled as usual i.e. the widget gets a key press event.

      JonBJ 1 Reply Last reply
      6
      • Chris KawaC Chris Kawa

        Either subclass and override event() to handle QEvent::ShortcutOverride or install a filter and check for the same. In either case accept() the event and return true when it's the return key. This will override the shortcut and pass the event through to the widget to handle as usual.

        BTW, how do these shortcuts and keys work?

        With no shortcuts involved it's just a bubble up thing - the click goes to whatever was under the cursor and accepts clicks. If you put a "transparent for clicks" flag on a widget the click goes to whatever is under it and so on all the way to the bottom. With buttons it's similar - focused widget gets it first and if it doesn't accept keyboard the event bubbles up through parents until something handles it.

        How shortcuts work depends on the scope. Assuming you have the default window scope when a button is pressed the widget that has focus gets ShortcutOverride event first. If it rejects it (the default) the shortcut swallows the button. If it accepts it the shortcut is overriden and the press is handled as usual i.e. the widget gets a key press event.

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

        @Chris-Kawa
        Great stuff. I have plenty to try from all three of you, thanks :)

        1 Reply Last reply
        0
        • jeremy_kJ Offline
          jeremy_kJ Offline
          jeremy_k
          wrote on last edited by
          #9

          Another option: check for the focus widget in the shortcut's triggered slot.

          Asking a question about code? http://eel.is/iso-c++/testcase/

          1 Reply Last reply
          0
          • JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #10

            Morning folks :)

            I took @Chris-Kawa's suggestion of QEvent::ShortcutOverride, which I did not know about and seems to be exactly what I want: just don't let a shortcut on Key_Return activate while focus is in my QLineEdit, then leave return to be acted on by the line edit just as however it does it now. I did it with installEventFilter(). And that worked fine.

            Then, I am a bit of a "purist" in my coding :) I thought about it and decided to subclass QLineEdit and do the same but in its event(). You could argue both ways. But the installEventFilter() requires (a) the parent main window to provide an eventFilter() method for the line edit and (b) the parent to call installEventFilter() on behalf of the line edit. Say I am a junior programmer, tasked with writing the line edit code, but not to bother the senior programmers who look after the main window :) I decided, for right or for wrong, to make it so the line edit behaviour is "self-contained": no matter where it is hosted it does not want to allow a Return shortcut to take that away from itself.

            So final code:

            /*virtual*/ bool SpecialLineEdit::event(QEvent *e) /*override*/
            {
                if (e->type() == QEvent::ShortcutOverride)
                {
                    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
                    if (keyEvent->key() == Qt::Key_Return)
                    {
                        // next line added for correct solation as per @Chris-Kawa's comment below
                        e->accept();
                        return true;
                    }
                }
                return QLineEdit::event(e);
            }
            

            Everyone happy with this? :)

            Thanks to all who participated.

            Chris KawaC 1 Reply Last reply
            1
            • JonBJ JonB has marked this topic as solved on
            • JonBJ JonB

              Morning folks :)

              I took @Chris-Kawa's suggestion of QEvent::ShortcutOverride, which I did not know about and seems to be exactly what I want: just don't let a shortcut on Key_Return activate while focus is in my QLineEdit, then leave return to be acted on by the line edit just as however it does it now. I did it with installEventFilter(). And that worked fine.

              Then, I am a bit of a "purist" in my coding :) I thought about it and decided to subclass QLineEdit and do the same but in its event(). You could argue both ways. But the installEventFilter() requires (a) the parent main window to provide an eventFilter() method for the line edit and (b) the parent to call installEventFilter() on behalf of the line edit. Say I am a junior programmer, tasked with writing the line edit code, but not to bother the senior programmers who look after the main window :) I decided, for right or for wrong, to make it so the line edit behaviour is "self-contained": no matter where it is hosted it does not want to allow a Return shortcut to take that away from itself.

              So final code:

              /*virtual*/ bool SpecialLineEdit::event(QEvent *e) /*override*/
              {
                  if (e->type() == QEvent::ShortcutOverride)
                  {
                      QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
                      if (keyEvent->key() == Qt::Key_Return)
                      {
                          // next line added for correct solation as per @Chris-Kawa's comment below
                          e->accept();
                          return true;
                      }
                  }
                  return QLineEdit::event(e);
              }
              

              Everyone happy with this? :)

              Thanks to all who participated.

              Chris KawaC Offline
              Chris KawaC Offline
              Chris Kawa
              Lifetime Qt Champion
              wrote on last edited by
              #11

              @JonB You're missing a call to e->accept() before returning true.

              Also, as a side note, since full keyboard users often use them interchangeably and QLineEdit also supports it, you should probably treat Key_Enter the same way if you want to be safe. And yes, the QLineEdit's signal is called returnPressed, but it is emitted for both Return and Enter.

              JonBJ 1 Reply Last reply
              3
              • Chris KawaC Chris Kawa

                @JonB You're missing a call to e->accept() before returning true.

                Also, as a side note, since full keyboard users often use them interchangeably and QLineEdit also supports it, you should probably treat Key_Enter the same way if you want to be safe. And yes, the QLineEdit's signal is called returnPressed, but it is emitted for both Return and Enter.

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

                @Chris-Kawa said in QLineEdit::returnPressed when something else has a Key_Return shortcut:

                @JonB You're missing a call to e->accept() before returning true.

                Funny, because I was going to ask about just this but didn't get around to it. I wondered if caller goes

                if (event(e) || e->isAccepted)
                

                but I guess they are different. It works, but doubtless because of default value or something. What is the difference/relationship between return result of event() and setting/clearing accepted, please?

                Will do for Key_Enter. Is that the key on my numeric pad which I have never used once in my life?

                Chris KawaC 1 Reply Last reply
                0
                • JonBJ JonB

                  @Chris-Kawa said in QLineEdit::returnPressed when something else has a Key_Return shortcut:

                  @JonB You're missing a call to e->accept() before returning true.

                  Funny, because I was going to ask about just this but didn't get around to it. I wondered if caller goes

                  if (event(e) || e->isAccepted)
                  

                  but I guess they are different. It works, but doubtless because of default value or something. What is the difference/relationship between return result of event() and setting/clearing accepted, please?

                  Will do for Key_Enter. Is that the key on my numeric pad which I have never used once in my life?

                  Chris KawaC Offline
                  Chris KawaC Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by
                  #13

                  What is the difference/relationship between return result of event() and setting/clearing accepted, please?

                  Return value says whether your handler handled the event i.e. if you return false the filter will go to the next guy in the chain. If you return true it stops with you.

                  accept sets a property of the event itself - so anyone getting the pointer can check whether it was accepted.

                  While usually they're set symmetrically you could also reject the event and return true, meaning the event should be ignored and no one else should look at it or you could call accept and return false, meaning you consider the event handled by you, but if anyone else in the chain wants a stab at it they can.

                  Will do for Key_Enter. Is that the key on my numeric pad which I have never used once in my life?

                  Yup, that's the one :)

                  JonBJ 1 Reply Last reply
                  2
                  • Chris KawaC Chris Kawa

                    What is the difference/relationship between return result of event() and setting/clearing accepted, please?

                    Return value says whether your handler handled the event i.e. if you return false the filter will go to the next guy in the chain. If you return true it stops with you.

                    accept sets a property of the event itself - so anyone getting the pointer can check whether it was accepted.

                    While usually they're set symmetrically you could also reject the event and return true, meaning the event should be ignored and no one else should look at it or you could call accept and return false, meaning you consider the event handled by you, but if anyone else in the chain wants a stab at it they can.

                    Will do for Key_Enter. Is that the key on my numeric pad which I have never used once in my life?

                    Yup, that's the one :)

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

                    @Chris-Kawa
                    Thanks, interesting.

                    Take my case. Clearly the vital thing is the return result (I don't want anyone else/the shortcut handler to deal with it), which I have right. Let's say I fail to accept(). What difference could that make? Nobody else could look at it? Does that matter?

                    If Key_Enter is the unknown key on the right, I certainly don't want my line edit contaminated by bothering to handle it. Undefined behaviour is fine. I'm actually happy to leave that as a shortcut if it's wanted.

                    Chris KawaC 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @Chris-Kawa
                      Thanks, interesting.

                      Take my case. Clearly the vital thing is the return result (I don't want anyone else/the shortcut handler to deal with it), which I have right. Let's say I fail to accept(). What difference could that make? Nobody else could look at it? Does that matter?

                      If Key_Enter is the unknown key on the right, I certainly don't want my line edit contaminated by bothering to handle it. Undefined behaviour is fine. I'm actually happy to leave that as a shortcut if it's wanted.

                      Chris KawaC Offline
                      Chris KawaC Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on last edited by Chris Kawa
                      #15

                      Let's say I fail to accept(). What difference could that make? Nobody else could look at it? Does that matter?

                      If you don't accept and return true it basically means "I've handled this event by deciding it doesn't matter". Keep in mind that this refers to the ShortcutOverride event, not the key press, so in other words it's "I've handled the event by ensuring nobody is overriding the shortcut. Let it eat the key".

                      That's how it works for this particular case. Not all events are made equal though. Some of them are more of a notification than a question, like when the OS informs you a color scheme has changed. You can't really meaningfully reject those events, as they are just informing you that something already happened, so nobody is looking at whether you accept those or not.
                      The return value is part of the event propagation mechanism to figure out when to stop propagating. The accepted/rejected bool is sort of a payload of the event that tells the sender at the end of propagation whether you did something with the event or not. That information is not always interesting to the sender, so some check it and some don't.

                      If Key_Enter is the unknown key on the right, I certainly don't want my line edit contaminated by bothering to handle it

                      It already does handle it. There are two keys that do the same thing on the QLineEdit, but you only defended against shortcut shadowing one of them. I just suggested to defend them both for consistency, but it's of course up to you which user habits you support.

                      Personally I use Enter all the time. It's just closer than Return when I have my hand on a mouse to the right, so I can just reach out with a thumb :)

                      JonBJ 1 Reply Last reply
                      1
                      • Chris KawaC Chris Kawa

                        Let's say I fail to accept(). What difference could that make? Nobody else could look at it? Does that matter?

                        If you don't accept and return true it basically means "I've handled this event by deciding it doesn't matter". Keep in mind that this refers to the ShortcutOverride event, not the key press, so in other words it's "I've handled the event by ensuring nobody is overriding the shortcut. Let it eat the key".

                        That's how it works for this particular case. Not all events are made equal though. Some of them are more of a notification than a question, like when the OS informs you a color scheme has changed. You can't really meaningfully reject those events, as they are just informing you that something already happened, so nobody is looking at whether you accept those or not.
                        The return value is part of the event propagation mechanism to figure out when to stop propagating. The accepted/rejected bool is sort of a payload of the event that tells the sender at the end of propagation whether you did something with the event or not. That information is not always interesting to the sender, so some check it and some don't.

                        If Key_Enter is the unknown key on the right, I certainly don't want my line edit contaminated by bothering to handle it

                        It already does handle it. There are two keys that do the same thing on the QLineEdit, but you only defended against shortcut shadowing one of them. I just suggested to defend them both for consistency, but it's of course up to you which user habits you support.

                        Personally I use Enter all the time. It's just closer than Return when I have my hand on a mouse to the right, so I can just reach out with a thumb :)

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

                        @Chris-Kawa
                        Thanks. Sorry to press, but I'm interested and still don't quite get the effect. Obviously I understand here I will accept as well as return true. But can you give an example (not code just explanation) of any event override where returning true but failing to accept causes some different behaviour upstream (or do I mean downstream?) behaviour from if it had also accepted it? A tangible example where behaviour would differ.

                        I have the mouse maybe 10 inches from the edge of the keyboard. My thumb is not that long! I have never used the numeric keypad or the Enter key ever on any keyboard. Frankly I suspect they are devil's spawn, there to tempt the unwary into unnecessary wickedness and gluttony.

                        Chris KawaC 1 Reply Last reply
                        0
                        • JonBJ JonB referenced this topic on
                        • JonBJ JonB

                          @Chris-Kawa
                          Thanks. Sorry to press, but I'm interested and still don't quite get the effect. Obviously I understand here I will accept as well as return true. But can you give an example (not code just explanation) of any event override where returning true but failing to accept causes some different behaviour upstream (or do I mean downstream?) behaviour from if it had also accepted it? A tangible example where behaviour would differ.

                          I have the mouse maybe 10 inches from the edge of the keyboard. My thumb is not that long! I have never used the numeric keypad or the Enter key ever on any keyboard. Frankly I suspect they are devil's spawn, there to tempt the unwary into unnecessary wickedness and gluttony.

                          Chris KawaC Offline
                          Chris KawaC Offline
                          Chris Kawa
                          Lifetime Qt Champion
                          wrote on last edited by
                          #17

                          can you give an example (not code just explanation) of any event override where returning true but failing to accept causes some different behaviour

                          A very common example is the close event. If you accept() it the window will close. If you ignore() it the window will stay open.

                          Frankly I suspect they are devil's spawn, there to tempt the unwary into unnecessary wickedness and gluttony.

                          All true. Those who had congress with the beast tend to develop elongated fingers turning into claws further down the line, letting them reach the notoriously elusive and distant Enter key with more ease.

                          JonBJ 1 Reply Last reply
                          1
                          • Chris KawaC Chris Kawa

                            can you give an example (not code just explanation) of any event override where returning true but failing to accept causes some different behaviour

                            A very common example is the close event. If you accept() it the window will close. If you ignore() it the window will stay open.

                            Frankly I suspect they are devil's spawn, there to tempt the unwary into unnecessary wickedness and gluttony.

                            All true. Those who had congress with the beast tend to develop elongated fingers turning into claws further down the line, letting them reach the notoriously elusive and distant Enter key with more ease.

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

                            @Chris-Kawa
                            I'm not going to lie, I still don't fully understand the behaviour/consequences for event->accept() or not! However, I discovered that the code I had without it did not always work correctly (sometimes it did, sometimes not when it hit my return true but still it treated it as a shortcut). I put in e->accept() and now it works consistently, and so I have corrected my solution code to include it.

                            Chris KawaC 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @Chris-Kawa
                              I'm not going to lie, I still don't fully understand the behaviour/consequences for event->accept() or not! However, I discovered that the code I had without it did not always work correctly (sometimes it did, sometimes not when it hit my return true but still it treated it as a shortcut). I put in e->accept() and now it works consistently, and so I have corrected my solution code to include it.

                              Chris KawaC Offline
                              Chris KawaC Offline
                              Chris Kawa
                              Lifetime Qt Champion
                              wrote on last edited by Chris Kawa
                              #19

                              @JonB Maybe this example will help. Say you have a hierarchy of widgets like this:
                              Window -> TabWidget -> Groupbox -> TextEdit

                              When you send some event to the TextEdit the sequence in pseudo code is like this:

                              QWidget* widget = TextEdit;
                              QEvent* event = ...
                              
                              while(widget && !widget->event(event))
                              {
                                  widget = widget->parentWidget();
                              }
                              
                              bool result = event->isAccepted();
                              doSomethingWithResult(result);
                              
                              

                              i.e. it goes up the parent tree until one of the widgets returns true and then it checks whether the event was accepted or not and does something with it.

                              If you return true but don't either accept or ignore the event it will be left in whatever state the previous handler on the stack left it with. If you're the only one or none of the handlers touched it it's gonna be whatever the event sender initialized it with and that differs depending on event - some are accepted by default and some are ignored by default.

                              JonBJ 1 Reply Last reply
                              3
                              • Chris KawaC Chris Kawa

                                @JonB Maybe this example will help. Say you have a hierarchy of widgets like this:
                                Window -> TabWidget -> Groupbox -> TextEdit

                                When you send some event to the TextEdit the sequence in pseudo code is like this:

                                QWidget* widget = TextEdit;
                                QEvent* event = ...
                                
                                while(widget && !widget->event(event))
                                {
                                    widget = widget->parentWidget();
                                }
                                
                                bool result = event->isAccepted();
                                doSomethingWithResult(result);
                                
                                

                                i.e. it goes up the parent tree until one of the widgets returns true and then it checks whether the event was accepted or not and does something with it.

                                If you return true but don't either accept or ignore the event it will be left in whatever state the previous handler on the stack left it with. If you're the only one or none of the handlers touched it it's gonna be whatever the event sender initialized it with and that differs depending on event - some are accepted by default and some are ignored by default.

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

                                @Chris-Kawa
                                6 lines of code are worth a thousand words ;) Perfectly clear now!

                                1 Reply Last reply
                                0
                                • JonBJ JonB referenced this topic on

                                • Login

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