0
votes

I created a qtquick 2.4 file and in the file I used TextInput and ListView. What I want is when user writing something in the TextInput, ListView appears below the TextInput to suggest some words to the user and when user click out of the MouseArea of ListView or TextInput, anywhere in the qtquick file, ListView is being hidden. But my problem is I don't know how should I hide the listview when user click out of the MouseArea of ListView or TextInput? I tried to use Menu component instead of ListView but due to problem in using Menu component, I couldn't use that.

Rectangle{
    height: 400;
    width: 400;

Rectangle {
id: cbxRoot;
width: 150
height: 45;
color: "white";
border.color: "black";
radius: 5;
property bool cbxtriggered: false;

TextInput
{
    id: cbxTextBox;
    anchors.top: parent.top;
    width: 150
    height:45 ;
    verticalAlignment: Text.AlignVCenter;
    color: "black";
    horizontalAlignment: Text.AlignHCenter;
    clip: true;
    readOnly: false;

    MouseArea
    {
        id: cbxMouseArea;
        anchors.fill: parent;
        enabled: true;

        onClicked:
        {
            cbxTextBox.focus = true;
            if(cbxRoot.cbxtriggered)
            {
                cbxRoot.cbxtriggered = false;
            }
            else
            {
                cbxRoot.cbxtriggered = true;
            }
        }
    }

    selectByMouse: true;

    Keys.onPressed:
    {
        cbxRoot.cbxtriggered = true;
    }

    onTextChanged:
    {
        var maxChar = 30;
        var txtInput = cbxTextBox;
        if(txtInput.text.length > maxChar)
        {
            txtInput.text = txtInput.text.substring(0,maxChar);
            txtInput.cursorPosition = maxChar;
        }
    }
}

ListModel
{
    id: cbxListModel;
    ListElement { name: "Theme"; number: 0 }
    ListElement { name: "Theme"; number: 1 }
    ListElement { name: "Theme"; number: 2 }
    ListElement { name: "Theme"; number: 3 }
    ListElement { name: "Theme"; number: 4 }
}

ListView
{
    id: cbxListView;
    anchors.top : cbxTextBox.bottom;
    visible: cbxRoot.cbxtriggered;
    focus: true;
    displayMarginBeginning: contentHeight;
    displayMarginEnd: contentHeight;
    spacing: 2;
    model: cbxListModel;
    delegate: Text {
          text: name + ", " + number
      }

    clip: false;
    width: cbxRoot.width;
    height: 70;
}
}
}
1
If it is a reusable component you should work on the focus state and change visibility according to that. You can force focus with forceActiveFocus(). If it is not a component you can add a MouseArea outside the TextInput and use that to unfocus it. Which one is your case?BaCaRoZzo
Thanks you for your quick reply. I used a reusable component, but I have multi components in my qml file, it seems to be difficult to active focus on every component in my qml file. I want a easier method to handle it.Behzad
Focus management in Qt quick is really a mess, sometimes. I agree with you. However, in this case it shoudn't be a big issue. I'll provide an example later today to see if it could fit your needs.BaCaRoZzo

1 Answers

0
votes

Try to create a MouseArea just beneath the input controls (InputText and ListView in this case), and whatever it is clicked the input mode should be cancelled. The way mouse events are handled and eaten by input controls but events outside them are handled by MouseArea. Take a look this code:

import QtQuick 2.2

Rectangle{
    height: 400
    width: 400
    border.width: 5

    property alias inputFocused: inputTextBox.focus

    ListModel{
        id: cbxListModel;
        ListElement { name: "Theme"; number: 0 }
        ListElement { name: "Theme"; number: 1 }
        ListElement { name: "Theme"; number: 2 }
        ListElement { name: "Theme"; number: 3 }
        ListElement { name: "Theme"; number: 4 }
    }

    MouseArea{
        id: cancelArea
        anchors.fill: parent

        enabled: inputFocused
        visible: enabled
        z: inputGroup.z-1 // just beneath inputGroup

        onClicked: inputFocused = false
    }

    Item{
        id: inputGroup
        anchors{
            top: parent.top
            topMargin: 56
            horizontalCenter: parent.horizontalCenter
        }

        // if there are more controls, raise the z parameter
        // to raise cancelArea over them but beneath inputGroup
        z: inputFocused ? 99 : 0

        width: 200
        height: 200

        TextInput{
            id: inputTextBox
            anchors{
                top: parent.top
            }
            width: parent.width
            height: 24
            Rectangle{
                anchors.fill: parent
                anchors.margins: -3
                color: "transparent"
                border.width: 1
            }
        }

        ListView{
            id: cbxListView;
            anchors{
                top: inputTextBox.bottom
                topMargin: 12
            }
            width: parent.width
            height: 70;

            visible: inputFocused;

            model: cbxListModel;
            spacing: 2;
            delegate: Text {
                  text: name + ", " + number
              }

            clip: false;
        }

    }
}

I hope this solution fits your needs.