当 QML 滚动条位于底部并且窗口高度被调整大小时,它不会更新

Posted

技术标签:

【中文标题】当 QML 滚动条位于底部并且窗口高度被调整大小时,它不会更新【英文标题】:QML Scroll Bar doesn't update when it is at the bottom and window height is resized 【发布时间】:2021-03-11 02:28:42 【问题描述】:

我有一个正在处理的自定义滚动条 QML 类型。我遇到的问题是,如果滚动条一直位于页面底部并且主应用程序窗口的高度增加,则翻译后的内容会保持原位并且滚动条的大小不会更新。发生此窗口大小调整后,单击滚动条会导致内容对齐到正确的位置,并且滚动条会对齐到正确的大小。可以对下面的代码进行哪些更改,以便在窗口高度发生变化时更新内容(红色块)的位置和滚动条大小?之后再次单击滚动条时不会。看问题只要打开下面的代码,将蓝色滚动条一直滚动到底部,增加主窗口的高度(观察滚动条大小和内容位置),然后点击滚动条后面的调整大小。这是我的代码:

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import QtQuick.Shapes 1.15


Window 
    id: main_window
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    color: 'light blue'

    // container
    ColumnLayout 
        id: my_column
        anchors.centerIn: parent
        width: main_window.width / 3
        height: main_window.height / 3
        spacing: 0

        // contents
        ColumnLayout 
            id: repeater_element
            Layout.fillWidth: true
            Layout.fillHeight: false
            spacing: 4
            Repeater 
                model: 7
                Rectangle 
                    Layout.fillWidth: true
                    Layout.fillHeight: false
                    Layout.preferredHeight: 75
                    Layout.alignment: Qt.AlignTop
                    color: 'red'
                
            
            transform: Translate 
                id: rect_translate
                y: 0
            
        
    

    // scroll bar type
    Scroll_Bar 
        x: 0
        y: 0
        height: parent.height
        width: 20
        container_element: my_column
        content_element: repeater_element
        translate_element: rect_translate
        orientation: Qt.Vertical
    

    // just a border for the container element
    Shape 
        ShapePath 
            strokeWidth: 4
            strokeColor: "black"
            fillColor: Qt.rgba(.09, .05, .86, 0)
            joinStyle: ShapePath.MiterJoin
            startX: my_column.x
            startY: my_column.y

            PathLine 
                relativeX: my_column.width
                relativeY: 0
            

            PathLine 
                relativeX: 0
                relativeY: my_column.height
            

            PathLine 
                relativeX: -my_column.width
                relativeY: 0
            

            PathLine 
                relativeX: 0
                relativeY: -my_column.height
            
        
    

Scroll_Bar.qml

import QtQuick 2.0
import QtQuick.Controls 2.5

ScrollBar 
    property var container_element
    property var content_element
    property var translate_element

    QtObject 
        id: internal
        property real vertical_size: container_element.height / content_element.height
        property real horizontal_size: container_element.width / content_element.width
        property real off_the_bottom: (content_element.height - container_element.height) + translate_element.y
    

    id: scroll_bar_element
    hoverEnabled: true
    active: size
    orientation: orientation
    size: orientation === Qt.Vertical ? internal.vertical_size : internal.horizontal_size
    padding: 0
    contentItem: Rectangle 
        id: ci
        radius: 0
        color: 'blue'
    

    onSizeChanged: 
        if(size > 1)
            visible = false
        
        else
            visible = true
        
    

    onPositionChanged: 
        if (orientation === Qt.Horizontal) 
            translate_element.x = -scroll_bar_element.position * content_element.width
         else 
            translate_element.y = -scroll_bar_element.position * content_element.height
        
    

    Component.onCompleted: 
        scroll_bar_element.onPositionChanged()
    

【问题讨论】:

【参考方案1】:

您几乎无法编写比现有滚动条更好的滚动条,因此我编写了以下代码,它与您在示例中看到的相同。 ScrollBar 可以是 flickable 的兄弟,因此它不会获得所有权,您可以将其放置在您想要的位置。你甚至可以让它旋转。

它可以解决您的问题吗?

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12

Window 
    id: main_window
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    color: 'light blue'

    Flickable 
        id: flickable
        anchors.centerIn: parent
        width: main_window.width / 3
        height: main_window.height / 3

        contentWidth: repeater_element.width
        contentHeight: repeater_element.height

        ScrollBar.vertical: scrollBar

        // container
        ColumnLayout 
            id: my_column
            width: main_window.width / 3
            height: main_window.height / 3
            spacing: 0

            // contents
            ColumnLayout 
                id: repeater_element
                Layout.fillWidth: true
                Layout.fillHeight: false
                spacing: 4
                Repeater 
                    model: 7
                    Rectangle 
                        Layout.fillWidth: true
                        Layout.fillHeight: false
                        Layout.preferredHeight: 75
                        Layout.alignment: Qt.AlignTop
                        color: 'red'
                    
                
                transform: Translate 
                    id: rect_translate
                    y: 0
                
            
        
    

    ScrollBar 
        id: scrollBar
        anchors.left: parent.left
        anchors.top: parent.top
        anchors.bottom: parent.bottom

        //try this for fun
        //rotation: 5

        contentItem: Rectangle 
            implicitWidth: 20
            implicitHeight: 20
            color: "blue"
        
    

    Rectangle 
        color: "transparent"
        border.width: 4
        anchors.fill: flickable
    


【讨论】:

以上是关于当 QML 滚动条位于底部并且窗口高度被调整大小时,它不会更新的主要内容,如果未能解决你的问题,请参考以下文章

用浏览器窗口调整两个div底部div到高度[复制]

阻止 ListBox 使用内容而不是窗口来调整大小

将 ScrollView 高度调整为屏幕高度?

js如何监听屏幕滚动到底了

javascript element-ui@1.x版本的动态调整表底部滚动条位置,引用在表格行数超过屏幕高度,并且列较多的情况

jQuery检测滚动条(scroll)是否到达底部