为Qt QML中的许多Text元素指定字体

Specifying font for many Text-elements in Qt QML

本文关键字:元素 字体 Text 许多 Qt QML      更新时间:2023-10-16

我有一个通过QML文件指定的小部件。此小部件包含一个顶级Rectangle,其中包含两个Columns。这些Columns中的每一个都包含许多Text-元素。这个QML小部件被封装在C++中QDeclarativeView的一个子类中。

我想为这些Text-元素中的每一个指定字体。今天,我通过指定顶级属性来做到这一点:

property string fontfamily: "Arial"
property bool fontbold: false
property bool fontitalic: false
property int fontpixelsize: 11
property string fontcolor: "White"

并将每个Text-元素绑定到这些属性:

Text
{   
    color: fontcolor
    font.family: fontfamily
    font.bold: fontbold
    font.italic: fontitalic
    font.pixelSize: fontpixelsize
    ...
}

这不是很优雅,每次我需要支持新的东西(例如下划线字体)时都需要添加新的字段。我无法声明font类型的属性并绑定到该属性(小部件为空,qmlviewer警告"属性后的预期类型")。

有没有更好的方法为所有Text-元素指定字体?

注意!我正在手写QML文件。

在Qt 5.6中(至少,可能更早),您可以使用Qt.font()动态分配字体对象并在其他地方引用它。所以,这是有效的:

property font myFont: Qt.font({
    family: fontfamily,
    bold: fontbold,
    italic: fontitalic,
    pixelSize: fontpixelsize
});
Text
{   
    color: fontcolor
    font: parent.myFont
}

关于Qt.font()的更多信息,请点击此处:https://doc.qt.io/qt-5/qml-qtqml-qt.html#font-方法

另一种可能性是编写一个新的QML组件,该组件从Text继承并默认设置一些属性:

样式文本.qml

import QtQuick 1.0
Text {
    // set default values
    color: "blue"
    font.family: "Arial"
    font.bold: true
    font.italic: true
    font.pixelSize: 12
}

main.qml

import QtQuick 1.0
Rectangle {
    Row {
        spacing: 10
        Column {
            StyledText {
                text: "Foo1"
            }
            StyledText {
                text: "Bar1"
            }
            StyledText {
                text: "Baz1"
            }
        }
        Column {
            StyledText {
                text: "Foo2"
            }
            StyledText {
                text: "Bar2"
            }
            StyledText {
                text: "Baz2"
            }
        }
    }
}

一个可能的解决方案是编写一个函数,该函数在传递的元素(例如Column)的children上迭代。在该功能中,可以设置所有属性:

import QtQuick 1.0
    Rectangle {
    Row {
        spacing: 10
        Column {
            id: col1
            Text {
                property bool useStyle: true
                text: "Foo1"
            }
            Text {
                property bool useStyle: true
                text: "Bar1"
            }
            Text {
                property bool useStyle: true
                text: "Baz1"
            }
        }
        Column {
            id: col2
            Text {
                property bool useStyle: true
                text: "Foo2"
            }
            Text {
                text: "not styled"
            }
            Text {
                property bool useStyle: true
                text: "Baz2"
            }
        }
    }
    function setTextStyle(parentElement) {
        for (var i = 0; i < parentElement.children.length; ++i) {
            console.log("t", typeof parentElement.children[i]);
            if (parentElement.children[i].useStyle) {  // apply style?
                parentElement.children[i].color = "blue";
                parentElement.children[i].font.family = "Arial"
                parentElement.children[i].font.bold = true;
                parentElement.children[i].font.italic = true;
                parentElement.children[i].font.pixelSize = 12;
            }
        }
    }
    // set style
    Component.onCompleted: {
        setTextStyle(col1);
        setTextStyle(col2);
    }
}

每个包含属性useStyle(设置为true)的元素都将被设置样式。这比手动指定样式要短,但您仍然可以定义哪些元素应该设置样式或不设置样式。

Necro发布,但我觉得它仍然缺少最新的解决方案。CCD_ 17将在不使用CCD_。您可以在父项或Singleton类型中声明它,然后可以将属性绑定到它。

这里有一个的例子

Item {
  id: root
    
  FontMetrics {
    id: fontMetrics
    font.family: "Arial"
    font.pixelSize: 24
  }
    
  property alias font: fontMetrics.font
    
  Text { font: root.font }
  Text { font: root.font }
}

这里有一些有用的解决方案,但我一直无法定义一些基本字体,同时仍能在稍后指定多个字体的详细信息。特别是,因为:

  1. CCD_ 20为同一族的每个字体设置相同的CCD_。参考
  2. 如果使用Qt.font()(或FontMetrics),则对于font属性而言,这是全有或全无
  3. 定义新的Text组件需要每个字体一个文件。更新:自5月15日起可能不是真的
  4. 触发function很难在整个应用程序中进行有效管理

我认为还有一个解决方案的空间:

在我的main.qml中,我为每个字体文件使用了一个FontLoader,但只在族发生变化时才麻烦设置id

FontLoader { source: "qrc:/fonts/ITCAvantGardeStd-Bk.otf";     id: flAvantGarde;   }
FontLoader { source: "qrc:/fonts/ITCAvantGardeStd-BkObl.otf";                      }
FontLoader { source: "qrc:/fonts/ITCAvantGardeStd-BoldCn.otf";                     }
FontLoader { source: "qrc:/fonts/ITCAvantGardeStd-Md.otf";                         }
FontLoader { source: "qrc:/fonts/ADAM.CG PRO.otf";             id: flAdam;         }

然后,这里是重要的部分,每个基本字体定义一个property var,如下所示:

property var fontAgBk:      { "family": flAvantGarde.name, "styleName": "Book" }
property var fontAgBkObl:   { "family": flAvantGarde.name, "styleName": "Book Oblique" }
property var fontAgBoldCn:  { "family": flAvantGarde.name, "styleName": "Bold Condensed" }
property var fontAgMd:      { "family": flAvantGarde.name, "styleName": "Medium" }
property var fontAdam:      { "family": flAdam.name }

var是能够指定一个字典的关键,该字典可以定义一次,但稍后会拆开。

在任何qml的其他地方,我可以做一些类似的事情:

Text {
    id: myText
    color: "#123456"
    font.family: fontBoldCn.family
    font.styleName: fontBoldCn.styleName
    font.pixelSize: 24
    font.letterSpacing: 5
}

仍然需要一些重复的代码,但至少魔术串只定义了一次。