如何使 TextArea 具有最大尺寸和滚动条?

How to make a TextArea have a max size and a scroll bar?

我有一个 TextArea,通常只包含大约一行文本。但是,我确实希望用户能够添加更多内容,并将 TextArea 扩展到最多约 15 行,此时可以通过滚动条访问任何其他文本。通过将 TextArea 包含在 Flickable 中(最终包含在 Rectangle 中),我已经能够使滚动方面正常工作。

Rectangle {
    id: rec
    width: 200
    height: 25

    Flickable {
        id: flickable
        anchors.fill: parent
        contentWidth: textArea.width
        contentHeight: textArea.height

        TextArea.flickable:
            TextArea {
            id: textArea
            text: qsTr("Hello, world!")
            wrapMode: Text.WordWrap
        }
        ScrollBar.vertical: ScrollBar { }
    }
}

此时,我该如何让文本框随着文本扩展到某个预定义的最大像素数(比如 300)?

编辑

好的,几乎完成了,只是在使用 Mitch 的解决方案使文本正确居中时遇到了一个问题。我的 main.qml 文件包含以下内容:

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    HelloWorld{
        anchors.centerIn: parent
    }
}

我的任何 HelloWorld.qml 文件包含以下内容:

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import QtQuick.Controls.Styles 1.4

ColumnLayout{

    width: 250

    FontMetrics {
        id: fontMetrics
        font: textArea.font
    }

    Flickable {
        id: flickable
        width: parent.width
        height: Math.min(contentHeight, fontMetrics.height * 15)
        contentWidth: width
        contentHeight: textArea.implicitHeight
        clip: true

        TextArea.flickable: TextArea {
            id: textArea
            text: "Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! "
                + "Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! "
            wrapMode: Text.WordWrap
            //padding: 0

            background: Rectangle {
                border.color: "blue"
            }
        }
        ScrollBar.vertical: ScrollBar {}
    }

}

这非常接近工作,但出于某种原因,当我在 main.qml 之外使用此代码时,文本会向右下方移动,直到用户选择它:

选择文本后,它看起来像这样(这是我希望它开始的地方):

啊哈!经过大量搜索,我终于找到了一个方便的 属性,名为 paintedHeight,它是 TextArea 的一部分。这将得到你 TextArea 中文本的高度,所以我用它来发现每行的大小是 13 并且只要编辑文本就更新基数 Rectangle 的高度,并且简单地用 if 语句来限制它。这是我古怪的解决方案:

Rectangle {
    property int paintedHeight: 13
    id: rec
    width: 200
    height: paintedHeight * 2

    Flickable {
        id: flickable
        anchors.fill: parent
        contentWidth: textArea.width
        contentHeight: textArea.height

        TextArea.flickable:
            TextArea {
            id: textArea
            wrapMode: Text.WordWrap

            property int maxNumberOfLines: 15
            onTextChanged: {
                rec.height = (lineCount * rec.paintedHeight) + rec.paintedHeight

                // cap the height so that the box stops expanding at maxNumberOfLines
                if(rec.height > rec.paintedHeight * (maxNumberOfLines + 1)){
                    rec.height = rec.paintedHeight * (maxNumberOfLines + 1)
                }
            }
        }
        ScrollBar.vertical: ScrollBar { }
    }
}

如果其他人发现自己处于类似情况,只需执行 console.log(paintedHeight) 来获取当前文本的高度(如果有多行,则相应地划分)来获取文本的高度,因为它可能与我的不同,具体取决于您使用的样式和字体(我使用的是 Fusion 样式)。然后只需修改 Rectangle 中的 paintedHeight 属性 为您的大小,将 TextArea 中的 maxNumberOfLines 属性 修改为您的最大行数希望文字有。

Flickableheight 设置为 contentHeight300 - 以较小者为准:

import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow {
    width: 400
    height: 400
    color: "#444"
    visible: true

    Rectangle {
        anchors.fill: flickable
    }

    Flickable {
        id: flickable
        width: parent.width
        height: Math.min(contentHeight, 300)
        contentWidth: width
        contentHeight: textArea.implicitHeight

        TextArea.flickable: TextArea {
            id: textArea
            text: qsTr("Hello, world! Hello, world! Hello, world! Hello, world! ")
            wrapMode: Text.WordWrap
        }
        ScrollBar.vertical: ScrollBar {}
    }
}

如果你不希望 Rectangle 在原处(Flickable 的兄弟),你可以删除它,添加

clip: true

Flickable

background: Rectangle {}

TextArea.

还有,如果你想更精确一点,可以用FontMetrics来计算行高:

import QtQuick 2.12
import QtQuick.Controls 2.12

ApplicationWindow {
    width: 400
    height: 400
    color: "#444"
    visible: true

    FontMetrics {
        id: fontMetrics
        font: textArea.font
    }

    Flickable {
        id: flickable
        width: parent.width
        height: Math.min(contentHeight, fontMetrics.height * 15)
        contentWidth: width
        contentHeight: textArea.implicitHeight
        clip: true

        TextArea.flickable: TextArea {
            id: textArea
            text: "Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! "
                + "Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! "
            wrapMode: Text.WordWrap
            padding: 0

            background: Rectangle {}
        }
        ScrollBar.vertical: ScrollBar {}
    }
}