如何使 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
属性 修改为您的最大行数希望文字有。
将 Flickable
的 height
设置为 contentHeight
或 300
- 以较小者为准:
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 {}
}
}
我有一个 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
属性 修改为您的最大行数希望文字有。
将 Flickable
的 height
设置为 contentHeight
或 300
- 以较小者为准:
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 {}
}
}