Make new window from separate file appear or disappear with QQmlApplicationEngine - qt

I'm using QQmlApplicationEngine то load my main window.
QQmlApplicationEngine engine;
engine.load("GUI.qml");
Where GUI.qml is my main GUI file. How I can create and destruct a new window from code? As far as I can see, if I write engine.load("SecondWindow.qml");, how I can close it? Or I should create and destruct such objects from QML itself?

Option 1: You can do it from QML, see this sample:
import QtQuick 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
title: "Window 1"
CheckBox {
id: cb
text: "Show Window #2"
}
Loader {
active: cb.checked
sourceComponent: Component {
ApplicationWindow { // Or "SecondWindow"
visible: true
width: 640
height: 480
title: "Window 2"
}
}
}
}
Option 2: Also, you can control it from C++ side, for example like this:
QML
import QtQuick 2.12
import QtQuick.Controls 2.5
ApplicationWindow {
id: window
visible: true
width: 640
height: 480
title: "Window 1"
Loader {
active: showWindowFlag
// Instead of "sourceComponent" you can use
// source: "SecondWindow.qml"
sourceComponent: Component {
ApplicationWindow {
visible: true
width: 640
height: 480
title: "Window 2"
}
}
}
}
C++
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QTimer>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
bool showWindowFlag = false;
engine.rootContext()->setContextProperty("showWindowFlag", showWindowFlag); // !!!!
auto timer = new QTimer(&engine); // Parent will delete timer
QObject::connect(timer, &QTimer::timeout, [&](){
showWindowFlag = !showWindowFlag;
engine.rootContext()->setContextProperty("showWindowFlag", showWindowFlag);
});
timer->setInterval(1000);
timer->setSingleShot(false);
timer->start();
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

Related

QT6.1 - Qml Why does the ProgressBar not have an animation corresponding to the indeterminate property?

As the title says, I set the indeterminate property of the ProgressBar to True, but he doesn't have any animation.
Just like this:
But:
I use the default project and the code is very simple.
I would like to know if the indeterminate itself does not have any animation or what is wrong with it?
Thanks for your help.
By the way, this is the first time I'm looking for answers here, so I hope it will be a pleasant experience :)
version:
Qt6.1.1 MinGW 64-bit (default Debug Version)
The code is as follows:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ProgressBar{
id: proBar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: 20
from: 1
to: 1
indeterminate: true
}
}
Yes, that's all the code in my qml. The rest of the file did not change a word
I think it relates to your Qt version , I test your code in my Qt .
I use Qt5.14 and GCC compiler, the result is this :
For adding Style :
in main.cpp put this
QQuickStyle::setStyle("Universal");
like this :
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQuickStyle::setStyle("Universal");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl)
{
if (!obj && (url == objUrl))
{
QCoreApplication::exit(-1);
}
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
and in .pro file add this :
QT += quick quickcontrols2
Edited code
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Universal 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Universal.theme: Universal.Dark
Universal.accent: Universal.Red
ProgressBar{
id: proBar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: 70
from: 1
to: 1
indeterminate: true
}
}

Qt Quick2 Material Dark Theme looks buggy/unreadable

I applied Material Dark Theme on my application as recommended on this question:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickStyle>
#include <QDebug>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
qputenv("QT_QUICK_CONTROLS_STYLE", QByteArray("Material"));
qputenv("QT_QUICK_CONTROLS_MATERIAL_THEME", QByteArray("Dark"));
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
And my main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Button {
id: button
x: 145
y: 70
width: 151
height: 90
text: qsTr("Button")
}
RoundButton {
id: roundButton
x: 401
y: 120
text: "+"
}
CheckBox {
id: checkBox
x: 157
y: 297
text: qsTr("Check Box")
}
Slider {
id: slider
x: 345
y: 232
value: 0.5
}
DelayButton {
id: delayButton
x: 377
y: 344
text: qsTr("Delay Button")
}
Switch {
id: switch1
x: 151
y: 409
text: qsTr("Switch")
}
}
While default material works as expected, if I change to material dark it looks like this:
Material dark looks buggy:
I am pretty sure it shouldn't look like this. Did I miss to install something or do I need to import something additionally?
Using qtcreator on Windows, qml objects are just random unchanged controls.
That should work with the Window from Qt Quick. Please create a bug report for that. Using ApplicationWindow does work though.

Independent dimensions for QML-Items

I am using QQmlApplicationEngine and therefore have one root element and Item-s. Because I have one root file, to which all the methods connected from C++ (but still accessible in whole .qml directory) I can't make the other Item-s be independet from the dimension settings of the root. So if I make minimumwidth of the value 300, so the other Item-s going to have the same minimumWidth too.
The quesstion is, whether it's possible to make them independent from main.qml and be able set others dimensions.
Here is some code to make you idea what I am talking about:
main.cpp:
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.rootContext()->setContextProperty("mqttClient",mqttClient);
engine.rootContext()->setContextProperty("math",math);
engine.load(url);
main.qml:
Window {
id:root
width: 400
height: 300
minimumWidth: 960
minimumHeight: 420
visible: true
title: qsTr("Dampfmaschine Client")
StackView {
id: stackView
initialItem: "LoginPage.qml"
anchors.fill: parent
}
Component{
id: login
LoginPage{}
}
Component{
id: measure_page2
MeasurePage2{}
}
function load_page(page){
switch(page){
case 'MeasurePage':
stackView.push(measure_page2);
break;
}
}
}
You can use the Binding type in QML to set a binding which can be optional. I propose to add some property in your pages, for example:
LoginPage {
property int windowWidth : 200
property int windowHeight : 300
}
Then in main, you put the Binding
Window {
id:root
width: 400
height: 300
minimumWidth: 960
minimumHeight: 420
visible: true
title: qsTr("Dampfmaschine Client")
Binding {
target: root
property: "width"
value: stackView.currentItem.windowWidth
}
Binding {
target: root
property: "height"
value: stackView.currentItem.windowHeight
}
StackView {
id: stackView
initialItem: "LoginPage.qml"
anchors.fill: parent
}
Component{
id: login
LoginPage{}
}
Component{
id: measure_page2
MeasurePage2{}
}
function load_page(page){
switch(page){
case 'MeasurePage':
stackView.push(measure_page2);
break;
}
}
}
This way, the window will always be bound to the current item of the stackView and you don't have to look after it.
Optionally you can also use implicitWidth and implicitHeight from the pages, leading to even less maintenance (but possibly some headaches with weird pages)

