Reputation: 2394
I have a small example of a ProgressBar
that when it finishes to execute the loop should notify the user that the calculation finished.
To be specific, after the ProgressBar
finishes, a Text
should turn from Connecting...
to Connected
.
The problem is that as soon as the ProgressBar
arrives at the end of the calculation the text does not change. I think that the problem might be on how I set the finished
function of the ProgressBar
. I have been trying to solve this problem for the last hours but there is some error I can't catch.
Below the most important part of the code:
progressbardialog.h
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;
};
progressbardialog.cpp
ProgressBar::ProgressBar()
{}
void spinEC(int &iteration)
{
Q_UNUSED(iteration)
const int work = 1000 * 1000 * 400;
volatile int v = 0;
for(int j = 0; j < work; ++j)
++v;
}
float ProgressBar::progress()
{
return m_progressValue;
}
bool ProgressBar::running()
{
return m_running;
}
bool ProgressBar::finished()
{
return m_finished;
}
void ProgressBar::startComputation()
{
m_running = true;
emit runningChanged();
// Prepare the vector
vector.clear();
for(int i = 0; i < 40; ++i)
vector.append(i);
const QFuture<void> future = QtConcurrent::map(vector, spinEC);
m_futureWatcher.setFuture(future);
connect(&m_futureWatcher, &QFutureWatcher<void>::progressValueChanged,
this, &ProgressBar::updateProgress);
}
void ProgressBar::cancelComputation()
{
m_running = false;
emit runningChanged();
}
void ProgressBar::finishComputation()
{
m_progressValue = false;
emit progressChanged();
}
void ProgressBar::updateProgress(int value)
{
m_progressValue = value;
emit progressChanged();
}
main.qml
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
}
}
]
}
EDITS:
On the progressbar.cpp I also tried the following in the function void ProgressBar::finishComputation()
but also it didn't work:
void ProgressBar::finishComputation()
{
m_progressValue = false;
emit finishedChanged();
}
What I have done so far is debugging the code as much as possible and after debugging line per line (I could not find out and decided to go line by line) I figured out that the problem is on the Q_PROPERTY
related to the finished
function I wrote.
All the other functions such as running
and progress
are working perfectly and applied the same exact philosophy to the finished
function to notify the end of the calculation and, therefore, change the State
from A to B of the Text
.
What am I missing out in the Progressbar
that is keeping me from finishing the exercise?
Thanks for shedding light on this matter.
Upvotes: 0
Views: 309
Reputation: 2388
The problem could be that m_finished is initialized with true in your header:
int m_finished = true;
So when the signal is emitted after the computation is done, QML doesn't detect any changes because the variable is still true!
Try changing it to false before starting the computation. Also don't forget to emit the changed signal each time running or finished change value:
void ProgressBar::startComputation()
{
m_running = true;
emit runningChanged();
m_finished = false;
emit finishedChanged();
...
}
void ProgressBar::finishComputation()
{
m_finished = true;
emit finishedChanged();
m_running = false;
emit runningChanged();
}
EDIT:
The Problem is that finishComputation is never called! A possible solution would be to add a check in your updateProgress function:
void ProgressBar::updateProgress(int value)
{
m_progressValue = value;
emit progressChanged();
if (m_progressValue == 40)
finishComputation();
}
Upvotes: 2