Linking QML file to Python file to retrive infomation from user input?
-
I have never worked with GUI for python before and now I needed to and was looking for a GUI lib that didn't look like something from windows ME. So I found this and gave it a go, So I have my .qml file where I made my layout, and my .py file where I call the front end and start the application. Thats as far as I was able to get, I cant get info from my combo-box, I cant get the directory path from my browse button. I would like to know how to get this info. Any insight on how I can do this would be great!
.py file:
import sys import os # Import Modules from PySide6.QtGui import QGuiApplication from PySide6.QtQml import QQmlApplicationEngine from PySide2.QtCore import QStringListModel, QObject, Slot # Instance Class if __name__ == "__main__": app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.load(os.path.join(os.path.dirname(__file__), "qml/main.qml")) comportComboModel = ['Roll Size 1','Roll Size 2','Roll Size 3','Roll Size 4','Roll Size 5'] engine.rootContext().setContextProperty("comModel", comportComboModel) # Close application if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec_())
.qml file:
import Qt.labs.platform 1.1 import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Controls.Material 2.15 ApplicationWindow{ id: window width: 800 height: 500 visible: true title: qsTr("Darwill Roll Tool") // Set Flags flags: Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint | Qt.CustomizeWindowHint | Qt.MSWindowsFixedSizeDialogHint | Qt.WindowTitleHint // Set material Style Material.theme: Material.Dark Material.accent: Material.LightBlue Image { id: image width: 179 height: 47 source: "../imgs/darwill-logo-header-sml_0.png" anchors.left: parent.left anchors.top: parent.top anchors.margins: 30 } Button { text: "Browse" onClicked: folderDialog.open() anchors.right: parent.right anchors.top: parent.top anchors.rightMargin: 240 anchors.topMargin: 30 } Button { text: "Create PDFs" onClicked: folderDialog.open() anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 30 } TextField { id: pathField width: 300 text: qsTr("") selectByMouse: true placeholderText: qsTr("Path to PDF files") readOnly: true anchors.right: parent.right anchors.top: parent.top anchors.rightMargin: 320 anchors.topMargin: 36 } Label { text: "<strong>Created</strong>: jkuzera@darwill.com" anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 10 } ComboBox { id: comBox width: 200 model: comModel anchors.right: parent.right anchors.top: parent.top anchors.margins: 30 } Dialog { FolderDialog { id: folderDialog currentFolder: viewer.folder folder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0] onAccepted: { console.log("You chose: " + folderDialog.folder) } } } }
-
I have never worked with GUI for python before and now I needed to and was looking for a GUI lib that didn't look like something from windows ME. So I found this and gave it a go, So I have my .qml file where I made my layout, and my .py file where I call the front end and start the application. Thats as far as I was able to get, I cant get info from my combo-box, I cant get the directory path from my browse button. I would like to know how to get this info. Any insight on how I can do this would be great!
.py file:
import sys import os # Import Modules from PySide6.QtGui import QGuiApplication from PySide6.QtQml import QQmlApplicationEngine from PySide2.QtCore import QStringListModel, QObject, Slot # Instance Class if __name__ == "__main__": app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.load(os.path.join(os.path.dirname(__file__), "qml/main.qml")) comportComboModel = ['Roll Size 1','Roll Size 2','Roll Size 3','Roll Size 4','Roll Size 5'] engine.rootContext().setContextProperty("comModel", comportComboModel) # Close application if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec_())
.qml file:
import Qt.labs.platform 1.1 import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Controls.Material 2.15 ApplicationWindow{ id: window width: 800 height: 500 visible: true title: qsTr("Darwill Roll Tool") // Set Flags flags: Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint | Qt.CustomizeWindowHint | Qt.MSWindowsFixedSizeDialogHint | Qt.WindowTitleHint // Set material Style Material.theme: Material.Dark Material.accent: Material.LightBlue Image { id: image width: 179 height: 47 source: "../imgs/darwill-logo-header-sml_0.png" anchors.left: parent.left anchors.top: parent.top anchors.margins: 30 } Button { text: "Browse" onClicked: folderDialog.open() anchors.right: parent.right anchors.top: parent.top anchors.rightMargin: 240 anchors.topMargin: 30 } Button { text: "Create PDFs" onClicked: folderDialog.open() anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 30 } TextField { id: pathField width: 300 text: qsTr("") selectByMouse: true placeholderText: qsTr("Path to PDF files") readOnly: true anchors.right: parent.right anchors.top: parent.top anchors.rightMargin: 320 anchors.topMargin: 36 } Label { text: "<strong>Created</strong>: jkuzera@darwill.com" anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 10 } ComboBox { id: comBox width: 200 model: comModel anchors.right: parent.right anchors.top: parent.top anchors.margins: 30 } Dialog { FolderDialog { id: folderDialog currentFolder: viewer.folder folder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0] onAccepted: { console.log("You chose: " + folderDialog.folder) } } } }
@404Developer Before pointing out what you need, I must point out that you have made a mistake that can cause silence bugs: Use PySide6 together with PySide2. Do not do it.
You must bear in mind that:
-
If you want to use FolderDialog then the eventloop must be QApplication as indicated in the docs.
-
If you want to send information from QML to python then you must implement a QObject where a slot receives the information.
*.py
import sys import os # Import Modules from PySide6.QtWidgets import QApplication from PySide6.QtQml import QQmlApplicationEngine from PySide6.QtCore import QObject, Slot class Backend(QObject): @Slot(str) def foo(self, text): print(text) # Instance Class if __name__ == "__main__": app = QApplication(sys.argv) engine = QQmlApplicationEngine() backend = Backend(app) comportComboModel = [ "Roll Size 1", "Roll Size 2", "Roll Size 3", "Roll Size 4", "Roll Size 5", ] engine.rootContext().setContextProperty("comModel", comportComboModel) engine.rootContext().setContextProperty("backend", backend) engine.load(os.path.join(os.path.dirname(__file__), "qml/main.qml")) # Close application if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec())
*.qml
import Qt.labs.platform 1.1 import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Controls.Material 2.15 import QtQuick.Window 2.15 ApplicationWindow { id: window width: 800 height: 500 visible: true title: qsTr("Darwill Roll Tool") // Set Flags flags: Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint | Qt.CustomizeWindowHint | Qt.MSWindowsFixedSizeDialogHint | Qt.WindowTitleHint // Set material Style Material.theme: Material.Dark Material.accent: Material.LightBlue Image { id: image width: 179 height: 47 source: "../imgs/darwill-logo-header-sml_0.png" anchors.left: parent.left anchors.top: parent.top anchors.margins: 30 } Button { text: "Browse" onClicked: folderDialog.open() anchors.right: parent.right anchors.top: parent.top anchors.rightMargin: 240 anchors.topMargin: 30 } Button { text: "Create PDFs" onClicked: folderDialog.open() anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 30 } TextField { id: pathField width: 300 text: qsTr("") selectByMouse: true placeholderText: qsTr("Path to PDF files") readOnly: true anchors.right: parent.right anchors.top: parent.top anchors.rightMargin: 320 anchors.topMargin: 36 } Label { text: "<strong>Created</strong>: jkuzera@darwill.com" anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 10 } ComboBox { id: comBox width: 200 model: comModel anchors.right: parent.right anchors.top: parent.top anchors.margins: 30 onCurrentTextChanged: backend.foo(comBox.currentText) } FolderDialog { id: folderDialog folder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0] onAccepted: { console.log("You chose: " + folderDialog.folder); } } }
-
-
OK, I dont really follow as to what you mean by silence bugs. I want a way for the user to browse for a folder and select it and have it return the path which that does. I dont know any other way to do it. Do you have a suggestion on how to fix the issue you point out and maybe what a silence bug is?
-
OK, I dont really follow as to what you mean by silence bugs. I want a way for the user to browse for a folder and select it and have it return the path which that does. I dont know any other way to do it. Do you have a suggestion on how to fix the issue you point out and maybe what a silence bug is?
@404Developer It seems that you have not understood my comment.
-
A silent bug is one that initially does not cause problems but as the application progresses something fails, and by its nature is difficult to track. Those bugs are the worst.
-
The code from my previous comment is the solution, have you tested it?
-
-
Ahhh I see! That makes sense. Now another question I have while I have someone clearly knowledge here, is it effective to keep grabbing the combo-box as its changed or only as I need it? Because I really only need all the data from the browse button, the combo-box after the create PDFs button is clicked. Is there a way I can set it up so that when the create PDFs button is clicked the data from browse, as well as the combo-box is passed to my python code?
-
Ahhh I see! That makes sense. Now another question I have while I have someone clearly knowledge here, is it effective to keep grabbing the combo-box as its changed or only as I need it? Because I really only need all the data from the browse button, the combo-box after the create PDFs button is clicked. Is there a way I can set it up so that when the create PDFs button is clicked the data from browse, as well as the combo-box is passed to my python code?
@404Developer Recommendation: Don't just copy code but understand it.
The logic is similar:
class Backend(QObject): @Slot(str, QUrl) def foo(self, combo, folder): print(combo, folder.toLocalFile())
onAccepted: { backend.foo(comBox.currentText, folderDialog.folder); }
Note: remove
onCurrentTextChanged: backend.foo(comBox.currentText)
-
@eyllanesc said in Linking QML file to Python file to retrive infomation from user input?:
@Slot(str, QUrl)
Can you run down what the @Slot is for please? That as well as QUrl errors for me.
-
@eyllanesc said in Linking QML file to Python file to retrive infomation from user input?:
@Slot(str, QUrl)
Can you run down what the @Slot is for please? That as well as QUrl errors for me.
@404Developer Precisely Slot is a decorator that allows to expose function to QML. I recommend you review some manuals or examples like https://qmlbook.github.io/. Unfortunately I am not a tutor so I will not respond anymore since in my opinion the problem has already been solved. Goodbye.
Have you imported QUrl:
from PySide6.QtCore import QObject, Slot, QUrl
? Trivial and obvious things I don't usually point out as I assume the OP has minimal knowledge of the tool. -
@404Developer Precisely Slot is a decorator that allows to expose function to QML. I recommend you review some manuals or examples like https://qmlbook.github.io/. Unfortunately I am not a tutor so I will not respond anymore since in my opinion the problem has already been solved. Goodbye.
Have you imported QUrl:
from PySide6.QtCore import QObject, Slot, QUrl
? Trivial and obvious things I don't usually point out as I assume the OP has minimal knowledge of the tool.This post is deleted! -
@eyllanesc said in Linking QML file to Python file to retrive infomation from user input?:
@Slot(str, QUrl)
Can you run down what the @Slot is for please? That as well as QUrl errors for me.
@404Developer Okay, it was a mistake on my part, change:
Button { text: "Create PDFs" onClicked: backend.foo(comBox.currentText, folderDialog.folder); anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 30 }
-
@404Developer Okay, it was a mistake on my part, change:
Button { text: "Create PDFs" onClicked: backend.foo(comBox.currentText, folderDialog.folder); anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: 30 }
@eyllanesc Ahh gotcha, Thank you for taking the time to help me out man. Very much appreciated!