How to slide QListView to the end and start from beginning?

I'm working on a project that gets news with API. I can clearly get the news from api and load them to the listview.
I simplify the code for telling my problem clearly.
Here is a 2 questions...
1 - I need to slide this list from top to the bottom basic sliding animation with given time. (eg. y from 0 to en of list with 5secs). The important point is the item count of the list can be changeable.
2 - When the animation reachs to the end of the list, I need to see the first item after the last item. But it has to be like this; after the last item of list, the first item has to shown( like infinite list) while the sliding process going on.
Here are my codes;
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QStringList news = { "news01",
"news02",
"news03",
"news04",
"news05",
"news06",
"news07",
"news08",
"news09",
"news10",
"news11",
"news12",
"news13",
"news14",
"news15",
"news16",
"news17",
"news18",
"news19",
};
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("listNews",news);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
Window {
id:pencere
visible: true
width: 640
height: 480
title: qsTr("Hello World")
color: "black"
ListView{
id: newsListView
implicitWidth: parent.width
implicitHeight: parent.height
model:listNews
spacing: 5
delegate: Rectangle {
id: delegateBackground
color:"#505051"
radius: 10
width: parent.width
height: contentContainer.height + 20
Item {
id: contentContainer
width: parent.width - 20
height: column.height
anchors.centerIn: delegateBackground
RowLayout {
width: parent.width
Rectangle {
id: newsicon
width: 16
height: 16
color: "steelblue"
Layout.alignment: Qt.AlignTop
}
ColumnLayout {
id: column
Layout.fillWidth: true
spacing: 100
Text {
Layout.fillWidth: true
Layout.alignment: Qt.AlignBottom
id: messageText
text: modelData
wrapMode: TextEdit.WordWrap
verticalAlignment: index %2 == 0 ? Text.AlignBottom : Text.AlignTop
color: "white"
}
}
}
}
}
}
}
For the first question you could add something like the following to your ListView. This will trigger an animation if you press the arrow key up/down. It isn't perfect, but it explains how to use NumberAnimations. The key to move the ListView content is the property contentY. If you want to scroll all the way to the bottom of the news feed you could calculate the position by using contentHeight of the ListView and the Window height.
ListView {
id: newsListView
property bool scrollUp: false
property bool scrollDown: false
focus: true
Keys.onUpPressed: newsListView.scrollUp = true
Keys.onDownPressed: newsListView.scrollDown = true
NumberAnimation on contentY {
running: newsListView.scrollDown
from: 0
to: newsListView.contentHeight
duration: 1000
onFinished: newsListView.scrollDown = false
}
NumberAnimation on contentY {
running: newsListView.scrollUp
from: newsListView.contentHeight
to: 0
duration: 1000
onFinished: newsListView.scrollUp = false
}
...
}
For the first question as proposed by #iam_peter, you can try using NumberAnimation to animate scrolling. For second query, in my opinion you can try researching on PathView as it is much easier to get circular list behavior in PathView without cumbersome index calculations.
Also, please have a look at this topic ListView Scrolling.

The program has unexpectedly finished - app crashed

I have a problem with Qt Charts in QML modeling. I have a simple application that implements a very simple ChartView. As I run the application, it crashed and I get the error in Application Output The program has unexpectedly finished.
I added in my src.pro
QT += qml quickcontrols2 charts
and my applications is this
import QtCharts 2.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ChartView {
anchors.fill: parent
theme: ChartView.ChartThemeBrownSand
antialiasing: true
PieSeries {
id: pieSeries
PieSlice { label: "eaten"; value: 94.9 }
PieSlice { label: "not yet eaten"; value: 5.1 }
}
}
}
How do I have this problem?
Check if you are using QGuiApplication instead of QApplication in your main.cpp.
The following example works properly, but it crashes if we use QGuiApplication in main():
Note: Since Qt Creator 3.0 the project created with Qt Quick Application wizard based on Qt Quick 2 template uses QGuiApplication by default. As Qt Charts utilizes Qt Graphics View Framework for drawing, QApplication must be used. The project created with the wizard is usable with Qt Charts after the QGuiApplication is replaced with QApplication.
More info here.
main.cpp
#include <QApplication>
#include <QQuickView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQuickView *view = new QQuickView;
view->setSource(QUrl(QLatin1String("qrc:/main.qml")));
view->show();
return app.exec();
}
main.qml
import QtQuick.Controls 2.0
import QtQml 2.2
import QtCharts 2.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ChartView {
anchors.fill: parent
theme: ChartView.ChartThemeBrownSand
antialiasing: true
PieSeries {
id: pieSeries
PieSlice { label: "eaten"; value: 94.9 }
PieSlice { label: "not yet eaten"; value: 5.1 }
}
}
}

Resources