(I'm using Qt 5, QtQuick 2, with Controls.)
I'm writing my first QML application and would like to maintain modularity and relatively small file lengths.
There are certain things that come in big batches that I would like to tuck away into helper files, but I'm not sure of the right way to do this.
The two examples I've run into so far have been FontLoader
and Action
.
In my particular situation, I'll be using 6 fonts in my whole application, so I would like to load them all early on, and not have to worry about it again. My question is, where should I put the FontLoader
s?
One option is to just put them in main.qml
somewhere, but that feels a bit cluttered to me. What I've done is created a file FontLoaders.qml
, which contains:
Item {
width: 0; height: 0
FontLoader {
name: "myFont1"
source: "/fonts/myFont1.ttf"
}
FontLoader {
name: "myFont2"
source: "/fonts/myFont2.ttf"
}
// ...
}
Then, in main.qml
somewhere, I just have a FontLoaders {}
.
The other example I have is Action
. I have a big batch of Action
s that I'd like to be visible more-or-less application-wide. I have a AppMenuBar
component, and this seems like a natural place to put the Action
s, but that basically doubles the size of the QML file defining the menu bar, and logically speaking the two could be split out. (Many of the actions are accessible both through the menu bar and through other buttons in the application.)
The "solutions" I have basically work, but they feel sloppy to me (especially FontLoaders
), and I'm wondering if there is some cleaner way to do this that I haven't figured out yet.
I have similar issues. I did have a look at some of the sources of Qt and figured you can do this:
pragma Singleton
import QtQuick 2.0
QtObject {
property FontLoader fontLatoBlackLoader: FontLoader {
name: "fontLatoBlack"
source: "qrc:/fonts/Lato-Black.ttf"
}
}
In your say fonts.qml file and then in the application you just do:
Label {
text: "Sample tesxt"
font.family: Fonts.fontLatoBlackLoader.name
}
You don't have to instantiate the Fonts object. It just exists globally.
Hope that helps. I have spent a few hours to figure this out myself as I had the same sloppiness/ugliness issues :)
I'd like to be visible more-or-less application-wide
There are several ways you can go about:
1 - QML has dynamic scoping, which means if you declare some property in the root component, it will be accessible everywhere, as long as it is not shadowed by an identically named local property, you could have a property var something : someObject
and use it anywhere. It doesn't even need to be a property, if you set an id FontLoaders { id: fontLoaders }
you can use fontLoaders
everywhere.
2 - you can use a shared library and use a var
in there and include the library everywhere you need that object available:
// Test.js
.pragma library
var obj
// in qml
import "Test.js" as Shared
Shared.obj = someObject
3 - you can find the object in C++ once the main QML is instantiated and register it as a context property, making it globally available in QML
4 - you can use a C++ class to create a wrapper to server as an accessor to shared data
3 and 4 are explained with code snippets in this answer, although this is more useful for C++ objects you use in QML, frankly, the dynamic scoping in QML is the easiest way to go.
As of where exactly to put them - wherever it makes most sense. If you need those application-wide, the main component seems the obvious choice, and if you don't want to clutter it too much, declare those in separate qml files and just instantiate in the main as you've done with the font loaders.
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