Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Enter key to accept dialog
Forum Updated to NodeBB v4.3 + New Features

Enter key to accept dialog

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
4 Posts 2 Posters 1.7k 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.
  • B Offline
    B Offline
    Bob64
    wrote on last edited by
    #1

    It's a fairly standard paradigm to be able to accept dialogs via enter/return and reject via escape, but QML does not offer any inbuilt support for this. I would like to get this working generally in my application but I am not sure what is the best/correct way to achieve it. I find the documentation discussion of keyboard focus to be a bit confusing so a big part of the problem I am sure is that I do not have a good mental model of how it works.

    As for what I have tried, most of my dialogs have an explicit DialogButtonBox assigned to the footer and I have been able to make some progress by:

    • calling forceActiveFocus() on the button box
    • adding key handlers (e.g. Keys.onEnterPressed: dlg.accept()) in the DialogButtonBox

    This works to an extent but the issue is how to ensure that forceActiveFocus is called whenever it needs to be. For example, with a simple message dialog, I can do it in onOpened, but once controls are added to the dialog that the user might start interacting with, focus is easily lost from the button box. For example, the second simplest dialog I have tried with has a single combo box. I got this to work by calling forceActiveFocus on the button box in the onClosed event for the combo popup, but this is all a bit ad hoc and doesn't scale to more complex situations.

    Is there a more generic solution to this?

    1 Reply Last reply
    0
    • M Offline
      M Offline
      Mr MinimalEffort
      wrote on last edited by
      #2

      Hi @Bob64 , there are a few ways to do this with focus scopes and the like, but simply put I think you are missing setting focus:true on the dialog itself (But without your code I can't be sure)
      As for navigation you can specify this with KeyNavigation.tab/backtab

      Here is an example dialog (Note I am using Qt6.2)

      Dialog {
          id: dialog
          title: "My Dialog"
          anchors.centerIn: parent
          focus: true
      
          Column {
              anchors.fill: parent
              Text {
                  text: "Here is my Dialog"
              }
              TextField {
                  id: textInput
                  placeholderText: "Input some text"
                  KeyNavigation.tab: textInput2
              }
              TextField {
                  id: textInput2
                  placeholderText: "Input some text"
                  KeyNavigation.backtab: textInput
                  KeyNavigation.tab: textInput3
              }
              TextField {
                  id: textInput3
                  placeholderText: "Input some text"
                  KeyNavigation.backtab: textInput2
                  KeyNavigation.tab: textInput
                  Keys.onReturnPressed: dialog.accept()
              }
      
              Row {
                  Button {
                      id: cancelButton
                      text: "Cancel"
                      onClicked: dialog.reject()
                  }
                  Button {
                      id: okButton
                      text: "Ok"
                      onClicked: dialog.accept()
                  }
              }
          }
      
          onAccepted: {
              console.log("Accepted")
          }
      
          onRejected: {
              console.log("Rejected")
          }
          onOpened: {
              textInput.focus = true
          }
      }
      

      If that doesn't explain what you want perhaps you could share your code that is not working.

      Kind Regards
      -Mr MinimalEffort

      (Windows 10, Qt-6.2, QtCreator-5.x)

      B 2 Replies Last reply
      0
      • M Mr MinimalEffort

        Hi @Bob64 , there are a few ways to do this with focus scopes and the like, but simply put I think you are missing setting focus:true on the dialog itself (But without your code I can't be sure)
        As for navigation you can specify this with KeyNavigation.tab/backtab

        Here is an example dialog (Note I am using Qt6.2)

        Dialog {
            id: dialog
            title: "My Dialog"
            anchors.centerIn: parent
            focus: true
        
            Column {
                anchors.fill: parent
                Text {
                    text: "Here is my Dialog"
                }
                TextField {
                    id: textInput
                    placeholderText: "Input some text"
                    KeyNavigation.tab: textInput2
                }
                TextField {
                    id: textInput2
                    placeholderText: "Input some text"
                    KeyNavigation.backtab: textInput
                    KeyNavigation.tab: textInput3
                }
                TextField {
                    id: textInput3
                    placeholderText: "Input some text"
                    KeyNavigation.backtab: textInput2
                    KeyNavigation.tab: textInput
                    Keys.onReturnPressed: dialog.accept()
                }
        
                Row {
                    Button {
                        id: cancelButton
                        text: "Cancel"
                        onClicked: dialog.reject()
                    }
                    Button {
                        id: okButton
                        text: "Ok"
                        onClicked: dialog.accept()
                    }
                }
            }
        
            onAccepted: {
                console.log("Accepted")
            }
        
            onRejected: {
                console.log("Rejected")
            }
            onOpened: {
                textInput.focus = true
            }
        }
        

        If that doesn't explain what you want perhaps you could share your code that is not working.

        B Offline
        B Offline
        Bob64
        wrote on last edited by
        #3

        Thank you @Mr-MinimalEffort. I am going to take another look today. I will try out your example and try to share a simple version of what I have.

        1 Reply Last reply
        0
        • M Mr MinimalEffort

          Hi @Bob64 , there are a few ways to do this with focus scopes and the like, but simply put I think you are missing setting focus:true on the dialog itself (But without your code I can't be sure)
          As for navigation you can specify this with KeyNavigation.tab/backtab

          Here is an example dialog (Note I am using Qt6.2)

          Dialog {
              id: dialog
              title: "My Dialog"
              anchors.centerIn: parent
              focus: true
          
              Column {
                  anchors.fill: parent
                  Text {
                      text: "Here is my Dialog"
                  }
                  TextField {
                      id: textInput
                      placeholderText: "Input some text"
                      KeyNavigation.tab: textInput2
                  }
                  TextField {
                      id: textInput2
                      placeholderText: "Input some text"
                      KeyNavigation.backtab: textInput
                      KeyNavigation.tab: textInput3
                  }
                  TextField {
                      id: textInput3
                      placeholderText: "Input some text"
                      KeyNavigation.backtab: textInput2
                      KeyNavigation.tab: textInput
                      Keys.onReturnPressed: dialog.accept()
                  }
          
                  Row {
                      Button {
                          id: cancelButton
                          text: "Cancel"
                          onClicked: dialog.reject()
                      }
                      Button {
                          id: okButton
                          text: "Ok"
                          onClicked: dialog.accept()
                      }
                  }
              }
          
              onAccepted: {
                  console.log("Accepted")
              }
          
              onRejected: {
                  console.log("Rejected")
              }
              onOpened: {
                  textInput.focus = true
              }
          }
          

          If that doesn't explain what you want perhaps you could share your code that is not working.

          B Offline
          B Offline
          Bob64
          wrote on last edited by
          #4

          @Mr-MinimalEffort I tried out your example. It is a good example of implementing keyboard navigation between fields but I don't think I explained very well because, whereas in a sense it goes further than what I was asking about, it does not do the main thing I am interested in which is how to implement behaviour such that dialogs may be accepted (i.e. equivalent of pressing "Ok") by pressing return/enter on keyboard. This is supported out of the box in QtWidgets by the concept of a 'default' button.

          Here's an example from Visual Studio on Windows, the Tools...|Options dialog:

          c4538310-002e-4a63-a8e8-67146649ee72-image.png

          As you can see, the OK button is highlighted here to indicate that it is the default button. No matter how much I click around in the dialog, I can at any point press my return key to accept the dialog.

          Here's some example code with three dialogs: the one you provided, a simple message dialog with the most basic out of the box implementation, and a modified version of the latter that does what I want it to but I don't know if this is the right way to do it. I haven't posted it yet, but the next one would have a single combo widget which causes more complication because it can take focus away from the buttons. However, it would be good to understand the options for the most basic case before getting into that.

          (BTW I am, for work reasons, unfortunately still on 5.9.6.)

          import QtQuick 2.9
          import QtQuick.Window 2.2
          import QtQuick.Controls 2.2
          
          Window {
              visible: true
              width: 640
              height: 480
              title: qsTr("Hello World")
          
              Dialog {
                  id: dialog1
                  title: "My Dialog"
          
                  x: (parent.width - width)/2
                  y: (parent.height - height)/2
          
                  focus: true
          
                  Column {
                      anchors.fill: parent
                      Text {
                          text: "Here is my Dialog"
                      }
                      TextField {
                          id: textInput
                          placeholderText: "Input some text"
                          KeyNavigation.tab: textInput2
                      }
                      TextField {
                          id: textInput2
                          placeholderText: "Input some text"
                          KeyNavigation.backtab: textInput
                          KeyNavigation.tab: textInput3
                      }
                      TextField {
                          id: textInput3
                          placeholderText: "Input some text"
                          KeyNavigation.backtab: textInput2
                          KeyNavigation.tab: textInput
                          Keys.onReturnPressed: dialog.accept()
                      }
          
                      Row {
                          Button {
                              id: cancelButton
                              text: "Cancel"
                              onClicked: dialog.reject()
                          }
                          Button {
                              id: okButton
                              text: "Ok"
                              onClicked: dialog.accept()
                          }
                      }
                  }
          
                  onAccepted: {
                      console.log("Accepted")
                  }
          
                  onRejected: {
                      console.log("Rejected")
                  }
                  onOpened: {
                      textInput.focus = true
                  }
              }
          
              Dialog {
                  id: dialog2
          
                  height: 150; width: 150
                  x: (parent.width - width) / 2
                  y: (parent.height - height) / 2
          
                  focus: true
                  modal: true
          
                  Label {
                      verticalAlignment: Text.AlignVCenter
                      horizontalAlignment: Text.AlignHCenter
                      anchors.centerIn: parent
                      text: "Hello"
                  }
          
                  standardButtons: Dialog.Ok
              }
          
              Dialog {
                  id: dialog3
          
                  height: 150; width: 150
                  x: (parent.width - width) / 2
                  y: (parent.height - height) / 2
          
                  focus: true
                  modal: true
          
                  Label {
                      verticalAlignment: Text.AlignVCenter
                      horizontalAlignment: Text.AlignHCenter
                      anchors.centerIn: parent
                      text: "Hello"
                  }
          
                  standardButtons: Dialog.Ok
          
                  footer: DialogButtonBox {
                      id: buttons
                      standardButtons: Dialog.Ok
                      alignment: Qt.AlignHCenter
                      Keys.onEnterPressed: dialog3.accept()
                      Keys.onReturnPressed: dialog3.accept()
          
                      onVisibleChanged: if (visible) forceActiveFocus()
                  }
              }
          
              Column {
                  anchors.top: parent.top
                  anchors.left: parent.left
                  anchors.margins: 5
          
                  spacing: 5
          
                  Button {
                      text: "Open dialog 1"
                      onClicked: dialog1.open()
                  }
                  Button {
                      text: "Open dialog 2"
                      onClicked: dialog2.open()
                  }
                  Button {
                      text: "Open dialog 3"
                      onClicked: dialog3.open()
                  }
              }
          }
          
          
          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