Disable Dialog OK button until input valid
-
I am writing what I assumed to be a simple dialog, using
Dialog
. This holds a couple of input fields that need to be provided by the user before they should be allowed to click OK. I have got the layout how I want it and so on and now I find I am stuck in trying to add the logic to disable the button. Perhaps I am naive but I assumed that this would be straightforward. Am I missing something?In fact it seems that every time I have tried to use
Dialog
, I have hit some sort of issue. Since starting to write this question I thought to go back and look at some other things I have done and it turns out that I implemented something similar previously usingWindow
and doing all my own button handling logic and layout. Is that the correct way to do it or is there a simpler option staring me in the face? -
OK, apologies - I am still quite new to QML. Some things have clicked with me and others still seem to feel more difficult than I think they should.
I should have been more explicit. I understand the general paradigm but what was not obvious was how actually to get hold of the buttons to disable/enable them? ( @JonB you seem to be talking about Qt widgets - this is the QML sub-forum. As I say, I understand the principles and that is the sort of thing I would have done many years ago when I used to use Qt widgets.)
To answer my own question, it seems that I need to explicitly assign a
DialogButtonBox
as the footer. I can then reference thestandardButton
method on theDialogButtonBox
. To me this is an example of things just being a bit more inconvenient than they should be and involves a certain amount of reading between the lines in the documentation.For example:
import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Window 2.2 Window { visible: true width: 200 height: 200 title: qsTr("Hello World") Dialog { id: dlg modal: true height: parent.height width: parent.width TextField { anchors.centerIn: parent height: 30 width: 60 validator: IntValidator {} onTextEdited: { buttons.standardButton(Dialog.Ok).enabled = acceptableInput; } } footer: DialogButtonBox { id: buttons standardButtons: Dialog.Ok | Dialog.Cancel } onOpened: { buttons.standardButton(Dialog.Ok).enabled = false; } } Component.onCompleted: { dlg.open(); } }
-
Hi,
The usual way is to react on each modification of an input and then check if they are all provided and valid and only then enable the button.
-
I am writing what I assumed to be a simple dialog, using
Dialog
. This holds a couple of input fields that need to be provided by the user before they should be allowed to click OK. I have got the layout how I want it and so on and now I find I am stuck in trying to add the logic to disable the button. Perhaps I am naive but I assumed that this would be straightforward. Am I missing something?In fact it seems that every time I have tried to use
Dialog
, I have hit some sort of issue. Since starting to write this question I thought to go back and look at some other things I have done and it turns out that I implemented something similar previously usingWindow
and doing all my own button handling logic and layout. Is that the correct way to do it or is there a simpler option staring me in the face?@Bob64
Exactly as @SGaist has just said. You don't have to implement your own anything-complicated. No Dialog vs Window issue.You start with the button disabled. If your "input fields" are
QLineEdit
s, say, you will respond to theirtextChanged()
signal by looking to see if they are now "acceptable", and when they all are you enable the button.It is straightforward! :)
-
OK, apologies - I am still quite new to QML. Some things have clicked with me and others still seem to feel more difficult than I think they should.
I should have been more explicit. I understand the general paradigm but what was not obvious was how actually to get hold of the buttons to disable/enable them? ( @JonB you seem to be talking about Qt widgets - this is the QML sub-forum. As I say, I understand the principles and that is the sort of thing I would have done many years ago when I used to use Qt widgets.)
To answer my own question, it seems that I need to explicitly assign a
DialogButtonBox
as the footer. I can then reference thestandardButton
method on theDialogButtonBox
. To me this is an example of things just being a bit more inconvenient than they should be and involves a certain amount of reading between the lines in the documentation.For example:
import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Window 2.2 Window { visible: true width: 200 height: 200 title: qsTr("Hello World") Dialog { id: dlg modal: true height: parent.height width: parent.width TextField { anchors.centerIn: parent height: 30 width: 60 validator: IntValidator {} onTextEdited: { buttons.standardButton(Dialog.Ok).enabled = acceptableInput; } } footer: DialogButtonBox { id: buttons standardButtons: Dialog.Ok | Dialog.Cancel } onOpened: { buttons.standardButton(Dialog.Ok).enabled = false; } } Component.onCompleted: { dlg.open(); } }
-
OK, apologies - I am still quite new to QML. Some things have clicked with me and others still seem to feel more difficult than I think they should.
I should have been more explicit. I understand the general paradigm but what was not obvious was how actually to get hold of the buttons to disable/enable them? ( @JonB you seem to be talking about Qt widgets - this is the QML sub-forum. As I say, I understand the principles and that is the sort of thing I would have done many years ago when I used to use Qt widgets.)
To answer my own question, it seems that I need to explicitly assign a
DialogButtonBox
as the footer. I can then reference thestandardButton
method on theDialogButtonBox
. To me this is an example of things just being a bit more inconvenient than they should be and involves a certain amount of reading between the lines in the documentation.For example:
import QtQuick 2.9 import QtQuick.Controls 2.2 import QtQuick.Window 2.2 Window { visible: true width: 200 height: 200 title: qsTr("Hello World") Dialog { id: dlg modal: true height: parent.height width: parent.width TextField { anchors.centerIn: parent height: 30 width: 60 validator: IntValidator {} onTextEdited: { buttons.standardButton(Dialog.Ok).enabled = acceptableInput; } } footer: DialogButtonBox { id: buttons standardButtons: Dialog.Ok | Dialog.Cancel } onOpened: { buttons.standardButton(Dialog.Ok).enabled = false; } } Component.onCompleted: { dlg.open(); } }
-
Hi,
The usual way is to react on each modification of an input and then check if they are all provided and valid and only then enable the button.
@SGaist This seems like a workaround, rather than a solution, this is usually a bad way to do user-input validation. The assumption that you can just react to text change and enable/disable the button in all cases is shortsighted. What if I want to call a web service to validate, or perform some other time consuming or expensive operation?
-
@SGaist This seems like a workaround, rather than a solution, this is usually a bad way to do user-input validation. The assumption that you can just react to text change and enable/disable the button in all cases is shortsighted. What if I want to call a web service to validate, or perform some other time consuming or expensive operation?
@nenchev then you implement it differently.
My suggestion is not a solution applicable to all circonstances as there are no such things. If your validation takes that long to process then you have to give your user a better feedback to let them know longer processing is required and ongoing but it also does not makes sens to add a progress bar if your validation takes less than a second.