2016-09-05 5 views
3

다중 선택을 지원하는 QML ListView을 만들었으며이 중 여러 개를 내 응용 프로그램에서 인스턴스화합니다. 키보드 포커스를 특정 목록에 제공하고 해당 목록에 대한 키 누름을 처리하고 포커스에 따라 선택한 행에 대한 강조 표시를 그려야합니다.ListView간에 포커스 전달

그러나 ListView 대리자 또는 ListView 자체에 focus=true을 지정하면 activeFocus이 ListView에 나타나지 않으며 키 누르기 신호가 트리거되지 않습니다.

중 하나를 목록 enter image description here

import QtQuick 2.7 
import QtQuick.Window 2.0 

Window { 
    id:window; visible:true; width:400; height:160; color:'darkgray' 

    Component { 
    id: row 
    Rectangle { 
     id: root 
     property int i: index 
     property bool current: ListView.isCurrentItem 
     property bool focused: ListView.view.activeFocus 
     width:parent.width; height:20 
     color: current ? (focused ? 'pink' : 'lightblue') : 'lightgray' 
     MouseArea { 
     anchors.fill: parent 
     onClicked: { 
      root.ListView.view.currentIndex = i; 
      root.ListView.view.focus = true; 
     } 
     } 
     Text { anchors.fill:parent; text:modelData } 
    } 
    } 

    Component { 
    id: myList 
    ListView { 
     delegate: row 
     width:window.width/2-10; height:window.height; y:5 
     Keys.onUpPressed: decrementCurrentIndex() 
     Keys.onDownPressed: incrementCurrentIndex() 
    } 
    } 

    Loader { 
    sourceComponent:myList; x:5 
    onLoaded: item.model = ['a','b','c','d'] 
    } 
    Loader { 
    sourceComponent:myList; x:window.width/2 
    onLoaded: item.model = ['1','2','3','4','5'] 
    } 
} 

을 클릭하면, 선택한 행 핑크를 설정하지 않고 아래 선택을 조정하지 않습니다/키를 누르면 :

나는 내 문제를 보여주는 간단한 예제 응용 프로그램을 만들었습니다 .

(a) 한 번에 하나의 ListView 만 보유하고 (b) ListView가이 포커스를 유지하는 경우를 감지 할 수 있고 (c) 키보드 신호를 허용하도록 특정 ListView에 포커스를 전달할 수 있습니까? 포커스가있는 동안에 만 ListView에서 작업 할 수 있습니까?

중요한 경우에 대비하여 Qt 5.7을 사용하고 있습니다.


상황이 내가 실패, 시도했다 :

  • 대신 ListView에의 사각형에 focus=true 설정.
  • 속성을 activeFocus 대신 ListView.view.focus으로 보도록 설정하면 두 목록을 동시에 핑크로 바꿀 수 있습니다.
  • Keyboard Focus in Qt Quick을 통해 읽고 FocusScope에있는 사각형 또는 ListView를 래핑하십시오. (게다가, 모든 인터페이스를 따라 전달되는 통증).

    • 다시 판독 하루의 빛의 페이지를 단일 FocusScope에서 두 Loader 배치. 하나의 객체가 true로 Item::focus 세트를 가질 수있는 각 내에서

      범위를 초점 : 모두의 ListView 같은 저주는 분명히 문서의이 섹션의 내 독서를 위반 동시 초점을 가질 수 있습니다. 두 개 이상의 항목에 focus 속성 집합이있는 경우 포커스를 설정할 마지막 형식은 focus이고 나머지는 포커스 범위가없는 경우와 마찬가지로 해제됩니다.

  • 아이템의 ListView를 포장하고 해당 항목에 키 핸들러를두고, 그 항목을 집중하려고.

  • ListView에 interactive:false을 설정하십시오.
  • ListView에 keyNavigationEnabled:false을 설정하십시오. (이상한 결과는 5.7에서 소개되었다는 도움말과 QtQuick 2.7이 적절한 import 문임을 암시 함에도 불구하고 "ListView.keyNavigationEnabled" is not available in QtQuick 2.7을 산출합니다.)
  • focus:true을 단지 모든 경우에 찾을 수있는 모든 객체에 넣을 수 있습니다.

