【问题标题】:QML TextArea: different behavior when using QtQuick.Controls > 2.0 vs 1.4QML TextArea:使用 QtQuick.Controls > 2.0 与 1.4 时的不同行为
【发布时间】:2019-10-07 10:04:58
【问题描述】:

我是 Qml 的新手,但我想试一试,看看是否值得用它来代替旧的 Qt 小部件,尤其是因为我听说它更适合移动设备。我将 Qml 用于 GUI 以及几个 C++ 类用于核心逻辑。 我需要一个可滚动的 TextArea,就像在文本编辑器中一样,所以我发现我必须使用嵌套在 ScrollView 中的 TextArea,如下所示:

ScrollView {
    ...
    TextArea {
        ...
    }
}

我喜欢我的深色 QML 应用程序中的结果,它有一个漂亮的文本编辑器和在我的深色背景上漂亮的滚动条。

当我需要在我的代码中实现 scrollTo 函数时,问题出现了。我的应用程序是一种播放器,它突出显示文本并在达到 1/4 高度时向下滚动。我发现我可以使用 flickableItem.contentY 属性来调整 ScrollView 中文本的相对位置,但是即使其他答案提到了该属性,该属性也不存在。

我找到了 Qt 文档,但没有任何迹象,只有一个 contentItem 属性。所以我尝试调整 contentItem.y 属性,但结果很糟糕。文本和整个背景都在平移,覆盖了我的顶部工具栏。

所以我在文档中搜索了 TextArea 的其他实现,发现 QtQuick.Controls 1.4 有一个继承 ScrollView 类的 TextArea 实现。这就是解决方案,我想。我切换到较旧的实现并设法使整个工作正常进行。现在我可以通过 flickableItem.contentY 属性和 contentHeight vs height 属性以编程方式滚动我的 TextArea 来计算我有多少空间。

这里的问题是 1.4 版本的滚动条看起来很难看,我觉得使用旧版本有点 hack。他们是否有理由从 ScrollView 中删除 flickableItem 属性?是否有其他方法可以对新的 Controls 版本做同样的事情?

这是我的代码:

import QtQuick 2.12
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.12

TextArea {
    id: textArea

    anchors.fill: parent
    backgroundVisible: false

    /*background: Rectangle {
        anchors.fill: parent
        color: "#000000"
    }*/

    //color: "#ffffff"

    textColor: "#ffffff"
    selectByKeyboard: true
    selectByMouse: true
    verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn

    function scrollToY(y) {
        if ((contentHeight-y) > flickableItem.height && y > flickableItem.height/4) {
            flickableItem.contentY = y - flickableItem.height/4
        }
    }
}

【问题讨论】:

  • 简单来说,你想要一个可滚动的 textArea?

标签: qt qml qtquick2


【解决方案1】:

我不知道 Qt Quick Controls 1 和 Qt Quick Controls 2 之间实现更改背后的原因。但是,Qt Quick Controls 2 中的 ScrollView 可以通过编程方式滚动到 ScrollBar.vertical.position。我编写了一个示例代码,它使用计时器移动内容,直到它向下滚动,当计时器停止时。请注意,如果内容适合可见区域,则禁用滚动条并且不会启动计时器,因为不需要移动内容。您可以通过将布尔值 useLongText 更改为 false 来测试它。

import QtQuick.Window 2.2
import QtQuick 2.9
import QtQuick.Controls 2.2

Window {
    visible: true
    width: 400
    height: 400
    color: "blue"
    property string exampleTextShort: "Lorem Ipsum is simply dummy text of the printing and typesetting industry."

    property string exampleTextLong: "Lorem Ipsum is simply dummy text of the printing and typesetting industry.

Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.

It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
"

    property bool useLongText: true // Change this to test with short text too

    Timer {
        id: timer
        running: scrollView.wholeTextSeen ? false : true
        repeat: true
        interval: 2000
        onTriggered: {
            scrollView.scrollDown()
        }
    }

    Rectangle{
        id: rect
        anchors.centerIn: parent
        width: parent.width*0.2;
        height: parent.height*0.2;
        ScrollView {
            id: scrollView
            anchors.fill: parent
            clip: true
            property bool wholeTextSeen: ScrollBar.vertical.size >= 1 ? true : false
            ScrollBar.vertical.policy: ScrollBar.vertical.size >= 1 ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
            TextArea {
                readOnly: true
                text: useLongText ? exampleTextLong : exampleTextShort
                wrapMode: Text.WordWrap
            }

            function scrollDown() {
                if (wholeTextSeen) {
                    timer.running = false
                } else {
                    var scrollVar = ScrollBar.vertical.position + ScrollBar.vertical.size
                    console.log("scrollVar:",scrollVar)
                    if (scrollVar >= 1) {
                        wholeTextSeen = true
                    } else {
                        var step = 0.2
                        step = scrollVar + step > 1 ? 1 - scrollVar : step
                        ScrollBar.vertical.position = ScrollBar.vertical.position + step
                    }
                }
            }
        }
    }
}

运行长文本时的示例输出对我来说如下所示:

qml: scrollVar: 0.15625
qml: scrollVar: 0.35625
qml: scrollVar: 0.55625
qml: scrollVar: 0.7562500000000001
qml: scrollVar: 0.95625
qml: scrollVar: 1

【讨论】:

  • 非常感谢。 ScrollBar.vertical.position 正是我要寻找的。在您的 sn-p 中,您以任意速率滚动文本,而我需要向下滚动 1 个确切文本行的数量,并且仅当它 > 可见 textArea 高度的 1/4 时。不过,这应该很容易发现。只是出于好奇,关键字ScrollBar,它是一个类型名称,不是声明一个新的孩子吗?它不应该是一个属性名称,例如scrollBar吗?
  • ScrollBar.vertical 在 ScrollView 中被称为附加属性。您可以从Qt documentation 阅读有关附加属性的更多信息。因此,您需要设置该附加属性的位置属性,以便以编程方式使内容沿垂直方向移动。
  • 再次感谢您。您可能注意到我对 Qml 语言还很陌生,但我学得很快,而且我已经设法用它创建了一个不错的应用程序。我仍然更喜欢用 C++ 编写核心内容,因为我有点老派,但我欣赏 QtQuick 的良好 UI 功能,Qml 减少了工作量。
猜你喜欢
  • 1970-01-01
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 1970-01-01
  • 2013-08-18
相关资源
最近更新 更多