Qt 如何使Flickable确保其内部项目的可见性?

Qt 如何使Flickable确保其内部项目的可见性?,qt,qml,flickable,Qt,Qml,Flickable,我有一个Flickable,其中包含大量TextField对象,它们排列在一列中,每个TextField都固定在前一个TextField的底部。一切正常,只是当我使用tab键浏览这些字段时,焦点最终会转到Flickable可见矩形之外的文本字段,然后用户在手动向下滚动Flickable之前无法看到光标 本质上,我在寻找某种“.EnsureRevisible()”方法,这样当文本字段接收到焦点时,Flickable会自动滚动,以便刚刚聚焦的文本字段完全可见。您是否考虑过一种更为典型的ar方法?我的

我有一个
Flickable
,其中包含大量
TextField
对象,它们排列在一列中,每个TextField都固定在前一个TextField的底部。一切正常,只是当我使用tab键浏览这些字段时,焦点最终会转到
Flickable
可见矩形之外的文本字段,然后用户在手动向下滚动Flickable之前无法看到光标


本质上,我在寻找某种“.EnsureRevisible()”方法,这样当文本字段接收到焦点时,Flickable会自动滚动,以便刚刚聚焦的文本字段完全可见。

您是否考虑过一种更为典型的ar方法?我的意思是,如果您使用类似于
ListView
的东西,您可以简单地更改
currentItem
,此时,如果视图超出可见范围,视图将自动滚动到它

此外,它将只加载可见范围内的文本元素,从而节省一些内存

但即使使用当前的方法,确保可见性也不会那么复杂

  Flickable {
    id: flick
    anchors.fill: parent
    contentHeight: col.height
    function ensureVisible(item) {
      var ypos = item.mapToItem(contentItem, 0, 0).y
      var ext = item.height + ypos
      if ( ypos < contentY // begins before
          || ypos > contentY + height // begins after
          || ext < contentY // ends before
          || ext > contentY + height) { // ends after
        // don't exceed bounds
        contentY = Math.max(0, Math.min(ypos - height + item.height, contentHeight - height))
      }
    }
    Column {
      id: col
      Repeater {
        id: rep
        model: 20
        delegate: Text {
          id: del
          text: "this is item " + index
          Keys.onPressed: rep.itemAt((index + 1) % rep.count).focus = true
          focus: index === 0
          color: focus ? "red" : "black"
          font.pointSize: 40
          onFocusChanged: if (focus) flick.ensureVisible(del)
        }
      }
    }
  }
Flickable{
id:flick
锚定。填充:父级
contentHeight:col.height
功能可修改(项目){
var ypos=item.mapToItem(contentItem,0,0).y
var ext=item.height+ypos
如果(ypos内容+高度//在
||extcontentY+height){//结束于
//不要越界
contentY=Math.max(0,Math.min(ypos-height+item.height,contentHeight-height))
}
}
纵队{
id:col
中继器{
id:rep
型号:20
代表:文本{
id:del
文本:“这是项目”+索引
Keys.on按下:rep.itemAt((索引+1)%rep.count)。焦点=真
焦点:索引===0
颜色:聚焦?“红色”:“黑色”
font.pointSize:40
onFocusChanged:if(焦点)flick.ensurerevible(del)
}
}
}
}
解决方案是快速而粗糙的,但将其投入生产形态将是微不足道的。映射到
contentItem
而不是flickable是很重要的,因为考虑到当前的滚动量,flickable会给出错误的结果。使用映射将使解决方案不受您可能使用的任何定位方案的影响,还将支持任意级别的嵌套对象。

dtech的答案是正确的。 它很容易与一个很好的捕捉动画相结合,也很容易为x方向的flickables进行修改。此外,用户可能故意轻弹或拖动flickable。在我的例子中,C++代码控制网格布局中的项目的文本或显示效果,包含在可闪烁的内容中。当C++代码发出信号时,闪烁的需要很好,但如果用户故意拖动或轻击,则不需要闪烁。以下是dtech为x方向flickable修改的函数:

function ensureVisible(item) {
    if (moving || dragging)
        return;
    var xpos = item.mapToItem(contentItem, 0, 0).x
    var ext = item.width + xpos
    if ( xpos < contentX // begins before
              || xpos > contentX + width // begins after
              || ext < contentX // ends before
              || ext > contentX + width) { // ends after
        // don't exceed bounds
        var destinationX = Math.max(0, Math.min(xpos - width + item.width, contentWidth - width))
        ensureVisAnimation.to = destinationX;
        ensureVisAnimation.from = contentX;
        ensureVisAnimation.start();
    }
}
//This animation is for the ensure-visible feature.
NumberAnimation on contentX {
    id: ensureVisAnimation
    to: 0               //Dummy value - will be set up when this animation is called.
    duration: 300
    easing.type: Easing.OutQuad;
}
功能可修改(项目){
如果(移动| |拖动)
返回;
var xpos=item.mapToItem(contentItem,0,0).x
var ext=item.width+xpos
如果(xposcontentX+width//在
||extcontentX+width){//结束于
//不要越界
var destinationX=Math.max(0,Math.min(xpos-width+item.width,contentWidth-width))
ensureVisAnimation.to=destinationX;
ensureVisAnimation.from=contentX;
确保重新激活。开始();
}
}
//此动画用于“确保可见”功能。
contentX上的数字化{
id:EnsureRevision
to:0//虚拟值-将在调用此动画时设置。
持续时间:300
easing.type:easing.OutQuad;
}

谢谢,这对我来说很有效,但是也需要缓存一些flickable页面,否则默认情况下不会创建缓存外的列表项,我们可能会出错。通过设置来为我解决:
cacheBuffer:(parent.height>0)?parent.height*3:0
-3页缓存。