참고 : 나는 표준 ListView이 선택을 보여주기 위해 highlight를 사용하고, 키보드 탐색이 currentItem을 조정하는 것으로 알고 있습니다. 그러나 필자의 필요에 따라 동시에 여러 항목을 선택해야하기 때문에 강조와 키보드를 특별히 관리해야합니다.


편집 : 각 사각형에

import QtQuick 2.7 
import QtQuick.Window 2.0 

Window { 
    id:window; visible:true; width:400; height:160; color:'darkgray' 

    FocusScope { 
    Rectangle { 
     width: window.width/2-6; height:window.height-8; x:4; y:4 
     color: focus ? 'red' : 'gray' 
     MouseArea { anchors.fill:parent; onClicked:parent.focus=true } 
     Text { text:'focused'; visible:parent.activeFocus } 
     Keys.onSpacePressed: console.log('space left') 
    } 
    Rectangle { 
     width: window.width/2-6; height:window.height-8; x:window.width/2+2; y:4 
     color: focus ? 'red' : 'gray' 
     MouseArea { anchors.fill:parent; onClicked:parent.focus=true } 
     Text { text:'focused'; visible:parent.activeFocus } 
     Keys.onSpacePressed: console.log('space right') 
    } 
    } 
} 

을 클릭하면이 빨간색으로 만들고, 하나의 어떤에서 빨간색으로 할 수있다 : 여기에 내가 기대하는 것처럼 행동 아니에요 간단한 테스트 케이스이다 주어진 시간. (좋습니다.) 그러나 Rectangle에는 activeFocus이 없기 때문에 "focused"텍스트가 표시되지 않습니다. 또한 키를 누르면 중 하나에 포커스가있을 때 메시지가 기록되지 않습니다.

편집 2 : Whoa. FocusScope를 삭제하면 예상대로 작동합니다. 포커스는 여전히 독점적이며 activeFocus이 부여되고 공백은입니다. 아마도 위의 내 문제는 ListViewFocusScope (문서에 따르면)이기 때문일 수 있습니다.

편집 3 아래 미치의 코멘트 당은 FocusScopefocus:true 설정은 모든 것이 FocusScope 제대로 작동 할 수 있습니다. 그러나, 내 대답 아래 (그리고 미치의 의견), FocusScope 내 간단한 샘플 애플 리케이션 중 하나를 올바르게 작동 얻을 필요가 없습니다.

+0

