Signal slot question



  • Hello all,

    I ran into some peculiar behaviour. Maybe because I'm newbie on this stuff.
    I will give an example.

    On the QDialog D there is a QLineEdit L, QComboBox C, QPushButton P. P is the OK button to close the dialog.
    P has a private slot in D on_P_clicked(). The private slot is there save the state of L & C.
    For L there is a private slot on_L_editingFinished() to validate what the user typed in.

    Sometimes the dialog disappears and then I get a validation error from on_L_editingFinished.

    Is there a (Qt) way that the editingFinished signal fires always first? I mean before the signal from C and/or P.

    Regards,

    Theo.



  • No, there is not.
    If you want things to happen in a certain sequence, just make you emit the signals in that sequence or ensure in some other way that the event happen in the right order. Do not rely on the slots connected to a single signal to be called in a specific order, even if they are in practice.

    Also, please mind your terminology to keep things clear:

    • a signal is emitted or, if you will, fires
    • a slot is invoked
    • a signal is connected to a slot

    So, P doesn't "have a private slot", but is connected to a private slot in D.



  • [quote author="Andre" date="1295524209"]No, there is not.
    If you want things to happen in a certain sequence, just make you emit the signals in that sequence or ensure in some other way that the event happen in the right order. Do not rely on the slots connected to a single signal to be called in a specific order, even if they are in practice.
    [/quote]

    <nitpick mode=on>
    Trolls have decided to make this behaviour public:

    [quote]If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted.[/quote]
    </nitpick>



  • Darn. I knew it :-(

    Anyway, I still think it is bad practice to rely on it, if only for the fact that it is not easy to spot from the code what the order is going to be.



  • If there no Qt way of doing this, then consider it as a feature request.
    Because it stands in the way of fast coding and user experience.

    If I must make al sorts of signal slot connections to get right firing order, there is something missing in Qt.

    The user goes form one field to another mostly in the order he likes.
    The editingFinished signal is a great signal to validate user input. But now I have to program around it because signal firing order is unpredictable. Because the clicked signal of P is earlier than the editingFinished signal of L.

    The user wants to know if he did something wrong immediately when he is finished editing the field by clicking somewhere else. In my testcase the Ok button.

    Now, I've put all the validations under the Ok button. But it is not user friendly because if you have a lot of input fields the user knows when he did something wrong at the end of the input session.



  • Theo, I must have misunderstood your question the first time, even though I thought I read it carefully. Your second posting is more clear in that aspect.

    I gather that this is what you do:[quote]
    You have a form, with a QLineEdit on it. You use the QLineEdit's editingFinished signal to do some validation on the line edit.
    On the form, you also have a pushbutton, that closes the form.

    The problem is, that if the user was editing the line edit, and then clicks the pushbutton, the order in which the signals are emitted is unpredictable, and can thus cause problems with the validation. [/quote]

    Did I understood you correctly? The invokation ordering peppe and I were talking about, was about slots connected to the same signal. You have a different situation. I am not sure, why the editing finished signal would be fired after a clicked signal of the button. There may be some kind of race condition there, perhaps depending on the speed of the click or something like that, but that is worth investigating.

    I agree that it would be nice to do all validations immediately. I think that is possible, if you use QValidators. You can attach those to another widget to handle validation in a nicely integrated way. There are standard validators available for integer, doubles and regular expressions, but you can also make your own by subclassing QValidator.

    I would disable an OK button if not all the input is valid, by the way.

    Note that putting a posting on this forum is a sure way of having a feature request be ignored. Not a lot of Qt Developers will read it, and even if they do, it will get lost. If you want to suggest a feature, use the "Qt bugtracker":http://bugreports.qt.nokia.com (often refered to as Jira, the name of the system used).



  • Hi,

    as far as I know, editing finished is emitted on focusOutEvent. Clicked for buttons is emitted on mouseReleaseEvent and on keyUp.
    So both rely on windows event orders. I'm not 100% sure, whether focusOut is send before the mouse click is finished by windows....
    Especially as you are inside Qt, and perhaps have alien widgets (no windows for each widget), then it relies on Qt's logic regarding mouse press / release / focus.



  • I'm programming on the N900 on Maemo 5. I'm relying completely on Qt. I'm trying to make 100% portable app. The app must be portable between Maemo and Symbian devices. The reason that I asked it here was because this signal slot thing seems to be generic to Qt.

    The QValidator is queried every time you type. In most of my cases I validate against the filesystem and other against a database and a small number against the Internet.
    I think, QValidator will make in such cases the app unresponsive. I think you can use QValidator best when you want some simple intelligent input masking in memory but not for queries I mentioned above.



  • OK, fair enough. If validating is expensive, then this is a good reason to delay it to later on. Signals and slots are indeed a core functionality of Qt. Other implementations of the same concept (such as the one in Boost) are from a later date.

    I think I also know why your push-button clicked() signal may be delivered before your validation is complete: network operations are asynchronous. That means that the eventloop keeps running while you wait for a response. That is a good thing, in general. However, here it means that the click on the push button is processed before the validation is finished. That of course causes trouble, as you noticed. I think this, or something similar, may be at the root of your problem.

    To get around it, I would advice you to disable the OK button while your form is in an inconsistent state. This way, you can not get into this situation at all, and your users will get decent feedback that they can not exit your form yet. What I would do is trigger the validation in a combination of ways, using a timer. You can do something like this for either a single widget, or for the complete form:

    • create a QTimer, set it to, say, 2 seconds
    • on a textChanged() signal, start the timer, or if it is already running, restart the timer
    • on an editingFinished signal, trigger the validation
    • on timeout of the timer, trigger the validation
    • in the validation, stop the timer.

    This way, your form will start validating the input when the user moves to the next field, but also if the user does not give any input for a set period of time. The latter can be convenient if there is only one field, or if the user is at the last field of a form. As soon as all fields contain valid input, you enable the OK button. While a validation is still running, you display a bussy: validating message of some sort near or on that button.

    This setup will work just fine for the expensive kind of validation you're talking about.



  • Gerolf mentioned it: editingFinished() is emitted on focus out event of the line edit.

    Pressing a push button does not necessarily change the focus, so when pressing the button, focus lasts in the line edit. The slot that is called on the pushbutton click eventually closes the dialog - this is the moment when the line edit looses focus and fires its signal.

    My solution would be to validate the input in the slot that is called by push button's click and not close the dialog if the validation failed. You can cache the validation result to speed up things (and connect a needsValidation slot that sets a bool to true with the textChanged or textEdited signals; or use isModified property)



  • Hello Volker,

    That's what I've done. I've written it in my second post in this thread. I'm a programmer that is not very patient and keeps waiting until someone gives me the ultimate solution.

    But, I still believe that there must come some functionality to allow programmers to validate the input fields, once.

    Regards,

    Theo



  • [quote author="Theo Kromhout van der Meer" date="1295598936"]
    But, I still believe that there must come some functionality to allow programmers to validate the input fields, once.
    [/quote]

    That's up to the programmer, since there is no general way of what and when how fields should be validated.

    Good practice is to validate the input fields just after they are changed (if that is possible - you mentioned a time penalty) or to validate all fields and reject to close the dialog if something is wrong.

    Both methods are very easy to achieve with the current means of Qt; I don't see any further option that should be implemented.



  • bq. "Is there a (Qt) way that the editingFinished signal fires always first? I mean before the signal from C and/or P."

    Hi all,

    Though it's an old post, I've found the solution to the issue on top:

    I had the same problem with a dialog containing QLineEdit and QPshButton:
    When editing the line-edit and just after it clicking the push-button, the slot connected to the push-button-siganl was fired first.

    The reason is that by default, the focus-policy of push-button is "TabFocus". Meaning the widget accepts keyboard focus by tabbing, NOT by clicking.

    When I clicked the button, the focus was still in the line-edit, therefore the "editingFinished" wasn't emitted.

    Solution:
    At the QT-designer, you should change the "focusPolicy" property of the push-button to "StrongFocus". Now the widget accepts focus by both tabbing and clicking. When you edit the line-edit, and then click the push-button, the "editingFinished" is emitted first.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.