0

I am trying to operate a change of text after a ProgressBar finishes its loop as shown below.

The actual result I have is the following:

wrong

The expected result would be the one below:

correct

Below the code of the minimal verifiable example. I am handling the ProgressBar as an external C++ class. In case needed the small verifiable example can be found here in case needed:

main.qml

import QtQuick 2.4
import QtQuick.Controls 2.12
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.12
import QtQuick.Controls.impl 2.12  // for IconLabel

ApplicationWindow {
    id: window
    width: 640
    height: 480
    visible: true

//    property var changeText
//    color: changeText ? changeText.color : "green"

    function buttonClick(button)
    {
        button.text = qsTr(" YES Connecting").arg(button.text);
        button.enabled = false;
        if (button.background && button.background instanceof Rectangle) {
            button.background.color = "green";
            button.background.gradient = null;
            button.background.visible = true;
        }
        if (button.contentItem && button.contentItem instanceof IconLabel) {
            button.contentItem.color = "white";
            button.contentItem.font.bold = true;
            button.contentItem.font.pointSize = 20;
        }
    }
    function textConnectedChange(textChange1)
    {
        textChange1.text = qsTr("Connecting...");
        textChange1.color = "blue";
        textChange1.content = "Connected";
        textChange1.font.bold = true;
        textChange1.font.pointSize = 15;
    }

    QtObject {
            id: test
            property color color: "grey"
        }

    ColumnLayout {
        Button {
            id: dialogA
            text: pBar.running ? "Connecting..." : "Not - Connected"
            Layout.fillWidth: true
            font.pointSize: 20
            spacing: 10
            onClicked: {
                buttonClick(this)
                pBar.startComputation()
            }
        }
        ColumnLayout {
            id: layout
            Layout.fillWidth: true
            spacing: 10
            GroupBox {
                id: box1
                width: parent.width
                title: "Connection"
                font.pointSize: 20
                Layout.fillWidth: parent
                spacing: 10

                GridLayout {
                    width: parent.width
                    columns: 1
                    RowLayout {
                        id: row1
                        spacing: 200
                        Layout.fillWidth: true
                        Layout.fillHeight: false
                        Label {
                            id: textField
                            text: "Connection:"
                            font.pointSize: 15
                            Layout.fillWidth: true
                        }
                        Text {
                            id: connected
                            text: pBar.running ? textConnectedChange(this) : "Not-Connected"
                            color: "red"
                            font.pointSize: 15
                            horizontalAlignment: Text.AlignRight
                            Layout.fillWidth: true
                            onTextChanged: {
                                text: parent.changeText = test
                            }
                        }
                    }
                }
            }
            GroupBox {
                id: boxprogress
                title: "Connection Progress"
                font.pointSize: 20
                Layout.fillWidth: parent
                width: parent.width
                spacing: 10
                GridLayout {
                    width: parent.width
                    columns: 1
                    RowLayout {
                        Layout.fillWidth: true
                        Layout.fillHeight: false
                        ProgressBar {
                            id: progressbar_id
                            Layout.fillWidth: true
                            Layout.fillHeight: true
                            width: parent.width
                            from: 0
                            to: 40
                            value: pBar.progress
                        }
                    }
                }
            }
        }
    }
}

progressbar.h

#ifndef PROGRESSBAR_H
#define PROGRESSBAR_H
#include <QObject>
#include <QFutureWatcher>
class ProgressBar : public QObject
{
    Q_OBJECT
    Q_PROPERTY(float progress READ progress NOTIFY progressChanged)
    Q_PROPERTY(bool running READ running NOTIFY runningChanged)
    Q_PROPERTY(bool finished READ finished NOTIFY finishedChanged)
public:
    ProgressBar();
    float progress();
    bool running();
    bool finished();

public Q_SLOTS:
    void startComputation();
    void cancelComputation();
    void finishComputation();
private Q_SLOTS:
    void updateProgress(int value);
signals:
    void progressChanged();
    void runningChanged();
    void finishedChanged();
private:
    bool m_running = false;
    int m_progressValue = 0;
    int m_finished = true;
    QVector<int> vector;
    QObject m_Model;
    QFutureWatcher<void> m_futureWatcher;
};

#endif // PROGRESSBAR_H

main.cpp

