I am working on a project where I have to make a multi-screen/window application. I am using QML and PySide6 for this purpose. The flow of my applications is like below:
login screen -> search screen (search for certain items) -> test screen (performs some operations) -> reports screen (displays results from test screen).
Currently what I am doing is using a main.py file to load the login page:
import os
from pathlib import Path
import sys
from api_login_test import get_credentials
# from login_data import get_credentials
from PySide6.QtCore import QCoreApplication, Qt, QUrl, QObject
from PySide6.QtWidgets import QApplication, QLineEdit, QPushButton
from PySide6.QtQml import QQmlApplicationEngine
CURRENT_DIRECTORY = Path(__file__).resolve().parent
def main():
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
credentials = get_credentials()
engine.rootContext().setContextProperty('credentials', credentials)
login_file = os.fspath(CURRENT_DIRECTORY / "qml" / "login.qml")
url = QUrl.fromLocalFile(login_file)
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.QueuedConnection)
engine.load(url)
sys.exit(app.exec())
if __name__ == "__main__":
main()
once the login page opens up now for switching rest of the screens, I use javascript function I wrote in all my qml files to switch to next screen. Following is the JS code I am using for switching to next screen.
function switch_to_test(access) {
if (access == true) {
var component = Qt.createComponent("test_interface_dark_debug.qml")
var win = component.createObject()
win.show()
visible = false
}
else {
console.log('Invalid Credentials')
}
}
And this is causing my UI to crash as I reach test screen. So is there a way to efficiently switching the screens without my UI crashing? I found out this explanation for the crashing of my UI, but I don't know how to resolve the issue. Thank you
CodePudding user response:
The following is a showcase of various approaches regarding to your question.
Although all the code here is coherent and meant to be run together, It shows different approaches to navigate pages and you may adopt what you like.
Setup:
File main.py:
import sys
from pathlib import Path
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
qml_file = Path(__file__).parent / "main.qml"
engine.load(qml_file)
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
Method 1: Use a StackView
:
File main.qml:
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material 2.15
ApplicationWindow {
id: mainFrame
width: 640
height: 480
visible: true
title: qsTr("Windows handeling in QML")
Material.theme: Material.Dark
StackView{id: stack_view
initialItem: logginWin
anchors.fill: parent;
Component{id: logginWin
LoginWin{
onLoggedIn: {
stack_view.push("./StackLayoutWin.qml")
console.log("logged In")
}
}
}
}
}
File LoginWin.qml:
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material 2.15
Item{id: root
anchors.fill: parent;
signal loggedIn;
TextArea{id: input_
placeholderText: "Enter password"
anchors.centerIn: parent
}
Button{
text: "Login";
anchors {
horizontalCenter: parent.horizontalCenter;
top: input_.bottom
}
onClicked: {
console.log(input_.text)
if(input_.text == "12345")
{
root.loggedIn()
}
else{
input_.text = "Wrong password"
}
}
}
}
Pros | Cons |
---|---|
Default animation | You will have to pop / append windows while navigating, That makes it inconvenient for multi-directional pages workflow. |
Very easy for one direction pages workflow that also can be reversed. |
Method 2:
Here would be our "main application" window.
You would have here different pages the user would be able to navigate.
File StackLayoutWin.qml:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Controls.Material 2.15
Item{
Button{id: return_to_StackView
anchors{
top: parent.top
right: parent.right
}
text: "return to login page"
onClicked: {
stack_view.pop()
}
}
StackLayout {
id: layout
anchors.top: return_to_StackView.bottom
width: parent.width;
height: parent.height;
currentIndex: 1
Rectangle {
color: 'teal'
implicitWidth: 200
implicitHeight: 200
}
Rectangle {
color: 'plum'
implicitWidth: 300
implicitHeight: 200
}
}
}
You can find this example here