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. QCompleter for QLineEdit documentation and behaviour question
QtWS25 Last Chance

QCompleter for QLineEdit documentation and behaviour question

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 3 Posters 2.8k 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 Online
    JonBJ Online
    JonB
    wrote on last edited by JonB
    #1

    I have two questions about attaching a QCompleter to a QLineEdit.

    Documentation

    I have read documentation at http://doc.qt.io/qt-5/qcompleter.html and http://doc.qt.io/qt-5/qlineedit.html#setCompleter carefully. Taking an absolute default code:

    self.le = QtWidgets.QLineEdit()
    self.completer = QtWidgets.QCompleter(["111", "112", "121", "2222", "333"])
    self.le.setCompleter(self.completer)
    

    When the user clicks (or presses Enter) on an item in the popup, the text of the item is copied into the QLineEdit.

    Can anyone point me to anywhere in the documentation where this is actually stated??

    The only mention I can find of anything related is in http://doc.qt.io/qt-5/qcompleter.html#activated :

    This signal is sent when an item in the popup() is activated by the user (by clicking or pressing return).

    Well, I'm not connecting the activated signal. Is this what it does for a QLineEdit by default or something?

    Behaviour

    My actual objective is: after the selected item has been copied, I want the QLineEdit to treat it as the use has finished editing the text, so that it gets acted on immediately. (I would have thought this is a not-uncommon requirement. It's the kind of behaviour you'd expect if you were using an (editable) combobox.)

    I have come up with the following addition to the above code, which seems to work:

    self.le.completer().activated.connect(self.le.editingFinished.emit)
    

    Is this right/best? My connecting the activated signal does not seem to have stopped selecting an item from copying it to the QLineEdit, so maybe it never used the activated signal itself to do that in the first place? What is doing the text copy when? Am I supposed to call the base QCompleter::activated slot before/after my handler too to do anything more?

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

      Hi,

      You don't connect that signal yourself, it's handled internally.

      setText is used when you select an entry.

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

      JonBJ 1 Reply Last reply
      2
      • JonBJ JonB

        I have two questions about attaching a QCompleter to a QLineEdit.

        Documentation

        I have read documentation at http://doc.qt.io/qt-5/qcompleter.html and http://doc.qt.io/qt-5/qlineedit.html#setCompleter carefully. Taking an absolute default code:

        self.le = QtWidgets.QLineEdit()
        self.completer = QtWidgets.QCompleter(["111", "112", "121", "2222", "333"])
        self.le.setCompleter(self.completer)
        

        When the user clicks (or presses Enter) on an item in the popup, the text of the item is copied into the QLineEdit.

        Can anyone point me to anywhere in the documentation where this is actually stated??

        The only mention I can find of anything related is in http://doc.qt.io/qt-5/qcompleter.html#activated :

        This signal is sent when an item in the popup() is activated by the user (by clicking or pressing return).

        Well, I'm not connecting the activated signal. Is this what it does for a QLineEdit by default or something?

        Behaviour

        My actual objective is: after the selected item has been copied, I want the QLineEdit to treat it as the use has finished editing the text, so that it gets acted on immediately. (I would have thought this is a not-uncommon requirement. It's the kind of behaviour you'd expect if you were using an (editable) combobox.)

        I have come up with the following addition to the above code, which seems to work:

        self.le.completer().activated.connect(self.le.editingFinished.emit)
        

        Is this right/best? My connecting the activated signal does not seem to have stopped selecting an item from copying it to the QLineEdit, so maybe it never used the activated signal itself to do that in the first place? What is doing the text copy when? Am I supposed to call the base QCompleter::activated slot before/after my handler too to do anything more?

        Gojir4G Offline
        Gojir4G Offline
        Gojir4
        wrote on last edited by Gojir4
        #3

        Hi ,
        @JonB said in QCompleter for QLineEdit documentation and behaviour question:

        When the user clicks (or presses Enter) on an item in the popup, the text of the item is copied into the QLineEdit.
        Can anyone point me to anywhere in the documentation where this is actually stated??

        I don't think you will find this in the documentation. This is implicit as this is the goal of the completer. QLineEdit is already designed to handle actived and highlighted signals and to set the text accordingly.
        Here is the source code of QLineEdit:setCompleter():

        void QLineEdit::setCompleter(QCompleter *c)
        {
            Q_D(QLineEdit);
            if (c == d->control->completer())
                return;
            if (d->control->completer()) {
                disconnect(d->control->completer(), 0, this, 0);
                d->control->completer()->setWidget(0);
                if (d->control->completer()->parent() == this)
                    delete d->control->completer();
            }
            d->control->setCompleter(c);
            if (!c)
                return;
            if (c->widget() == 0)
                c->setWidget(this);
            if (hasFocus()) {
                QObject::connect(d->control->completer(), SIGNAL(activated(QString)),
                                 this, SLOT(setText(QString)));
                QObject::connect(d->control->completer(), SIGNAL(highlighted(QString)),
                                 this, SLOT(_q_completionHighlighted(QString)));
            }
        }
        

        There is two important things which are done here to make it working:

        • Calling QCompleter::setWidget() and pass pointer on the "edit" widget in argument (this).
        • Connecting to signal actived to handle insertion of completion item and signal highlighted, which may be used depending of the CompletionMode

        So except if you have some validator on your QLineEdit, I would suggest to use the signal activated directly without connecting it to QLineEdit::editFinished().
        I will try to make an example with my bad python level :)

        def handleNewText(text):
            print(text)
        self.le.completer().activated.connect(handleNewText)
        

        @JonB said in QCompleter for QLineEdit documentation and behaviour question:

        Is this right/best? My connecting the activated signal does not seem to have stopped selecting an item from copying it to the QLineEdit, so maybe it never used the activated signal itself to do that in the first place? What is doing the text copy when? Am I supposed to call the base QCompleter::activated slot before/after my handler too to do anything more?

        Connecting to asignal will not disconnect it from the QLineEdit, so it will not stop completion in your QLineEdit.

        1 Reply Last reply
        2
        • SGaistS SGaist

          Hi,

          You don't connect that signal yourself, it's handled internally.

          setText is used when you select an entry.

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by JonB
          #4

          @SGaist , @Gojir4
          Thank you both.

          @SGaist

          You don't connect that signal yourself, it's handled internally.
          setText is used when you select an entry.

          Fair enough. I don't know if you are the person to mention it to, but that could do with being documented.

          @Gojir4
          Don't worry about the Python! C++ is fine.
          The bit I don't get is

          So except if you have some validator on your QLineEdit, I would suggest to use the signal activated directly without connecting it to QLineEdit::editFinished().

          Why wouldn't you connect to editFinished? Maybe there will indeed be a validator. All I know is I want selection to be treated as whatever editing finished would do. I don't know what that might be, so I emit the signal. What possible disadvantage are you suggesting there might be?

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

            You can request an improvement to the documentation on the bug report system or even better, you can submit an improvement to the documentation :)

            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
            • JonBJ JonB

              @SGaist , @Gojir4
              Thank you both.

              @SGaist

              You don't connect that signal yourself, it's handled internally.
              setText is used when you select an entry.

              Fair enough. I don't know if you are the person to mention it to, but that could do with being documented.

              @Gojir4
              Don't worry about the Python! C++ is fine.
              The bit I don't get is

              So except if you have some validator on your QLineEdit, I would suggest to use the signal activated directly without connecting it to QLineEdit::editFinished().

              Why wouldn't you connect to editFinished? Maybe there will indeed be a validator. All I know is I want selection to be treated as whatever editing finished would do. I don't know what that might be, so I emit the signal. What possible disadvantage are you suggesting there might be?

              Gojir4G Offline
              Gojir4G Offline
              Gojir4
              wrote on last edited by
              #6

              @JonB said in QCompleter for QLineEdit documentation and behaviour question:

              Why wouldn't you connect to editFinished? Maybe there will indeed be a validator. All I know is I want selection to be treated as whatever editing finished would do. I don't know what that might be, so I emit the signal. What possible disadvantage are you suggesting there might be?

              You're right. What I meant is you don't need to connect activated to editFinished. I was assuming that editFinished will be called "automatically" by QLineEdit's slot connected to activated , with a "validated" string as argument, except if validation failed. But I was wrong as it only emits textChanged indirectly by calling QLineEdit::setText(). Also the doc says "The text is not validated when inserted with setText().". So it seems that using completer will bypass the validator anyway.

              So I think you can assume that the string argument from activated will be the same value than the one contained in the line edit.

              def onEditFinished(text): //text contains value selected from completer
                  print(le.text()) //Get updated value from QLineEdit
              self.le.completer().activated.connect(onEditFinished)
              

              If the goal is to handle the new value, connecting to activated seems enough to me. If the goal is to explicitly emit editFinished, so ok you need to make the "extra" connection but I don't see the benefits.

              JonBJ 1 Reply Last reply
              1
              • Gojir4G Gojir4

                @JonB said in QCompleter for QLineEdit documentation and behaviour question:

                Why wouldn't you connect to editFinished? Maybe there will indeed be a validator. All I know is I want selection to be treated as whatever editing finished would do. I don't know what that might be, so I emit the signal. What possible disadvantage are you suggesting there might be?

                You're right. What I meant is you don't need to connect activated to editFinished. I was assuming that editFinished will be called "automatically" by QLineEdit's slot connected to activated , with a "validated" string as argument, except if validation failed. But I was wrong as it only emits textChanged indirectly by calling QLineEdit::setText(). Also the doc says "The text is not validated when inserted with setText().". So it seems that using completer will bypass the validator anyway.

                So I think you can assume that the string argument from activated will be the same value than the one contained in the line edit.

                def onEditFinished(text): //text contains value selected from completer
                    print(le.text()) //Get updated value from QLineEdit
                self.le.completer().activated.connect(onEditFinished)
                

                If the goal is to handle the new value, connecting to activated seems enough to me. If the goal is to explicitly emit editFinished, so ok you need to make the "extra" connection but I don't see the benefits.

                JonBJ Online
                JonBJ Online
                JonB
                wrote on last edited by JonB
                #7

                @Gojir4
                I'll try one more time. I'm not sure whether you're trying to say something I don't understand or whether we are talking at cross-purposes :)

                • I wish to add a QCompleter to some QLineEdits I already have.

                • Those QLineEdits may already be set up so that when editing completed (e.g. press Enter or perhaps press Tab to move off) code wishes to act on that immediately. (In the current particular situation this is indeed the case: when the user has finished typing into the QLineEdit its content is a "filter" which immediately causes refresh of the whole page.)

                • The outside world will have hooked to a signal from the QLineEdit to accomplish this behaviour. The outside world will know nothing about whether the QLineEdit does or does not have a QCompleter attached.

                • When the user clicks to accept a suggestion, the QCompleter appears to first copy the text into the QLineEdit (that emits textChanged) and then explicitly emit the activated signal.

                • I can't use the textChanged signal as that is emitted as text is being typed in, that's too early to act on since we're waiting for the complete text before we can act on it.

                In your example, you have written your own onEditFinished() slot and connected QCompleter::activated signal to it. However, that is not the real world. The outside world will (or may) have connected a function to QLineEdit::editingFinished for whatever behaviour it wants on editing completed. In the QCompleter we know nothing about that, so we don't have an explicit function to call. All we know is we'd like the QLineEdit to behave however it would behave if the user had typed into it and finished typing, e.g. by pressing Enter or Tab or by clicking elsewhere. That's what my question stated:

                My actual objective is: after the selected item has been copied, I want the QLineEdit to treat it as [if] the use[r] has finished editing the text, so that it gets acted on immediately.

                So, I don't know about you but I cannot see how the QCompleter::activated would know what to call to achieve that, other than by causing the QLineEdit to emit its editingFinished signal?

                Gojir4G 1 Reply Last reply
                0
                • JonBJ JonB

                  @Gojir4
                  I'll try one more time. I'm not sure whether you're trying to say something I don't understand or whether we are talking at cross-purposes :)

                  • I wish to add a QCompleter to some QLineEdits I already have.

                  • Those QLineEdits may already be set up so that when editing completed (e.g. press Enter or perhaps press Tab to move off) code wishes to act on that immediately. (In the current particular situation this is indeed the case: when the user has finished typing into the QLineEdit its content is a "filter" which immediately causes refresh of the whole page.)

                  • The outside world will have hooked to a signal from the QLineEdit to accomplish this behaviour. The outside world will know nothing about whether the QLineEdit does or does not have a QCompleter attached.

                  • When the user clicks to accept a suggestion, the QCompleter appears to first copy the text into the QLineEdit (that emits textChanged) and then explicitly emit the activated signal.

                  • I can't use the textChanged signal as that is emitted as text is being typed in, that's too early to act on since we're waiting for the complete text before we can act on it.

                  In your example, you have written your own onEditFinished() slot and connected QCompleter::activated signal to it. However, that is not the real world. The outside world will (or may) have connected a function to QLineEdit::editingFinished for whatever behaviour it wants on editing completed. In the QCompleter we know nothing about that, so we don't have an explicit function to call. All we know is we'd like the QLineEdit to behave however it would behave if the user had typed into it and finished typing, e.g. by pressing Enter or Tab or by clicking elsewhere. That's what my question stated:

                  My actual objective is: after the selected item has been copied, I want the QLineEdit to treat it as [if] the use[r] has finished editing the text, so that it gets acted on immediately.

                  So, I don't know about you but I cannot see how the QCompleter::activated would know what to call to achieve that, other than by causing the QLineEdit to emit its editingFinished signal?

                  Gojir4G Offline
                  Gojir4G Offline
                  Gojir4
                  wrote on last edited by
                  #8

                  @JonB said in QCompleter for QLineEdit documentation and behaviour question:

                  I'll try one more time. I'm not sure whether you're trying to say something I don't understand or whether we are talking at cross-purposes :)

                  hmmm... I'm not sure too :)

                  What I'm trying to say is that connecting activated signal to the editFinished one or directly to your "outside world" slot (which refresh the page) will have the same result.

                  But if you can't accessing the slot to make the connect , so in this case I agree that you need to connect to editFinished .

                  JonBJ 1 Reply Last reply
                  0
                  • Gojir4G Gojir4

                    @JonB said in QCompleter for QLineEdit documentation and behaviour question:

                    I'll try one more time. I'm not sure whether you're trying to say something I don't understand or whether we are talking at cross-purposes :)

                    hmmm... I'm not sure too :)

                    What I'm trying to say is that connecting activated signal to the editFinished one or directly to your "outside world" slot (which refresh the page) will have the same result.

                    But if you can't accessing the slot to make the connect , so in this case I agree that you need to connect to editFinished .

                    JonBJ Online
                    JonBJ Online
                    JonB
                    wrote on last edited by
                    #9

                    @Gojir4
                    This is generic code for making the QCompleter work (i.e. accept picking a suggestion as meaning we have edited the line edit, finished editing it, and want it to be acted on immediately if appropriate) against any QLineEdit it's attached to. Imagine this was functionality that Qt had decided to provide in their base, generic QCompleter. How would they have coded it? They cannot possibly know what/whether the QLineEdit has a specific function attached to it, can they?

                    The whole point of Qt's signal/slot mechanism is that objects/widgets emit signals and leave the outside world to connect those to slots as appropriate if desired, and that logic/behaviour (whether slots are attached and if so what they do), so that the signal emitter is isolated from what might be going on in the slot receiver(s).

                    1 Reply Last reply
                    0

                    • Login

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