이 [예제] (http://doc.qt.io/qt-5/qml-qtquick-listview.html#example-usage)를 사용하면 기본적으로 키보드 포커스를 얻게됩니다. 'ListView'의 부모로'Rectangle'을 설정할 수 있는지 모르겠습니다. – Tarod

+0

편집부 : 하나 이상의 동시 요소에'focus : true '가 허용되는 이유는 무엇입니까? Qt를 사용하면 여러 항목을 동시에 "집중"시킬 수있는 기이 한 개념의 집중이 가능합니까? 왜 FocusScope는 이것에 대한 해결책입니까? – Phrogz

+0

'focus'는 명령 이상의 요청입니다. 'activeFocus'는 아이템이 실제로 포커스되었는지 여부를 나타냅니다. 초점 물건은 약간의 악몽 일 수 있지만, 나는 동의한다. 나는 당신이'focus : true'로 두 개의 다른 항목을보고있는 것을 모른다. 그러나 필요할 수도있다. – Mitch

답변

3

onActiveFocusItemChanged: print(activeFocusItem) 

당신이 볼 수있는 당신이 원래의 예에서 활성 초점 항목을 인쇄하는 경우 로더 중 어느 것도 포커스를 얻지 못한다. 항상 창의 기본 항목입니다.당신은 그것의 위임을 클릭하면

import QtQuick 2.7 
import QtQuick.Window 2.2 

Window { 
    id: window 
    visible: true 
    width: 400 
    height: 160 
    color: 'darkgray' 

    onActiveFocusItemChanged: print(activeFocusItem) 

    Component { 
     id: row 
     Rectangle { 
      id: root 
      property int i: index 
      property bool current: ListView.isCurrentItem 
      property bool focused: ListView.view.activeFocus 
      width: parent.width 
      height: 20 
      color: current ? (focused ? 'pink' : 'lightblue') : 'lightgray' 

      MouseArea { 
       anchors.fill: parent 
       onClicked: { 
        root.ListView.view.currentIndex = i 
        root.ListView.view.focus = true 
       } 
      } 
      Text { 
       anchors.fill: parent 
       text: modelData 
      } 
     } 
    } 

    Component { 
     id: myList 
     ListView { 
      delegate: row 
      width: window.width/2 - 10 
      height: window.height 
      y: 5 
      Keys.onUpPressed: decrementCurrentIndex() 
      Keys.onDownPressed: incrementCurrentIndex() 
     } 
    } 

    Loader { 
     objectName: "loader1" 
     sourceComponent: myList 
     focus: true 
     x: 5 
     onLoaded: item.model = ['a', 'b', 'c', 'd'] 
    } 
    Loader { 
     objectName: "loader2" 
     sourceComponent: myList 
     x: window.width/2 
     onLoaded: item.model = ['1', '2', '3', '4', '5'] 
    } 
} 

그러나, 이제 두 번째 뷰가 초점이되지 않습니다

당신이 로더의 하나에 focus: true을 설정하면

은, 그것은 초점을 것입니다. 우리가 초점을 둘 다 선언했다면, 우리는 어느 것이 초점을 맞출 지 통제권을 잃게됩니다. 사실, 두 번째 뷰의 대리자를 클릭해도 포커스가있는 것으로 선언하더라도 두 번째 뷰의 대리자를 클릭해도 해당 뷰가 활성 포커스가되지 않습니다. 첫 번째 로더가 포커스를 잃었을 때 포커스를 잃어 버렸기 때문입니다. 그것이 작동하는 즉, 당신이 좋은 작은 번들 위임 구성 요소를 갖는 전체 목적 패배뿐만 아니라 초점 로더, 제공해야 할 것 :이 시점에서

import QtQuick 2.7 
import QtQuick.Window 2.2 

Window { 
    id: window 
    visible: true 
    width: 400 
    height: 160 
    color: 'darkgray' 

    onActiveFocusItemChanged: print(activeFocusItem) 

    Component { 
     id: row 
     Rectangle { 
      id: root 
      property int i: index 
      property bool current: ListView.isCurrentItem 
      property bool focused: ListView.view.activeFocus 
      width: parent.width 
      height: 20 
      color: current ? (focused ? 'pink' : 'lightblue') : 'lightgray' 

      MouseArea { 
       anchors.fill: parent 
       onClicked: { 
        root.ListView.view.currentIndex = i 
        root.ListView.view.parent.focus = true 
        root.ListView.view.focus = true 
       } 
      } 
      Text { 
       anchors.fill: parent 
       text: modelData 
      } 
     } 
    } 

    Component { 
     id: myList 
     ListView { 
      delegate: row 
      width: window.width/2 - 10 
      height: window.height 
      y: 5 
      Keys.onUpPressed: decrementCurrentIndex() 
      Keys.onDownPressed: incrementCurrentIndex() 
     } 
    } 

    Loader { 
     objectName: "loader1" 
     sourceComponent: myList 
     x: 5 
     onLoaded: item.model = ['a', 'b', 'c', 'd'] 
    } 
    Loader { 
     objectName: "loader2" 
     sourceComponent: myList 
     x: window.width/2 
     onLoaded: item.model = ['1', '2', '3', '4', '5'] 
    } 
} 

을 그냥 것 포기하고 적극적으로 초점을 맞추어 라 :

import QtQuick 2.7 
import QtQuick.Window 2.2 

Window { 
    id: window 
    visible: true 
    width: 400 
    height: 160 
    color: 'darkgray' 

    onActiveFocusItemChanged: print(activeFocusItem) 

    Component { 
     id: row 
     Rectangle { 
      id: root 
      objectName: ListView.view.objectName + "Rectangle" + index 
      property int i: index 
      property bool current: ListView.isCurrentItem 
      property bool focused: ListView.view.activeFocus 
      width: parent.width 
      height: 20 
      color: current ? (focused ? 'pink' : 'lightblue') : 'lightgray' 
      MouseArea { 
       anchors.fill: parent 
       onClicked: { 
        root.ListView.view.currentIndex = i 
        root.ListView.view.forceActiveFocus() 
       } 
      } 
      Text { 
       anchors.fill: parent 
       text: modelData 
      } 
     } 
    } 

    Component { 
     id: myList 
     ListView { 
      objectName: parent.objectName + "ListView" 
      delegate: row 
      width: window.width/2 - 10 
      height: window.height 
      y: 5 
      Keys.onUpPressed: decrementCurrentIndex() 
      Keys.onDownPressed: incrementCurrentIndex() 
     } 
    } 

    Loader { 
     id: loader1 
     objectName: "loader1" 
     sourceComponent: myList 
     x: 5 
     onLoaded: item.model = ['a', 'b', 'c', 'd'] 
    } 
    Loader { 
     objectName: "loader2" 
     sourceComponent: myList 
     x: window.width/2 
     onLoaded: item.model = ['1', '2', '3', '4', '5'] 
    } 
} 

나는 정말로 초점 시스템을 싫어한다. 나는 더 나은 것을 생각해 낼 수 있다고 말하는 것이 아니지만, 사용하기 쉽지 않습니다.

+0

흥미 롭습니다. 저는 여러분에게 여기서 배우고있는 것은 자식 항목이 포커스를 얻으려면 그 조상도 포커스가 있어야한다는 것입니다. 사실이라면, 이것은 나에게 거꾸로 보입니다. 하위 항목에 초점을두면 모든 상위 항목에 초점을 맞출 수 있다고 가정했습니다. – Phrogz

+2

['forceActiveFocus()'] (http://doc.qt.io/qt-5/qml-qtquick-item.html#forceActiveFocus-method)에 대해 정말 감사합니다. 그것은 매력처럼 작동합니다. – Phrogz

0

내 원래 샘플 응용 프로그램의 문제는 내 Loader의 사용과 관련이있는 것 같습니다.

ListView { 
    width:window.width/2-6; height:window.height-8; x:4; y:4 
    delegate: row 
    model: ['a','b','c','d'] 
    Keys.onUpPressed: decrementCurrentIndex() 
    Keys.onDownPressed: incrementCurrentIndex() 
} 
ListView { 
    width:window.width/2-6; height:window.height-8; x:window.width/2+2; y:4 
    delegate: row 
    model: ['1','2','3','4','5'] 
    Keys.onUpPressed: decrementCurrentIndex() 
    Keys.onDownPressed: incrementCurrentIndex() 
} 

... 내가 파일 기반 구성 요소를 사용하는 경우 그것은 또한 작동합니다 : 명시 적 목록 내 로더 코드를 대체하는 윈도우 위임 구성 요소 코드를 무시하는 것은 작동

MyList.qml을

import QtQuick 2.7 
ListView { 
    delegate: row 
    width:window.width/2-6; height:window.height-8; y:4 
    Keys.onUpPressed: decrementCurrentIndex() 
    Keys.onDownPressed: incrementCurrentIndex() 
} 

main.qml

// ...Window and row component as in the question above.. 
MyList { x:4;    model:['a','b','c','d']  } 
MyList { x:window.width/2+2; model: ['1','2','3','4','5'] } 

...하지만 ListViewactiveFocus 준 적이 있기 때문에이 원래 코드는 작동하지 않습니다

Component { 
    id: myList 
    ListView { 
    delegate: row 
    width:window.width/2-6; height:window.height-8; y:4 
    Keys.onUpPressed: decrementCurrentIndex() 
    Keys.onDownPressed: incrementCurrentIndex() 
    } 
} 
Loader { 
    sourceComponent:myList; x:4 
    onLoaded: item.model = ['a','b','c','d'] 
} 
Loader { 
    sourceComponent:myList; x:window.width/2+2 
    onLoaded: item.model = ['1','2','3','4','5'] 
} 
+0

아쉽게도 내 실제 응용 프로그램은 로더를 사용하지 않으므로 초점이가는 곳을 알아 내기 위해이 간단한 코드와 샘플 코드 간의 차이점을 더 찾아야 할 것입니다. – Phrogz