I want show charts in my app with Python back-end and qml front-end but I got an error.
Import:
import QtCharts 2.3
Error:
module "QtCharts" is not installed
I installed qtcharts with maintaince.exe
How to solve this?
In PyQt6 the chart module comes in a separate package and you must run:
python -m pip install PyQt6-Charts PyQt6
On the other hand maintaince.exe only works for C++ so installing QtCharts does not affect PyQt6.
In the next part there is a demo:
import os
from pathlib import Path
import sys
from PyQt6.QtCore import QCoreApplication, Qt, QUrl
from PyQt6.QtWidgets import QApplication
from PyQt6.QtQml import QQmlApplicationEngine
CURRENT_DIRECTORY = Path(__file__).resolve().parent
def main():
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
url = QUrl.fromLocalFile(filename)
def handle_object_created(obj, obj_url):
if obj is None and url == obj_url:
QCoreApplication.exit(-1)
engine.objectCreated.connect(
handle_object_created, Qt.ConnectionType.QueuedConnection
)
engine.load(url)
sys.exit(app.exec())
if __name__ == "__main__":
main()
import QtQuick
import QtQuick.Controls
import QtCharts
ApplicationWindow {
id: root
width: 640
height: 480
visible: true
title: qsTr("Login Page")
ChartView {
id: chartView
anchors.fill: parent
LineSeries {
XYPoint {
x: 0
y: 0
}
XYPoint {
x: 1.1
y: 2.1
}
}
}
}
Note: In Qt6 the versions of the QML modules should not be indicated.
Related
I'm trying to run the example of item selection for a TableView, but it needs Qt.labs.qmlmodels. The problem is, that doesn't appear to be installed, and I can't find the correct package.
main.qml:
import Qt.labs.qmlmodels
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ApplicationWindow {
visible: true
width: 1000
height: 700
title: "Test"
TableView {
id: tableView
anchors.fill: parent
clip: true
model: TableModel {
rows: [{
"name": "Harry"
}, {
"name": "Hedwig"
}]
TableModelColumn {
display: "name"
}
}
selectionModel: ItemSelectionModel {
model: tableView.model
}
delegate: Rectangle {
required property bool selected
implicitWidth: 100
implicitHeight: 30
color: selected ? "blue" : "lightgray"
Text {
text: display
}
}
}
}
main.py:
import sys
import signal
from PyQt6.QtGui import QGuiApplication
from PyQt6.QtQml import QQmlApplicationEngine
# Make app respond to Ctrl-C
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.quit.connect(app.quit) # type: ignore
engine.load("main.qml")
sys.exit(app.exec())
Running main.py gives me this error:
QQmlApplicationEngine failed to load component
file:///home/user/test2/main.qml:1:1: module "Qt.labs.qmlmodels" is not installed
OS: Arch Linux
Qt version: 6.3.1-1
please read this:
qt-6.4-qml-python-missing-liberary-module-qt5compat-graphical-effects-is-not-installed
Just now, I try to change matplotlib-backends' version. I find that the pyqt6 folder doesn't have the Qt folder.
So I copy that in pyside6 lib to pyqt lib.
For me is:from D:\Python\Python39\Lib\site-packages\PySide6\qml\Qt to D:\Python\Python39\Lib\site-packages\PyQt6\Qt6\qml.
Please try this, hope it work.
I just created a new project in Qt-creator: "Qt for python QtQuick application",
When i try to run automatically generated code it throws following error
Error
QQmlApplicationEngine failed to load component
file:///C:/Users/dell/Documents/test1/qml/main.qml:2:1: plugin cannot be loaded for module "QtQuick.Window": Cannot load library C:\Users\dell\Anaconda3\Library\qml\QtQuick\Window.2\windowplugin.dll: The specified procedure could not be found.
main.py
# This Python file uses the following encoding: utf-8
import sys
import os
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
}
I have added a simple QML component ("qml/MyButton") to my "resource.qrc" file:
<RCC>
<qresource prefix="/">
<file>qml/MyButton.qml</file>
</qresource>
</RCC>
I then compiled the QRC to a python module with:
pyside2-rcc -o resource.py resource.qrc
Then I imported resource.py in main.py:
import sys
import os
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
import resource
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
And called MyButton component in main.qml:
import QtQuick 2.13
import QtQuick.Window 2.13
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
MyButton {
}
}
This is "qml/MyButton.qml":
import QtQuick 2.0
import QtQuick.Controls 2.13
Button {
text: 'Click Me'
}
When I run the program I get the error that "MyButton is not a type". I want to use the QML component by using the python generated resource file. I don't know what I am doing wrong.
Automatic import if the .qml is next to the main file but in your case MyButton.qml is not next to the main.qml so the package has to be imported:
import QtQuick 2.13
import QtQuick.Window 2.13
import "qrc:/qml"
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
MyButton {
}
}
I have a problem with Toolbar when I use the qml file with PyQt5. The result is not the seem : no background image when mouse is over, image no resize automatically.
I want to know if it's normal.
How can I do for have the same result with PyQt5
The result with qmlscene:
The result with Python:
Thanks you for your help.
File : _test.py
from PyQt5.QtCore import (
pyqtProperty,
pyqtSignal,
pyqtSlot,
QAbstractListModel,
QModelIndex,
QObject,
Qt,
QTimer,
)
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtQuick import QQuickView
class MainWindow(QObject):
def __init__(self, parent=None):
super().__init__(parent)
if __name__ == "__main__":
import sys
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.quit.connect(app.quit)
main_window = MainWindow()
engine.load("_test.qml")
if not engine.rootObjects():
sys.exit(app.exec_())
sys.exit(app.exec())
File : _test.qml
import QtQuick 2.4
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
ApplicationWindow {
width: 500
height: 200
visible: true
ToolBar {
Layout.fillWidth: true
RowLayout {
anchors.fill: parent
ToolButton {
//width: parent.height
anchors.margins: 4
iconSource: "ico/abacus.png"
}
ToolButton {
width: parent.height
Image {
source: "ico/quitter.png"
anchors.fill: parent
anchors.margins: 4
}
}
ToolButton {
width: parent.height
iconSource: "ico/start.png"
anchors.margins: 4
}
ToolButton {
width: parent.height
Image {
source: "ico/stop.png"
anchors.fill: parent
anchors.margins: 4
}
}
}
}
}
Analyzing the source code of qmlscene and testing with the --apptype option I get the following:
qmlscene _test.qml --apptype gui
qmlscene _test.qml --apptype widgets
So analyzing the fundamental difference is that QApplicacion is being used and not QGuiApplication, so internally it should activate some flag that scales the icons.
Considering the above, the solution is:
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
if __name__ == "__main__":
import os
import sys
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
current_dir = os.path.dirname(os.path.realpath(__file__))
file = os.path.join(current_dir, "_test.qml")
engine.load(QUrl.fromLocalFile(file))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
According to the docs of Qt Quick Controls 1:
Note: We are using QApplication and not QGuiApplication in this
example. Though you can use QGuiApplication instead, doing this will
eliminate platform-dependent styling. This is because it is relying on
the widget module to provide the native look and feel.
So it seems that the scaling of the icons is part of the style of the platform.
Each type of project requires a QXApplication:
Console application: You can use any of the 3 types of QXApplication, but using QCoreApplication is the most optimal since the other QXApplication require that they have a window system that in that case is an unnecessary requirement.
QML Application: It requires at least one QGuiApplication, but for certain ones such as the need to use the styles of each platform it is necessary to use QApplication.
Qt Widgets Application: A QApplication is necessary because QWidgets use the styles of each platform.
The fact that sizes change, is this a problem of QtQuick.Controls 1?
Yes, one of the main differences between QQC1 and QQC2 is that the first one is developed to support desktop platforms so you use the styles, unlike the second one that is designed for embedded systems where the main objective is performance. For more information read Differences with Qt Quick Controls 1
Conclusions:
If you want your GUI made with QML to respect the styles of your desktop platform then you must use QQC1 with QApplication.
If your goal is that the style of your application does not respect the style of the desktop in addition to wanting more performance you should use QQC2 with QGuiApplication.
I have a python file and a qml file.
There is a button in the qml file to load a FileDialog. When I directly use qmlscene test.qml, the FileDialog is ok. But when I use python3 main.py, the FileDialog is strange, and I can't select a file by it. Please tell me how to fix it.
This is the normal file-dialog:
And this is the strange file-dialog:
The code is the following:
test.qml
import QtQuick 2.4
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtQuick.Layouts 1.1
Rectangle {
width: 400
height:30
Button {
id: save
text: "save"
onClicked: {
fileDialogLoader.item.open()
}
}
Loader {
id: fileDialogLoader
sourceComponent: fileDialog_com
}
Component{
id: fileDialog_com
FileDialog {
id: fileDialog
title: "select a file"
nameFilters: ["pdf files(*.pdf)"]
selectExisting: false
onAccepted: {
console.log(" you choose: "+ fileDialog.fileUrls)
}
}
}
}
main.py
#!/usr/bin/env python
# encoding: utf-8
from PyQt5.QtCore import QUrl, QObject, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
class MyMain(QObject):
pass
if __name__ == '__main__':
path = 'test.qml'
app = QGuiApplication([])
view = QQuickView()
con = MyMain()
context = view.rootContext()
context.setContextProperty("con",con)
view.engine().quit.connect(app.quit)
view.setSource(QUrl(path))
view.show()
app.exec()
The "strange" file-dialog is a default implementation that has been written entirely in QML. Qt will use this as a fallback when it cannot create either the platform's native dialog or the built-in QFileDialog.
The reason why your example uses the qml fallback, is because you are using QGuiApplication, which is not widget-based. If you switch to QApplication, your example will work as expected:
# from PyQt5.QtGui import QGuiApplication
from PyQt5.QtWidgets import QApplication
...
# app = QGuiApplication([])
app = QApplication([])