I am writing an app for which the client has provided a custom font. The font comes as four separate otf
files, one for regular, bold, italic and bold-italic. If I want to use only one of these four fonts in my class, I create the FontLoader
like so:
FontLoader { id: clientFontRegular; source: "qrc:/client/fonts/Font-Regular.otf" }
and then I can use it for any control on my page like so:
font.family: clientFontRegular.name
My problem is that I have multiple controls on my page, and I want to use regular for some, bold for some, italics for some others etc. To do this I've added FontLoader
objects for the other fonts as well, like so:
FontLoader { id: clientFontBold; source: "qrc:/client/fonts/Font-Bold.otf" }
FontLoader { id: clientFontItalic; source: "qrc:/client/fonts/Font-Italic.otf" }
FontLoader { id: clientFontBoldItalic; source: "qrc:/client/fonts/Font-BoldItalic.otf" }
But this does not work correctly. All four ids (clientFontRegular, clientFontBold, clientFontItalic and clientFontBoldItalic) can be used anywhere in the page (i.e. without crashing or ending up using the system font), but the font used no matter what is the bold font.
I know that all four of my otf
files are valid, because if I comment out all but the FontLoader for one file and use only that one, the custom font is rendered correctly. There just seems to be a problem with attempting to define multiple FontLoaders in one class (none of the FontLoader samples I've seen online use more than a single custom font).
Anybody know how to do this?
I also struggled around with the same issue and wondered why there is nothing about it in the docs. This is how I got it working:
First, I defined a custom Text
element (for example Label.qml), where a FontLoader
element is used for every single font style, like this:
import QtQuick 2.5
Text {
FontLoader { id: loader; source: "fonts/Blogger_Sans.otf"; }
FontLoader { source: "fonts/Blogger_Sans-Italic.otf"; }
FontLoader { source: "fonts/Blogger_Sans-Light.otf"; }
FontLoader { source: "fonts/Blogger_Sans-Medium.otf"; }
FontLoader { source: "fonts/Blogger_Sans-Bold.otf"; }
FontLoader { source: "fonts/Blogger_Sans-Light_Italic.otf"; }
FontLoader { source: "fonts/Blogger_Sans-Medium_Italic.otf"; }
FontLoader { source: "fonts/Blogger_Sans-Bold_Italic.otf"; }
font.family: loader.name;
}
The "trick" is to not dynamically reassign the Text
element's font.family
property. And this is already enough to control the font style:
Column {
anchors.centerIn: parent;
MyLib.Label {
text: "Blogger_Sans"
}
MyLib.Label {
text: "Blogger_Sans-Italic"
font.italic: true;
}
MyLib.Label {
text: "Blogger_Sans-Light"
font.weight: Font.Light;
}
MyLib.Label {
text: "Blogger_Sans-Medium"
font.weight: Font.Medium;
}
MyLib.Label {
text: "Blogger_Sans-Bold"
font.weight: Font.Bold;
}
MyLib.Label {
text: "Blogger_Sans-Light_Italic"
font.weight: Font.Light;
font.italic: true;
}
MyLib.Label {
text: "Blogger_Sans-Medium_Italic"
font.weight: Font.Medium;
font.italic: true;
}
MyLib.Label {
text: "Blogger_Sans-Bold_Italic"
font.weight: Font.Bold;
font.italic: true;
}
}
I am just assuming, but it looks like once fonts are loaded (like in this case by anonymous FontLoader
s), they are memorized and become automatically available when specifying them using the available font properties. But it's just guessing.
As pointed out in the comments by peppe, it's also possible to load custom fonts directly in C++ using QFontDatabase::addApplicationFont:
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans.otf");
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans-Bold_Italic.otf");
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans-Medium_Italic.otf");
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans-Light_Italic.otf");
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans-Italic.otf");
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans-Bold.otf");
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans-Medium.otf");
QFontDatabase::addApplicationFont(resDir + "fonts/Blogger_Sans-Light.otf");
Now the font and related styles are available in QML:
Text {
font.family: "Blogger Sans" // note the use of the font family name
text: "MyText"
font.bold: true
font.italic: true
}
The C++ approach just seems cleaner and also allows you to specify fonts without using file paths which is another big advantage.
I just spent the better part of an hour trial-and-erroring this. Actually, while qCring's answer works, it's actually much simpler. With
FontLoader { id: clientFontBold; source: "qrc:/client/fonts/Font-Bold.otf" }
FontLoader { id: clientFontItalic; source: "qrc:/client/fonts/Font-Italic.otf" }
FontLoader { id: clientFontBoldItalic; source: "qrc:/client/fonts/Font-BoldItalic.otf" }
all FontLoaders end up with the same default name, therefore clientFontBold.name == clientFontItalic.name == clientFontBoldItalic.name
and apparently Qt decides that the font that was registered last is mapped. You can easily see this by changing the order so clientFontItalic
will be last. Then all your text that uses clientFontBold.name
will be italics.
The solution is to of course name them:
FontLoader { id: clientFontBold; name: "MyFontBold"; source: "qrc:/client/fonts/Font-Bold.otf" }
FontLoader { id: clientFontItalic; name: "MyFontItalic"; source: "qrc:/client/fonts/Font-Italic.otf" }
FontLoader { id: clientFontBoldItalic; name: "MyFontBoldItalic"; source: "qrc:/client/fonts/Font-BoldItalic.otf" }
Now clientFontBold.name != clientFontItalic.name != clientFontBoldItalic.name
and the proper font will load. I don't know why the fact that unnamed fonts end up with the same name isn't documented anywhere in the examples.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With