I am trying to setup something very simple but the QML is not resolving my module. Why?
I just following the tutorial below, but it does not use cmake, not sure if this is cmake issue or code.
https://www.youtube.com/watch?v=yTH5e6atHoE
I created a "Colors" subdirectory on my folder structure with a qmldir and "CustomColors_01.qml"
here is my cmake file list:
qt_add_qml_module(appDlgDemo
URI DlgDemo
VERSION 1.0
QML_FILES main.qml
QML_FILES Colors/CustomColors_01.qml
QML_FILES Colors/qmldir
)
My folder structure:
-
│ .gitignore
│ CMakeLists.txt
│ main.cpp
│ main.qml
│
└───Colors
CustomColors_01.qml
qmldir
the qmldir
module Colors
singleton CustomColors 1.0 CustomColors_01.qml
the Colors/CustomColors_01.qml
pragma Singleton
import QtQuick
QtObject{
readonly property string background: "#f6f9f8"
}
the main.qml and it won't resolve "import Colors 1.0", only if I import directly, but this is not what I need.
Related
I have a simple test project at https://github.com/jh3010-qt-questions/font_test
When I build it, I get the error:
qrc:/main.qml:5 module "Fonts" is not installed
My directory structure looks like:
font_test
├── assets
│ └── Fonts
│ ├── Art Brewery.ttf
│ ├── Fonts.qml
│ ├── Roboto-Light.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-Regular.ttf
│ └── qmldir
├── font_test.pro
├── font_test.pro.user
├── main.cpp
├── main.qml
└── qml.qrc
my qml.qrc file is:
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
<qresource prefix="/Fonts">
<file alias="Art Brewery.ttf">assets/Fonts/Art Brewery.ttf</file>
<file alias="Roboto-Light.ttf">assets/Fonts/Roboto-Light.ttf</file>
<file alias="Roboto-Medium.ttf">assets/Fonts/Roboto-Medium.ttf</file>
<file alias="Roboto-Regular.ttf">assets/Fonts/Roboto-Regular.ttf</file>
</qresource>
</RCC>
my project file is:
QT += quick
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = $$PWD/assets
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
assets/Fonts/Fonts.qml \
assets/Fonts/qmldir
My Fonts.qml file is:
pragma Singleton
import QtQuick 2.12
Item
{
readonly property FontLoader artBrewery: FontLoader { source: "qrc:/Fonts/Art Brewery.ttf" }
readonly property FontLoader robotoLight: FontLoader { source: "qrc:/Fonts/Roboto-Light.ttf" }
readonly property FontLoader robotoMedium: FontLoader { source: "qrc:/Fonts/Roboto-Medium.ttf" }
readonly property FontLoader robotoRegular: FontLoader { source: "qrc:/Fonts/Roboto-Regular.ttf" }
}
My qmldir inside of the assets/fonts folder is:
singleton Fonts 1.0 Fonts.qml
I try to use the font in main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import Fonts 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Column
{
spacing: 8
anchors.fill: parent
anchors.margins: 8
Label
{
text: "DEFAULT: Pack my box with five dozen liquor jugs"
}
Label
{
text: "ART BREWERY: Pack my box with five dozen liquor jugs"
font.family: Fonts.artBrewery.name
font.pixelSize: 36
}
Label
{
text: "ROBOTO: Pack my box with five dozen liquor jugs"
}
}
}
Before I added QML_IMPORT_PATH = $$PWD/assets to my project file, Qt Creator would complain about import Fonts 1.0. Does it make sense this would be required?
I am wondering if assets/fonts/qmldir belongs in DISTFILES...?
I am not sure what needs to be changed so font.family: Fonts.artBrewery.name in main.qml will work.
As described here, the module has to be available in the QML engine's import path:
To define a module, a developer should gather together the various QML documents, JavaScript resources and C++ plugins which belong in the module into a single directory, and write an appropriate module definition qmldir file which should also be placed into the directory. The directory can then be installed into the QML import path as a module.
You can do this by calling addImportPath() with the path to the parent directory of the directory that contains the qmldir. When you import your module with
import Fonts 1.0
the QML engine looks through each import path for a directory called Fonts, and if it finds it, looks for a qmldir file. Since you use a prefix in your QRC file, the final path to the qmldir file is :/Fonts/qmldir. The parent directory of Fonts (the directory that contains the qmldir) is the root resource directory :/, so:
diff --git a/main.cpp b/main.cpp
index 3d80569..de4efb7 100644
--- a/main.cpp
+++ b/main.cpp
## -10,6 +10,7 ## int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
+ engine.addImportPath(":/");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
You also need to ensure that all of the files your module uses are available as resources. That means adding the following files:
diff --git a/qml.qrc b/qml.qrc
index f212706..40cb8dc 100644
--- a/qml.qrc
+++ b/qml.qrc
## -3,6 +3,8 ##
<file>main.qml</file>
</qresource>
<qresource prefix="/Fonts">
+ <file alias="qmldir">assets/Fonts/qmldir</file>
+ <file alias="Fonts.qml">assets/Fonts/Fonts.qml</file>
<file alias="Art Brewery.ttf">assets/Fonts/Art Brewery.ttf</file>
<file alias="Roboto-Light.ttf">assets/Fonts/Roboto-Light.ttf</file>
<file alias="Roboto-Medium.ttf">assets/Fonts/Roboto-Medium.ttf</file>
I see another answer beat me in a couple of minutes. Oh well. I'll post mine just in case.
How to fix the problem through directory import:
Add missing files to resource list in qml.qrc file:
<qresource prefix="/Fonts">
...........
<file alias="Fonts.qml">assets/Fonts/Fonts.qml</file>
<file alias="qmldir">assets/Fonts/qmldir</file>
please note the aliases, otherwise paths will be different
If you do not add the files to resources, they won't be visible through qrc://, and also they won't be included into your compiled application i.e. your code will only run on your computer unless you install missing files manually with your application
Remove module import from main.qml:
//import Fonts 1.0
This is not needed (and will not work) if you create your singleton through qmldir file
The import won't work because Qt won't be looking for modules within qrc:// path unless you explicitly specify so in C++ code - see the other answer on how to do that
Instead add a directory import to the top of main.qml:
import "qrc:/Fonts/"
this imports qmldir file which creates a singleton named Fonts from file Fonts.qml as you specified
Please note that although it imports qmldir and *.qml files inside the directory, it does not tell Qt to load modules from that same directory.
I also had to add QT += qml to font_test.pro but it's probably not needed for your version of Qt/QML if it compiles at all
Use your singleton like you are already trying to do: Fonts.artBrewery.name
References
See Qt documentation for more information:
QML directory import including directory definition qmldir files
module definition qmldir files
I'm trying to make a directory of a singleton QML File "All.qml" which I can import anywhere else into my project so that I can access its objects (namely the drawer). I made a qmldir file, in the same folder as the "All.qml", and even add the directory to the .qrc file.
The contents of the directory is as follows:
Module App.Drawer
singleton All 1.0 All.qml
But when I type in
import App.Drawer. 1.0
It says "module 'App.Drawer' not installed". I can't find any other way to access that drawer, as the project is huge with multiple folders and directories. Can anyone help me?
Also, this project has C++ integrated with it. I tried going and finding some file where maybe the other directories (there are other custom directories, which were made beforehand) have been installed, but couldn't find any.
You have to make sure that QEngine can find the qmldir file, and it has some specific requirements on where it will look.
First to make QEngine aware of the qmldir file you have to add an import path:
engine.addImportPath("qrc:/");
Your path may vary, read on:
The qmldir file has to placed in the folder structure dictated by module name. In your case it is <rootPath>/App/Drawer/qmldir. The "rootPath" is unknown to me, but let's assume you have the following in your qrc file:
<RCC>
<qresource prefix="/ProjectX/App/Drawer">
<file>Drawer.qml</file>
<file>qmldir</file>
</qresource>
</RCC>
Then "rootPath" is qrc:/ProjectX and the import call becomes:
engine.addImportPath("qrc:/ProjectX");
Also, the module declaration in qmldir should be the same as the folder structure where the qmldir file is placed. (And I think it should be lowercase)
module App.Drawer
singleton Drawer 1.0 Drawer.qml
If you want Qt Creator to also find the stuff you can use the QML2_IMPORT_PATH environment variable and set it to the correct folder using the same logic.
You can also place the files in the <Qt_installation_folder>/qml/App/Drawer but this means every project can use it and you have to keep it up-to-date during development, which might be overdone.
Edit
To see if your files are lined up correctly, you can add this debug code:
QDirIterator it(":", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
}
I have a PyQt5 application and most widgets written in Python. I want to write some widget in C++ Qt to make it faster and then embed it into my PyQt QMainWindow.
Is it possible?
You can use SIP to be able to execute a widget created in C ++ from python, in the following link I show an example of how to do it.
The structure of the example is as follows:
├── configure.py
├── sip
│ ├── AnalogClock.sip
│ └── PyAnalogClock.sip
└── src
├── analogclock.cpp
├── analogclock.h
├── analogclockl_global.h
└── AnalogClock.pro
In the src folder you must create the widget library
In the sip folder you must place the structure of the class that you will expose:
AnalogClock.sip
%Import QtGui/QtGuimod.sip
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
class AnalogClock : public QWidget{
%TypeHeaderCode
#include "analogclock.h"
%End
public:
AnalogClock(QWidget *parent /TransferThis/ = 0);
protected:
virtual void resizeEvent(QResizeEvent *);
virtual void paintEvent(QPaintEvent *e);
};
%End
PyAnalogClock.sip
%Module(name=PyAnalogClock, call_super_init=True, keyword_arguments="Optional")
%DefaultMetatype PyQt5.QtCore.pyqtWrapperType
%DefaultSupertype sip.simplewrapper
%Include AnalogClock.sip
configure.py is the script that configures the compilation of the project, if you have any problems you must modify some path (it has been tested in Linux)
It is then compiled by executing the following:
python configure.py
make
sudo make install
When executing the previous one it generates a folder called modules, inside of it is the dynamic library, in the case of the example PyAnalogClock.so, this file we place it in the folder of the source code:
.
├── main.py
└── PyAnalogClock.so
main.py
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyAnalogClock import AnalogClock
if __name__=="__main__":
import sys
a=QApplication(sys.argv)
w=AnalogClock()
w.show()
sys.exit(a.exec_())
output:
You can use SIP to create bindings for your C++ code the same way that the PyQt bindings are made.
However, the bindings generated by SIP are themselves C++ code, and in the case of PyQt link directly into the Qt binaries. If you just intend to rewrite PyQt code as C++ then any speedup realised will be negligible, as very little native python is executed in the first place.
I want to import a custom module in my main.qml file. Main.qml is located under "/" prefix of my qml.qrc resource.
My custom module Config.qml is located within Config subdirectory. (Config directory is where main.qml is, i.e. /path/to/main/Config/Config.qml.
The config.qml and qmldir files are stored under the prefix myPrefix in the qml.qrc file.
Project
|- Config
|- Config.qml
|- qmldir
|- main.qml
Also I created a qmldir file which is according to the documentation http://doc.qt.io/qt-5/qtqml-modules-identifiedmodules.html necessary. Here are my Config.qml and qmldir files.
Config.qml
pragma Singleton
import QtQuick 2.0
QtObject {
property int myVariable: 10
}
qmldir
singleton Config 1.0 Config.qml
When I want to import my custom module asMyModule in the main.qml file.
import "???" as MyModule
How can I do that? Does someone have a suggestion?
Edit:
qrc file
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
<qresource prefix="/myPrefix">
<file>Config/qmldir</file>
<file>Config/Config.qml</file>
</qresource>
** Question has been changed after the answer of Arpegius to raise another issue, I answer this new issue. **
This has nothing to do with qrc-prefix.
I believe your are mixing two different methods to import.
With or without prefix, to import a module you need to set the import-path of the QtQuick engine accordingly.
In your case, because your module directory is in the project-root directory :
engine.addImportPath("qrc:/");
// Now engine will look for subfolders which could be modules == with a qmldir
And in your main.qml you do the import using the prefix path instead of the filesystem path :
import myPrefix 1.0 as MyNamespace
You can also import simple QML files and not as a module :
// Because the path is relative to main.qml even in a qrc
import "myPrefix" as MyNamespace
Then you don't need the qmldir at all.
From documentation:
The module's qmldir file must reside in a directory structure within the import path that reflects the URI dotted identifier string, where each dot (".") in the identifier reflects a sub-level in the directory tree. For example, the qmldir file of the module com.mycompany.mymodule must be located in the sub-path com/mycompany/mymodule/qmldir somewhere in the import path.
So you should change module MyModule to module Config or import it within specific path:
import "./Config" as MyModule
if this is still an issue for anyone, you to right click on the file and select add file to directory. then you select the directory you wish to add the qml file in. this directory should be the same as the main qml file. doing this solved my problem
I've strange problem with Qt. Recently I downloaded Qt 5.0.1. And now every project I start in Qt as "Build->Start" works well. But if I start Release version of it from explorer there's no effect. And if I start Debug version from explorer I have this error
What's wrong?
I think you forgot to copy plugins directory beside your application.
Dependency Walker wont show them in the list, because they're loaded in runtime by Qt Core libs. So final executable have no idea about linkage or location of those plugins at compile time.
It precisely says, what it needs - the "windows" plugin. It should be located in folder "platforms", as qwindows.dll.
You can read more in Qt5 official windows deployment guide, but rather look on the forums for more practical info, i. e. here.
In short: to make your application (compiled with Qt built dynamically) run on other machine, you must include many libs with it. All of them should be copied from
Qt_installation_folder/Qt_version/used_compiler/bin
&
Qt_installation_folder/Qt_version/used_compiler/plugins/
QML plugins should be copied from
Qt_installation_folder/Qt_version/used_compiler/qml
&
Qt_installation_folder/Qt_version/used_compiler/imports
It is very important to copy Qt libraries from exact the same compiler as used in the project.
Below I present you an example (borrowed from above second link) with explanations:
ROOT FOLDER
│ YourApp.exe
│ D3DCompiler_43.dll // } \
│ libEGL.dll // } --> If you use Qt built with ANGLE support
│ libGLESv2.dll // } /
│
│ icudt49.dll // } \
│ icuin49.dll // } --> If you use Qt built with WebKit (Unicode support)
│ icuuc49.dll // } /
│
│ Qt5Core.dll // --> Basic Qt module, always needed
│ Qt5Gui.dll // --> If you use GUI module
│
│ Qt5Network.dll // } \
│ Qt5Qml.dll // } --> If you use QML
│ Qt5Quick.dll // } --> module
│ Qt5V8.dll // } /
│
│ Qt5Multimedia.dll // } --> If you use multimedia
│ Qt5MultimediaQuick_p.dll // } --> from QtQuick
│
├───platforms
│ qwindows.dll // Always needed for windows
│
├───QtMultimedia // If you import QtMultimedia 5.x
│ declarative_multimedia.dll
│ plugins.qmltypes
│ qmldir
│ Video.qml
│
├───QtQuick.2 // If you import Qt.Quick 2.x
│ plugins.qmltypes
│ qmldir
│ qtquick2plugin.dll