87 lines
2.9 KiB
QML
87 lines
2.9 KiB
QML
|
|
// =============================================
|
|||
|
|
// =============== 单个文本块组件 ===============
|
|||
|
|
// =============================================
|
|||
|
|
|
|||
|
|
import QtQuick 2.15
|
|||
|
|
import QtQuick.Controls 2.15
|
|||
|
|
import ".."
|
|||
|
|
|
|||
|
|
Item {
|
|||
|
|
id: tRoot
|
|||
|
|
property string text: ""
|
|||
|
|
|
|||
|
|
// 颜色固定,不受主题影响
|
|||
|
|
property color bgColor: "#99000000"
|
|||
|
|
property color textColor: "#FFFFFF"
|
|||
|
|
|
|||
|
|
// 外部接口,重设字体和组件大小
|
|||
|
|
property var resetSize: textEdit.resetFontSize
|
|||
|
|
property alias textEdit: textEdit // 文本组件
|
|||
|
|
property string end: "" // 结尾间隔符
|
|||
|
|
|
|||
|
|
// 传入一个相对于item的坐标,返回该坐标的文本序号。
|
|||
|
|
function where(item, mx, my) {
|
|||
|
|
const textPoint = textEdit.mapFromItem(item, mx, my)
|
|||
|
|
const textPos = textEdit.positionAt(textPoint.x, textPoint.y)
|
|||
|
|
return textPos
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 背景
|
|||
|
|
Rectangle {
|
|||
|
|
id: bgRect
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: bgColor
|
|||
|
|
}
|
|||
|
|
// 结尾标识
|
|||
|
|
Icon_ {
|
|||
|
|
icon: "line_feed"
|
|||
|
|
visible: end == "\n" // 标记换行符
|
|||
|
|
anchors.left: parent.right
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
anchors.leftMargin: 1
|
|||
|
|
height: Math.min(tRoot.height * 0.8 ,tRoot.width * 0.8 , size_.line * 2)
|
|||
|
|
width: height
|
|||
|
|
color: theme.subTextColor
|
|||
|
|
}
|
|||
|
|
// 文本
|
|||
|
|
TextEdit_ {
|
|||
|
|
id: textEdit
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: textColor
|
|||
|
|
readOnly: true // 只读
|
|||
|
|
selectByMouse: false // 禁止选择文本
|
|||
|
|
selectByKeyboard: false
|
|||
|
|
persistentSelection: true // 丢失焦点时,保留选区
|
|||
|
|
font.pixelSize: 10 // 初始:10像素
|
|||
|
|
|
|||
|
|
// 重设字体大小,以适合组件大小
|
|||
|
|
function resetFontSize() {
|
|||
|
|
text = tRoot.text
|
|||
|
|
// 初次调整,利用初始文字面积与容器面积的比值,计算字体大小
|
|||
|
|
let s = 1
|
|||
|
|
if(contentWidth>0 && contentHeight>0)
|
|||
|
|
s = (width * height) / (contentWidth * contentHeight)
|
|||
|
|
let ps = font.pixelSize * Math.sqrt(s)
|
|||
|
|
font.pixelSize = ps
|
|||
|
|
// 二次调整:如果文本比容器高出至少半行,则减小字体大小,直到不高于容器
|
|||
|
|
if(contentHeight >= height+(ps*0.5)) {
|
|||
|
|
// 为了保持性能,限定调整的最大次数
|
|||
|
|
for(let i=0; i<10 && contentHeight > height; i++) {
|
|||
|
|
font.pixelSize--
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 二次调整:如果当前只有一行,则优化字间距
|
|||
|
|
if(lineCount === 1 && text.length > 0) {
|
|||
|
|
const s = (tRoot.width - contentWidth) / text.length
|
|||
|
|
if(s > 0) {
|
|||
|
|
font.letterSpacing = s
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 优化整体宽高
|
|||
|
|
if(contentWidth > tRoot.width)
|
|||
|
|
tRoot.width = contentWidth
|
|||
|
|
if(contentHeight > tRoot.height)
|
|||
|
|
tRoot.height = contentHeight
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|