在 QML Scrollview 中时,QML MouseArea onWheel 事件无法正常工作

QML MouseArea onWheel event not working properly when inside QML Scrollview

我有一个 MouseArea 里面有一个 Scrollview 里面有一个 Rectangle。我实现了一个缩放功能,当按下 ctrl 并滚动鼠标滚轮时,缩放 in/out。但是,只有当 ScrollView 一直在顶部时才会放大,只有当 ScrollView 一直在底部时才会缩小。有一些额外的逻辑来处理文件的外部拖放。只要 TextEdit 中的文本大到足以得到 ScrollView,问题就应该能够重现。显然这是以前的一个错误,但我无法让它正常工作。我也尝试了下面的解决方案 link:

QtQuick2: Handle onWheel event inside of a ScrollView

Rectangle {
    id: palGenRectangle
    Layout.minimumWidth: 50
    property string display
    //width:800
    color: "white"

    ScrollView {
        id: palGenTextScrollView
        anchors.fill: parent

            MouseArea {
            id: mouseArea
            anchors.fill: parent
            onWheel: {
                if (wheel.modifiers & Qt.ControlModifier){
                    if (wheel.angleDelta.y > 0)
                    {
                        mainTextEdit.font.pixelSize++
                        console.log("+++++")
                    }
                    else
                    {
                        mainTextEdit.font.pixelSize--
                        console.log("-----")
                    }

                }
                else{
                    wheel.accepted=true
                }
            }
        }

        DropArea {
            anchors.fill: parent
            onEntered: {
                palGenRectangle.color = "light blue"
            }
            onExited: {
                palGenRectangle.color = "white"
            }
            onDropped: {
                palGenRectangle.color = "white"
            if (drop.hasText) {
                if (drop.proposedAction == Qt.MoveAction || drop.proposedAction == Qt.CopyAction) {
                    fileio.setPalFileTextFromFile(drop.text)
                    fileio.mainTextEdit = mainTextEdit.textDocument
                    drop.acceptProposedAction()
                }
            }
        }
    }
    Item {
        id: draggable
        anchors.fill: parent
        Drag.active: mouseArea.drag.active
        Drag.hotSpot.x: 0
        Drag.hotSpot.y: 0
        Drag.mimeData: { "text/plain": palGenRectangle.display }
        Drag.dragType: Drag.Automatic
        Drag.onDragStarted: 
        Drag.onDragFinished: {
            if (dropAction == Qt.MoveAction) {
                item.display = ""
            }
        }
    }


    TextEdit {
        id: mainTextEdit
        text: fileio.palFileText
        wrapMode: TextEdit.Wrap
        selectByMouse: true
        onTextChanged: {
            if (fileio.palFileText !== mainTextEdit.text)
                fileio.textIsModified = true
            else
                fileio.textIsModified = false
        }
    }
}

为了使这个答案更清楚,首先将鼠标区域从代码中提取到 ZoomArea 组件:

//ZoomArea.qml
MouseArea {
    onWheel: {
        if (wheel.modifiers & Qt.ControlModifier){
            if (wheel.angleDelta.y > 0)
            {
                mainTextEdit.font.pixelSize++
            }
            else
            {
                mainTextEdit.font.pixelSize--
            }
            wheel.accepted=true
        }
        else{
            wheel.accepted=false
        }
    }
}

请注意,wheel.accepted 与您的代码不同。如果触发缩放,它应该接受滚轮事件。不然缩放的时候也跟着滚动,很奇怪

在您的代码中 ZoomArea 无法正常工作,因为有多个内容项被分配给 ScrollView。在固定bug的示例代码中,只有一个Item。换句话说,您可以使用 Item 包装所有组件并将其添加到 ScrollView:

ScrollView {
    id: palGenTextScrollView

    Item {
        id: mainTextContent
        width: mainTextEdit.paintedWidth
        height: mainTextEdit.paintedHeight

        ZoomArea {
            id: mouseArea
            anchors.fill: parent
        }
        DropArea {}
        Item { id: draggable}
        TextEdit { id: mainTextEdit}
    }
}

当鼠标光标在文本上时它会起作用。但是,如果 TextEdit 中只有一个字符,并且鼠标光标在视图中为空 space,则缩放不起作用。为了让它更好,mainTextContent 应该填写 ScrollView:

ScrollView {
    id: palGenTextScrollView

    property int scrollBarWidth: 15
    anchors.fill: parent

    Item {
        id: mainTextContent
        width: Math.max(
            mainTextEdit.paintedWidth, 
            palGenTextScrollView.width - palGenTextScrollView.scrollBarWidth)
        height:Math.max(
            mainTextEdit.paintedHeight, 
            palGenTextScrollView.height - palGenTextScrollView.scrollBarWidth)

        ZoomArea{}
        //...
    }
}