#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "progressbar.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    ProgressBar pBar;
    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    engine.rootContext()->setContextProperty("pBar",   &pBar);
    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();
}

What I have done so far:

1) The following source was useful in understanding the problem but didn't bring any beneficial correction.

2) this post I found to be useful in order to modify the necessary bindings to change a text but didn't work

3) I consulted the official documentation regarding the QML bindings and tried to apply directly from there but something is not correct.

4) You see QObject in the code and that is because from here I thought I had to use it. I left it in the code to show you what additional trials I was trying to do, but that didn't work.

Please point in the right direction to solve this problem.

Emanuele
  • 2,194
  • 6
  • 32
  • 71
  • You should consider storing the example on gist.github.com for better readability of your post, that's probably why you got a downvote – Amfasis Dec 02 '19 at 20:46
  • @Amfasis, thank you very much for reading the question. Yes I am actually about to put the link. Will do it in one sec. – Emanuele Dec 02 '19 at 20:49
  • The small verifiable example can be found here [https://bitbucket.org/ERaggi/textchange/src/master/](https://bitbucket.org/ERaggi/textchange/src/master/) – Emanuele Dec 02 '19 at 20:52
  • I would also remove the cpp code in this case, as it is kinda easy to fill in the gaps, and if not, there is the bitbucket link. Or maybe leave the header – Amfasis Dec 02 '19 at 20:56
  • ok thank you I took out the header to make it simpler – Emanuele Dec 02 '19 at 20:58
  • Uhoh, I meant the other way around, show the header with the Q_PROPERTY but leave the cpp implementation to the bitbucket link – Amfasis Dec 02 '19 at 21:11
  • Ops sorry one sec... – Emanuele Dec 02 '19 at 21:14
  • Ok I have just updated the code in the question :) – Emanuele Dec 02 '19 at 21:21

1 Answers1

1

QML has a State object, which is perfectly suited for handling this kind of problem, I mean, you want different bindings in different "states".

The following example should get you quite somewhere, however, I'm not 100% I extracted everything correctly from your example:

Text {
    id: connected
    text: qsTr("Not-Connected")
    color: "red"
    font.pointSize: 15
    horizontalAlignment: Text.AlignRight
    Layout.fillWidth: true

    states: [
        State {
            name: "connecting"
            when: pBar.running
            PropertyChanges {
                target: connected
                text: qsTr("Connecting...")
                color: "blue"
                font.bold: true
            }
        },
        State {
            name: "connected"
            when: pBar.finished
            PropertyChanges {
                target: connected
                text: qsTr("Yes! Connected...")
                color: "green"
                font.bold: true
            }
        }
    ]
}
Amfasis
  • 3,932
  • 2
  • 18
  • 27
  • thank you for the answer, however it still does not work because as soon as the `ProgressBar` finishes the loop, the text does not change. – Emanuele Dec 02 '19 at 20:59
  • I mean it changes during the progress (but this behavior was happening before). I am trying to understand how to change the text at the end of the loop of the `ProgressBar`. So that at the end of the computation, it says "Connected" – Emanuele Dec 02 '19 at 21:02
  • Ok, I added another `State`, but I don't see how you know you are connected, so I put `something.connected`, which you have to change for your own case – Amfasis Dec 02 '19 at 21:14
  • So basically inside the class `ProgressBar` there is a function called `void spinEC(int &iteration)` which is doing a random calculation (for which I am simulating a real wi-fi connection) and as soon as that finishes, the result should be `Connected` – Emanuele Dec 02 '19 at 21:18
  • I think I know what you mean. I just added an additional `Q_PROPERTY` on the `ProgressBar`. Where you referring to that? – Emanuele Dec 02 '19 at 21:29
  • Connected means the `ProgressBar` finished the computation – Emanuele Dec 02 '19 at 21:53
  • Yes, that is what I mean. I see you (now?) have the `finished` property, will update my answer for it – Amfasis Dec 03 '19 at 07:08
  • Thank Amfasis, I think using `State` is the solution. My `ProgressBar` does not work still. I think is because of the the property `finished` I added, and don't know why. But I am going to mark your answer as correct and write a separate question on how to correctly set a `ProgressBar`. I must have make a mistake that I don't see. Thank you very much for your help! :) – Emanuele Dec 03 '19 at 15:54