【问题标题】:Click \ flick through emptry area of a Flickable that partially overlaps another Flickable单击 \ 轻拂与另一个 Flickable 部分重叠的 Flickable 的空白区域
【发布时间】:2017-08-04 09:45:13
【问题描述】:

我在底部有一个可轻弹的场景“编辑器”,停靠在其右侧,顶部有一个可轻弹的场景“大纲”,它显示了场景结构的树。

  Flickable {
    id: editor
    anchors.fill: parent
    contentWidth: 5000
    contentHeight: 5000
    Repeater {
      model: 500
      delegate: Rectangle {
        width: Math.random() * 200 + 50
        height: width
        x: Math.random() * editor.contentWidth
        y: Math.random() * editor.contentHeight
        color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
        border.color: "black"
      }
    }
  }

  Flickable {
    id: outliner
    anchors.right: editor.right
    width: contentWidth
    height: parent.height
    contentWidth: contentItem.childrenRect.width
    contentHeight: contentItem.childrenRect.height
    Column {
      Repeater {
        model: 500
        delegate: Rectangle {
          width: Math.random() * 200 + 50
          x: outliner.contentWidth - width
          height: 50
          color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
          border.color: "black"
        }
      }
    }
  }

当然,我希望能够同时滑动两者来导航,因为它们都比可用的屏幕空间更大。

问题是大纲可轻弹只会阻止编辑器轻弹,即使我从大纲项目不占据的位置轻弹。我不希望这样,我想要的是仅当轻弹发生在大纲项目顶部时才轻弹大纲,否则我想跳到编辑器,所以我可以单击并将其从该区域轻弹到对。

由于Flickable 的工作方式,我无法做到这一点。它会首先检查是否有拖动,只有当点击不超过拖动阈值时,它才会让点击向下到底层元素。所以我想不出只有在那个位置有物体时才轻弹的方法。

有什么方法可以让事件处理做我想做的事吗?

【问题讨论】:

  • 它在这里工作zippy.gfycat.com/FamiliarFavoriteCricket.webm 或者你的意思是它不应该在没有代表的大纲区域轻弹时轻弹?
  • 这就是我的意思。不仅它不应该轻弹,而且底部的轻弹也应该轻弹。

标签: qt qml qtquick2 overlap flickable


【解决方案1】:

您可以通过检查场景中的每台印刷机来做到这一点,如果印刷机下方有一个大纲代表的代表。如果不是,请将outliner 标记为非交互式。当editor有移动时重新启用它。

像这样:

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.0

ApplicationWindow {
    id: app
    visible: true
    width: 600
    height: 480
    Item { // a common parent not containing the MouseArea to be able to call childAt on press
        id: flickablesParent
        anchors.fill: parent
        Flickable {
            id: editor
            anchors.fill: parent
            contentWidth: 5000
            contentHeight: 5000
            onMovementStarted: outliner.interactive = true //re-enable the outliner user interaction so it can be flicked again.
            Repeater {
                model: 500
                delegate: Rectangle {
                    width: Math.random() * 200 + 50
                    height: width
                    x: Math.random() * editor.contentWidth
                    y: Math.random() * editor.contentHeight
                    color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
                    border.color: "black"
                }
            }
        }

        Flickable {
            id: outliner
            anchors.right: editor.right
            width: contentWidth
            height: parent.height
            contentWidth: contentItem.childrenRect.width
            contentHeight: contentItem.childrenRect.height

            Column {
                id: column // set an id so it can be referenced in the MouseArea
                Repeater {
                    model: 500
                    delegate: Rectangle {
                        width: Math.random() * 200 + 50
                        x: outliner.contentWidth - width
                        height: 50
                        color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
                        border.color: "black"
                    }
                }
            }
        }
    }
    MouseArea {
        id: dispatcher
        anchors.fill: parent
        onPressed: {
            var flickable = flickablesParent.childAt(mouse.x, mouse.y); //find out on what flickable we pressed (the check could be ommited but I guess it's more performant with)
            if (flickable === outliner) {
                var mappedPos = mapToItem(column, mouse.x, mouse.y);
                var delegate = column.childAt(mappedPos.x, mappedPos.y);
                if (!delegate)
                    outliner.interactive = false; //if there's no delegate where we pressed in the column, we disable the interactions of the outliner flickable.
            }
            mouse.accepted = false; // let the underlying Flickable deal with this event
        }
    }
}

编辑:您实际上不需要重新启用 onMovementStarted 中的大纲,您也可以在 MouseArea onPressed 中执行此操作。

喜欢

onPressed: {
    var flickable = flickablesParent.childAt(mouse.x, mouse.y); //find out on what flickable we pressed (the check could be ommited but I guess it's more performant with)
    if (flickable === outliner) {
        var mappedPos = mapToItem(column, mouse.x, mouse.y);
        var delegate = column.childAt(mappedPos.x, mappedPos.y);
        outliner.interactive = delegate ? true : false;
    }
    mouse.accepted = false; // let the underlying Flickable deal with this event
}

【讨论】:

  • 不幸的是,在我的生产代码中,大纲不仅仅是一个列,它是一个嵌套树,而且结构很深且任意,因此简单地检查该点是否不是那么容易或非常适用空的,
  • 遗憾的是,除了检查您按下的位置是否存在叶节点之外,我想不出其他解决方案。我也为我的解决方案感到自豪:(
  • 它可以工作......对于示例代码,但不适用于问题指定的内容:)我可能对某些人仍然有用,同时我认为我正在做一些有用的事情。跨度>
  • 我知道了,我希望能进行一次测试,看看是否有任何问题出现在不同的平台上。
【解决方案2】:

好吧,我想我做到了,关键是禁用大纲的交互性,然后通过代理中的 MouseArea 拦截输入,然后仔细计时并测量手动拖动增量,如果足够快,安排一个手动轻弹释放。

让它在按下时停止正在进行的轻弹并随后从下一次拖动中启动另一个轻弹在轻弹刚刚被取消后被证明是有问题的,但是通过将每个轻弹延迟到下一个事件循环周期我让它工作.

我还添加了车轮支撑等。

如果有人在任何平台上遇到问题,请在 cmets 中告诉我。

// the editor code is the same from the OP
  Flickable {
    id: outliner
    anchors.right: editor.right
    width: contentWidth
    height: parent.height
    contentWidth: contentItem.childrenRect.width
    contentHeight: contentItem.childrenRect.height
    interactive: false
    property int ly: 0
    property real lt: 0
    property int dy: 0
    function go(yy) {
      dy = contentY - (contentY -= yy - ly)
      ly = yy
      lt = Date.now()
    }
    Timer { 
      id: trigger
      interval: 1
      onTriggered: outliner.flick(0, outliner.dy * 150)
    }
    Column {
      Repeater {
        model: 500
        delegate: Rectangle {
          width: Math.random() * 200 + 50
          x: outliner.contentWidth - width
          height: 50
          color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
          border.color: "black"
          MouseArea {
            anchors.fill: parent
            Drag.active: drag.active
            drag.target: Item { id: dummy }
            onPressed: {
              dummy.y = 0
              if (outliner.flicking) outliner.cancelFlick()
            }
            onWheel: outliner.flick(0, wheel.angleDelta.y * 10)
            onPositionChanged: {
              if (drag.active) outliner.go(dummy.y)
            }
            onReleased: {
              if (Date.now() - outliner.lt < 50) trigger.start()
              outliner.ly = 0
              outliner.returnToBounds()
            }
          }
        }
      }
    }
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2015-11-30
    • 1970-01-01
    相关资源
    最近更新 更多