如何使 TextArea 具有最大尺寸和滚动条?
Posted
技术标签:
【中文标题】如何使 TextArea 具有最大尺寸和滚动条?【英文标题】:How to make a TextArea have a max size and a scroll bar? 【发布时间】:2019-02-04 20:54:27 【问题描述】:我有一个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
之外拥有此代码时,文本会向右下方移动,直到用户选择它:
选择文本后,它看起来像这样(这是我希望它开始的地方):
【问题讨论】:
【参考方案1】:将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
【讨论】:
很好的解决方案,只是一个后续问题:如果我尝试在与包含 ApplicationWindow 的文件不同的文件中使用您的代码,则文本开始移动到矩形之外,直到它被选中。我已经编辑了我的问题以包含我是如何编码的。知道是什么原因造成的吗? 嗯,我认为是填充。设置leftPadding: 0
、rightPadding: 0
等会有所帮助。在我的脑海中,我不确定它为什么会这样……顺便说一下,你可以用它来帮助可视化contentItem
:Component.onCompleted: Qt.createQmlObject("import QtQuick 2.0; Rectangle width: parent.width; height: parent.height; color: '#aaff0000'; ", flickable.contentItem);
(将它添加到@987654340 的正文中@)。
谢谢,将填充设置为零确实有帮助,但如果您想要非零填充,问题仍然存在。我注意到,如果我将Flickable
的width
设置为一个数字,而不是从ApplicationWindow
中获取它(即使用400
而不是parent.width
),这似乎会引发问题。一旦我将Flickable
移到应用程序窗口之外,我就无法访问该字段。很奇怪。
另一个有趣的事情:如果我使用您的代码来可视化问题,似乎填充在 Flickable
和 TextArea
之间单独发生(如果我将左侧的填充设置为10,TextArea
从Flickable
边缘右侧 10 个像素处开始,然后在我开始编辑时重置)【参考方案2】:
啊哈!经过大量搜索,我终于找到了一个方便的属性,名为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
属性修改为您希望文本具有的最大行数。
【讨论】:
以上是关于如何使 TextArea 具有最大尺寸和滚动条?的主要内容,如果未能解决你的问题,请参考以下文章