Progress bar function not looping - c++

Almost done with that application I've been working on BUT, now I have one more problem. I created a QProgressBar and connected it to a QTimer. It goes up one percent per second but surpasses the actual progress. I have yet to program in the former however I set up the timer to go up one every second. Here is my problem the progress bar goes up to one percent then stops. It hits the if statement every second I know that, but it doesn’t go any higher then 1%.
Edit:
Sorry meant to add the code.
#include "thiwindow.h"
#include "ui_thiwindow.h"
#include <QProcess>
#include <fstream>
#include <sstream>
int ModeI;
ThiWindow::ThiWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ThiWindow)
{
ui->setupUi(this);
std::ifstream ModeF;
ModeF.open ("/tmp/Mode.txt");
getline (ModeF,ModeS);
std::stringstream ss(ModeS);
ss >> ModeI;
ModeF.close();
SecCount = new QTimer(this);
Aproc = new QProcess;
proc = new QProcess;
connect(SecCount, SIGNAL(timeout()), this, SLOT(UpdateProcess()));
connect(Aproc, SIGNAL(readyRead()), this, SLOT(updateText()));
connect(proc, SIGNAL(readyRead()), this, SLOT(updateText()));
SecCount->start(1000);
if (ModeI==1)
Aproc->start("gksudo /home/brooks/Documents/Programming/AutoClean/LPB.pyc");
else
proc->start("/home/brooks/Documents/Programming/AutoClean/LPB.pyc");
ui->progressBar->setValue(0);
}
ThiWindow::~ThiWindow()
{
delete ui;
}
void ThiWindow::updateText()
{
if (ModeI==1){
QString appendText(Aproc->readAll());
ui->textEdit->append(appendText);}
else{
QString appendText(proc->readAll());
ui->textEdit->append(appendText);}
}
void ThiWindow::UpdateProcess()
{
SecCount->start(1000);
int Count=0;
float Increments;
int Percent_limit;
if (ModeI==1){
Increments = 100/5;
Percent_limit = Increments;
if (Count<Percent_limit) {
Count += 1;
ui->progressBar->setValue(Count);
}
}
}
If you need more let me know.
Thanks,
Brooks Rady

You are always incrementing zero. int Count=0; This have to be removed from this function and moved for example to constructor where timer is started and declare it in header file ( shown in last two code snipets )
void ThiWindow::UpdateProcess()
{
SecCount->start(1000);
int Count=0; // Count is 0
float Increments;
int Percent_limit;
if (ModeI==1){
Increments = 100/5;
Percent_limit = Increments;
if (Count<Percent_limit) {
Count += 1; // Count is 0 + 1
ui->progressBar->setValue(Count); // progressBar is 1
}
}
}
You have to declare Count in header file. Count will be stored as long as ThiWindows exists. Not only for a few miliseconds in your example ( Count was destroyed when your UpdateProccess functions finish and then recreated again when it was called again )
class ThiWindow : public QMainWindow {
Q_OBJECT
public:
// whatever you have
private:
int Count;
}
Count should be initialized before Timer starts
SecCount = new QTimer(this);
Aproc = new QProcess;
proc = new QProcess;
connect(SecCount, SIGNAL(timeout()), this, SLOT(UpdateProcess()));
connect(Aproc, SIGNAL(readyRead()), this, SLOT(updateText()));
connect(proc, SIGNAL(readyRead()), this, SLOT(updateText()));
Count = 0; // << move Count variable here
SecCount->start(1000);

Related

QProgressBar updates as function progress

How to initializa the operation of QProgressBar, I already declare her maximum, minimum, range and values.
I want to assimilate the progress of QProgressBar with the "sleep_for" function.
Current code:
void MainPrograma::on_pushCorre_clicked()
{
QPlainTextEdit *printNaTela = ui->plainTextEdit;
printNaTela->moveCursor(QTextCursor::End);
printNaTela->insertPlainText("corrida iniciada\n");
QProgressBar *progresso = ui->progressBar;
progresso->setMaximum(100);
progresso->setMinimum(0);
progresso->setRange(0, 100);
progresso->setValue(0);
progresso->show();
WORD wEndereco = 53606;
WORD wValor = 01;
WORD ifValor = 0;
EscreveVariavel(wEndereco, wValor);
//How to assimilate QProgressBar to this function:
std::this_thread::sleep_for(std::chrono::milliseconds(15000));
//StackOverFlow help me please
EscreveVariavel(wEndereco, ifValor);
use a QTimer
and in the slot update the value of the progressbar
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
t = new QTimer(this);
t->setSingleShot(false);
c = 0;
connect(t, &QTimer::timeout, [this]()
{ c++;
if (c==100) {
c=0;
}
qDebug() << "T...";
ui->progressBar->setValue(c);
});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
t->start(100);
}
I'm not sure about your intentions with such sleep: are you simulating long wait? do you have feedback about progress during such process? Is it a blocking task (as in the example) or it will be asynchronous?
As a direct answer (fixed waiting time, blocking) I think it is enough to make a loop with smaller sleeps, like:
EscreveVariavel(wEndereco, wValor);
for (int ii = 0; ii < 100; ++ii) {
progresso->setValue(ii);
qApp->processEvents(); // necessary to update the UI
std::this_thread::sleep_for(std::chrono::milliseconds(150));
}
EscreveVariavel(wEndereco, ifValor);
Note that you may end waiting a bit more time due to thread scheduling and UI refresh.
For an async task you should pass the progress bar to be updated, or some kind of callback that does such update. Keep in mind that UI can only be refreshed from main thread.

Implementing QTimer to execute a function for a given time

I have a function that should send data to a raspberry pi for a given period of time depending on the parameter.
//headerfiles
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QUdpSocket udpSocket;
// movement Timer
QTimer* movementTimer;
private slots:
void sendDatagram(); // Sends to the RaspberryPi
void processFrameAndUpdateGUI();
void turnLeft(double time);
void turnRight(double time);
void goStraight(double time);
void MovRobot();
};
// MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
movementTimer = new QTimer(this);
//send datagram sends data to tehe PI.
connect(movementTimer, SIGNAL(timeout()), this, SLOT(sendDatagram()));
MovRobot(); // MovRobot() function
}
// controls robot to turn left for specified time
void TurnLeft(double time)
{
s = 1; // sets the value to be sent to the PI.
movementTimer->setInterval(time);
movementTimer->setSingleShot(true);
movementTimer->start();
}
//sendDatagram() slot
void MainWindow::sendDatagram() {
QString datagramOutput = "start," +
QString::number(w) + ',' + QString::number(a) + ',' +
QString::number(s) + ',' + QString::number(d) + ',' +
QString::number(ui->motorSpeedSlider->value()) + ',' +
QString::number(dispenserSignal);
datagramOutput += ",end";
QByteArray datagram;
QDataStream out(&datagram,QIODevice::WriteOnly);
out << datagramOutput;
udpSocket.writeDatagram(datagram,QHostAddress("192.168.0.104"),12345);
}
//MovRobot Function;
void MainWindow :: MovRobot() {
if (ui->pushButton_3->isChecked()) {
MapArea(); // This function maps the area....
// final_plan is a vector<Point2i> that stores positions on the map for
// the robot to move to
for (int i = 0; i < final_plan.size(); i++) {
for (int j = final_plan.size() - 1; j>=0; j--) {
do {
Mat src;
bool bsuccess = cap.read(src);
if (!bsuccess) {
ui->label_34->setText("Status: Can't read frame.");
ui->pushButton_3->setChecked(0);
}
GetRobotPosition(src);
// AngleToGoal calculates the angle of the robot relative
// to the final goal.
double tempAngle = AngletoGoal(final_plan[i][j]);
if (tempAngle>=0) {
turnLeft(TimeToTurn(tempAngle));
}
else {
turnRight(TimeToTurn(tempAngle));
}
double tempDistance = DistancetoGoal(final_plan[i][j]);
goStraight(tempDistance);
} while (DistancetoGoal(final_plan[i][j])<20);
}
}
}
}
The timer should only send the data over to the PI for the duration it in time sendDatagram is the function that sends the data over to the Pi. Is there anything I'm missing here. The timer doesn't start inside the TurnLeft() function and doesn't run at all. Am I going about this wrong?
EDIT: 13/03/2016:
My apologies for the late reply. I've been quite sick the past few days. I've added the relevant parts of the code. MovRobot() is the main function responsible for the movement and this is called in the constructor for MainWindow. I have debugged and stepped through the program and yes, TurnLeft() is called. However, the sendDatagram() slot doesn't actually send anything in the function. To confirm sendDatagram() was actually working, I used another timer to continuously send information to the PI on the robot to control the arm.
// Header File
QTimer* tmrTimer;
private slot:
void processFrameAndUpdateGUI();
// MainWindow Constructor:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
connect(tmrTimer, SIGNAL(timeout()), this, SLOT(processFrameAndUpdateGUI()));
tmrTimer->start(10);
}
void MainWindow::processFrameAndUpdateGUI() {
sendDatagram();
}
The sendDatagram() slot is pretty much the same with the exception of me changing what values are being sent to the PI and this seems to work perfectly.
However, my original problem is, I would like to send the data to the robot with for a specified amount of time as that makes the robot turn x degrees. This is why I've made movementTimer() single shot.
Stepping through my program, I know this line is called within my TurnLeft function.
movementTimer->start();
but the sendDatagram() slot itself doesn't actually send anything to the PI.
Based on your code. The program never called TurnLeft(). So the timer never started. It will be better to start the timer in constrator instead.
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(MySlot()));
timer->start(1000);
I would try setting the timer to start in the constructor.

C++/Qt Threads error without using threads

I am using a special form of the qt framework and it will look a bit complicated. But do not worry. It is the same as the original framework of qt. (And no I can't change it)
My intention of this program is to load a table in a tableview from the ui. The tableview should have as many rows and text as files that are in a directory. I take all files in the directory and put an filter on them. Only the selected one are counted and used afterwards.
And now to my problem:
I want to display the table like an Excel table: it should highlight the cell where my cursor (in my example it is an counter which goes up and down) stands right now (Currently I do not have a cursor, so I have to use a self-created "cursor". You will see it in the program what I mean).
I use a QStandardItemModel to display it and a QStandardItem to define it.
Because I want to change the color of the cells I use an QStandardItem array to save the cells one by one.
form.h:
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QTextTable>
#include <QFont>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QString>
#include <QStringList>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QBrush>
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
void my_setCFGFromDirectory();
void my_Highlighted(int, bool);
void my_loadCFG(int);
private:
Ui::Form *ui;
QFile file;
QTextStream textstream;
QDir directory;
QString filename;
QStringList stringlist;
QStringList filter;
QStandardItemModel *model;
QStandardItem *tableitem;
QStandardItem* pointerTableitem[];
int max_files;
int w_counter;
bool check1;
bool check2;
bool check3;
};
#endif // FORM_H
and the
form.cpp
#include "form.h"
#include "ui_form.h"
#include "rbobject.h"
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
}
Form::~Form()
{
delete ui;
}
void Form::my_Highlighted(int actual_count, bool modus){
if(modus == 1){
w_counter = 0;
while(w_counter < max_files){
if(w_counter == actual_count){
pointerTableitem[w_counter]->setBackground(QBrush(QColor(130,180,255)));
}
w_counter++;
}
}
else
{
w_counter = 0;
while(w_counter < max_files){
pointerTableitem[w_counter]->setBackground(QBrush(QColor(255,255,255)));
w_counter++;
}
}
}
void Form::my_setCFGFromDirectory(){
directory.setPath("/etc/rosenbauer/CFG-Files");
filter << "*_CFG.ini";
stringlist = directory.entryList(filter); //takes the selected files and wriths them in a filelist
max_files = stringlist.count(); //Counts the selected files
pointerTableitem [max_files];
memset(pointerTableitem, 0, max_files*sizeof(int)); //The compiler can not see how many elements should be in the array at the time he constructs the array.
//So you have to use this to tell the compiler, how many elements it should create
model = new QStandardItemModel(max_files, 1, this); //Rows , Columns , this
model->setHorizontalHeaderItem(0, new QStandardItem(QString("CFG-Files"))); //Column , QStandarditem...name
for(w_counter = 0; w_counter != max_files; w_counter++){
tableitem = new QStandardItem();
tableitem->setBackground(QBrush(QColor(255,255,255)));
tableitem->setText(QString(stringlist[w_counter])); //Wriths text in the cell
qDebug() << tableitem->text();
pointerTableitem[w_counter] = tableitem; //Stacks the tableitems in a filelist
model->setItem(w_counter, 0, tableitem); //Row, Column , tableitem...text
}
w_counter = 0;
//pointerTableitem[2]->setBackground(QBrush(QColor(130,180,255))); //Test
ui->TableConfig->setModel(model); //Sets the table into the UI
}
void Form::my_loadCFG(int file_position){
check1 = 0;
check2 = 0;
directory.setPath("/etc/rosenbauer/etc/rosenbauer");
check1 = directory.remove("SA008_890560-001_CFG.ini");
check2 = directory.remove("reparsed/SA008_890560-001_CFG.ini_reparsed");
if(check1 && check2){
filename = pointerTableitem[file_position]->text();
check3 = QFile::copy("/etc/rosenbauer/CFG-Files/"+filename, "/etc/rosenbauer/SA008_890560-001_CFG.ini");
if(!check3){
qDebug() << "Error! Could not copy new CFG-file into directory";
}
}
else
{
qDebug() << "Error! Could not delete running CFG-file(s) from directory";
}
}
The main header rbobject45000.h
#ifndef RbObject45000_H
#define RbObject45000_H
#include "rbobject.h"
#include "form.h"
class RbObject45000 : public RbObject{
public:
RbObject45000();
RbObject45000(qint32 rbObjectId, RDataObject *dataobject, qint32 style, QObject *parent = 0);
RbObject45000(qint32 rbObjectId, qint32 style, qint32 prio, QObject *parent);
bool entered_ui;
bool entered_key;
short counter;
short w_count;
short delay_count;
short max_files;
short begin;
short end;
Form *f;
void exec();
~RbObject45000();
};
#endif // RbObject45000_H
And this is the main:
rbobject45000.cpp
RbObject45000::RbObject45000(qint32 rbObjectId, qint32 style, qint32 prio, QObject *parent):
RbObject(rbObjectId, style, prio, parent){
entered_ui = 0;
entered_key = 0;
counter = 0;
w_count = 1; //... whilecounter
delay_count = 0; //... delay for the deadtime
max_files = 0;
begin = 0;
end = 0;
f= new Form(); //f...name of the displayed UI
}
void RbObject45000::exec(){
//Opens the file on the display
if(getKey(RB_KEY_9) && getKey(RB_KEY_7) && entered_ui ==0){
f->show();
entered_ui = 1;
// Geting the Files from Directory
f->my_setCFGFromDirectory();
}
// Prescind them file in the table
if(entered_ui == 1 && delay_count == 2){
if(getKey(RB_KEY_7)){
counter--;
entered_key = 1;
if(counter < 0){
counter = 0;
}
}
else if(getKey(RB_KEY_9)){
counter++;
entered_key = 1;
if(counter > max_files){
counter = max_files;
}
}
if(entered_key == 1){
while(w_count <= max_files){
f->my_Highlighted(w_count, 0); //Cell , not highlighted
w_count++;
}
w_count = 0;
f->my_Highlighted(counter,1); //Cell , highlighted
entered_key = 0;
}
delay_count = 0;
}
else if(delay_count == 2){ //if delay == 2 and nobody hit a button
delay_count = 0;
}
delay_count++;
//Load the coosen file as programm-config in
if(entered_ui == 1){
if(getKey(RB_KEY_8)){
f->my_loadCFG(counter);
}
}
}
(RB_KEY_7-9 are buttons of a hardware-module, only have to click them)
So if I do it like this, the program will compile and start. If I press the buttons and the program run into the my_setCFGFromDirectory() it exits the window and stop running, but if the QStandardItem pointerTableitem is declared in the my_setCFGFromDirectory() everything works fine (but the pointerTableitem needs to be private).
The errors I get are:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is Form(0x167498), parent's thread is QThread(0x1414e8), current thread is QThread(0x15d2d8)
Segmentation fault
It appears to say I use a thread (I'm sure I don't). But I know it has something to do with pointerTableitem and the declaration in the header and cpp.
If I'm not mistaken the problem lies here:
model = new QStandardItemModel(max_files, 1, this);
You try to create a QStandardItemModel passing your Form instance this as a parent, the form was created on the main thread, this call apparently happens on another thread (the edits you made were not enough, it is still unclear if RbObject inherits QThread but you could check that yourself) and thus the error message.
Why not call the function on the main thread? Instead of doing this
f->show();
entered_ui = 1;
// Geting the Files from Directory
f->my_setCFGFromDirectory();
in a different thread, make a slot/signal pair for the Form class, put this code in the slot and fire the connected signal from RbObject45000::exec(). It is not correct to do UI manipulation from a non-UI trhead.

Refreshing with repaint() stops working

Today I encountered a problem with repaint() function from QT libraries. Long story short, I got a slot where I train my neural network using BP algorithm. I had tested the whole algorithm in console and then wanted to move it into GUI Application. Everything works fine except refreshing. Training of neural networks is a process containing a lot of computations, which are made in bp_alg function (training) and licz_mse function (counting a current error). Variable ilosc_epok can be set up to 1e10. Therefore the whole process may last even several hours. Thats why I wanted to display a current progress after each 100000 epochs (the last if contition). wyniki is an object of QTextEdit class used for displaying the progress. Unfortunately, repaint() doesnt work as intended. At the beginning it refreshes wyniki in GUI, but after some random time it stops working. When the external loop is finished, it refreshes once again showing all changes.
I tried to change frequency of refreshing, but sooner or later it always stops (unless the whole training process stops early enough because of satisfying the break condition). It looks like at some moment of time the application decides to stop refreshing because of too many computations. Imo it shouldnt happen. I was looking for a solution among older questions and managed to solve the problem when I used qApp->processEvents(QEventLoop::ExcludeUserInputEvents); instead of wyniki->repaint();. However, Im still curious why repaint() stops working just like that.
Below I paste a part of the code with the problematic part. Im using QT Creator 2.4.1 and QT Libraries 4.8.1 if it helps.
unsigned long int ile_epok;
double mse_w_epoce;
for (ile_epok=0; ile_epok<ilosc_epok; ile_epok++) { //external loop of training
mse_w_epoce = 0;
for (int i=0; i<zbior_uczacy_rozmiary[0]; i++) { //internal loop of training
alg_bp(zbior_uczacy[i], &zbior_uczacy[i][zbior_uczacy_rozmiary[1]]);
mse_w_epoce += licz_mse(&zbior_uczacy[i][zbior_uczacy_rozmiary[1]]);
}
//checking break condition
if (mse_w_epoce < warunek_stopu) {
wyniki->append("Zakończono uczenie po " + QString::number(ile_epok) + " epokach, osiągając MSE: " + QString::number(mse_w_epoce));
break;
}
//problematic part
if ((ile_epok+1)%(100000) == 0) {
wyniki->append("Uczenie w toku, po " + QString::number(ile_epok+1) + " epokach MSE wynosi: " + QString::number(mse_w_epoce));
wyniki->repaint();
}
}
You're blocking your GUI thread, so repaints will not work, it's just plainly bad design. You're never supposed to block the GUI thread.
If you insist on doing the work in the GUI thread, you must forcibly chop the work into small chunks and return to the main event loop after each chunk. Nested event loops are evil, so don't even think you'd want one. All this has a bad code smell, so stay away.
Alternatively, simply move your computation QObject to a worker thread and do the work there.
The code below demonstrates both techniques. It's easy to notice that the chopping-up-of-work requires to maintain loop state inside of the worker object, not merely locally in the loop. It's messier, the code smells bad, again - avoid it.
The code works under both Qt 4.8 and 5.1.
//main.cpp
#include <QApplication>
#include <QThread>
#include <QWidget>
#include <QBasicTimer>
#include <QElapsedTimer>
#include <QGridLayout>
#include <QPlainTextEdit>
#include <QPushButton>
class Helper : private QThread {
public:
using QThread::usleep;
};
class Trainer : public QObject {
Q_OBJECT
Q_PROPERTY(float stopMSE READ stopMSE WRITE setStopMSE)
float m_stopMSE;
int m_epochCounter;
QBasicTimer m_timer;
void timerEvent(QTimerEvent * ev);
public:
Trainer(QObject *parent = 0) : QObject(parent), m_stopMSE(1.0) {}
Q_SLOT void startTraining() {
m_epochCounter = 0;
m_timer.start(0, this);
}
Q_SLOT void moveToGUIThread() { moveToThread(qApp->thread()); }
Q_SIGNAL void hasNews(const QString &);
float stopMSE() const { return m_stopMSE; }
void setStopMSE(float m) { m_stopMSE = m; }
};
void Trainer::timerEvent(QTimerEvent * ev)
{
const int updateTime = 50; //ms
const int maxEpochs = 5000000;
if (ev->timerId() != m_timer.timerId()) return;
QElapsedTimer t;
t.start();
while (1) {
// do the work here
float currentMSE;
#if 0
for (int i=0; i<zbior_uczacy_rozmiary[0]; i++) { //internal loop of training
alg_bp(zbior_uczacy[i], &zbior_uczacy[i][zbior_uczacy_rozmiary[1]]);
currentMSE += licz_mse(&zbior_uczacy[i][zbior_uczacy_rozmiary[1]]);
}
#else
Helper::usleep(100); // pretend we're busy doing some work
currentMSE = 2E4/m_epochCounter;
#endif
// bail out if we're done
if (currentMSE <= m_stopMSE || m_epochCounter >= maxEpochs) {
QString s = QString::fromUtf8("Zakończono uczenie po %1 epokach, osiągając MSE: %2")
.arg(m_epochCounter).arg(currentMSE);
emit hasNews(s);
m_timer.stop();
break;
}
// send out periodic updates
// Note: QElapsedTimer::elapsed() may be expensive, so we don't call it all the time
if ((m_epochCounter % 128) == 1 && t.elapsed() > updateTime) {
QString s = QString::fromUtf8("Uczenie w toku, po %1 epokach MSE wynosi: %2")
.arg(m_epochCounter).arg(currentMSE);
emit hasNews(s);
// return to the event loop if we're in the GUI thread
if (QThread::currentThread() == qApp->thread()) break; else t.restart();
}
m_epochCounter++;
}
}
class Window : public QWidget {
Q_OBJECT
QPlainTextEdit *m_log;
QThread *m_worker;
Trainer *m_trainer;
Q_SIGNAL void startTraining();
Q_SLOT void showNews(const QString & s) { m_log->appendPlainText(s); }
Q_SLOT void on_startGUI_clicked() {
QMetaObject::invokeMethod(m_trainer, "moveToGUIThread");
emit startTraining();
}
Q_SLOT void on_startWorker_clicked() {
m_trainer->moveToThread(m_worker);
emit startTraining();
}
public:
Window(QWidget *parent = 0, Qt::WindowFlags f = 0) :
QWidget(parent, f), m_log(new QPlainTextEdit), m_worker(new QThread(this)), m_trainer(new Trainer)
{
QGridLayout * l = new QGridLayout(this);
QPushButton * btn;
btn = new QPushButton("Start in GUI Thread");
btn->setObjectName("startGUI");
l->addWidget(btn, 0, 0, 1, 1);
btn = new QPushButton("Start in Worker Thread");
btn->setObjectName("startWorker");
l->addWidget(btn, 0, 1, 1, 1);
l->addWidget(m_log, 1, 0, 1, 2);
connect(m_trainer, SIGNAL(hasNews(QString)), SLOT(showNews(QString)));
m_trainer->connect(this, SIGNAL(startTraining()), SLOT(startTraining()));
m_worker->start();
QMetaObject::connectSlotsByName(this);
}
~Window() {
m_worker->quit();
m_worker->wait();
delete m_trainer;
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
return a.exec();
}
#include "main.moc"

QTime QTimer timeout() driven Stopwatch has high CPU usage

In my game I need a stopwatch to measure and show the elapsed time.
For this purpose I made a simple widget:
ZuulStopwatchWidget::ZuulStopwatchWidget(QWidget *parent) :
QWidget(parent)
{
num = new QLCDNumber(this); // create the display
num->setDigitCount(9);
time = new QTime();
time->setHMS(0,0,0,0); // set the time
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(showTime()));
i=0;
QString text = time->toString("hh:mm:ss");
num->display(text);
//num->setStyleSheet("* { background-color:rgb(199,147,88);color:rgb(255,255,255); padding: 7px}}");
num->setSegmentStyle(QLCDNumber::Flat); //filled flat outline
//setStyleSheet("* { background-color:rgb(236,219,187)}}");
layout = new QVBoxLayout(this);
layout->addWidget(num);
setMinimumHeight(70);
}
ZuulStopwatchWidget::~ZuulStopwatchWidget()
{
// No need to delete any object that has a parent which is properly deleted.
}
void ZuulStopwatchWidget::resetTime()
{
time->setHMS(0,0,0);
QString text = time->toString("hh:mm:ss");
num->display(text);
i=0;
stopTime();
}
void ZuulStopwatchWidget::startTime()
{
//flag=0;
timer->start(1);
}
void ZuulStopwatchWidget::stopTime()
{
timer->stop();
}
void ZuulStopwatchWidget::showTime()
{
QTime newtime;
//if(flag==1)
//i=i-1;
i=i+1;
newtime=time->addMSecs(i);
QString text = newtime.toString("mm:ss:zzz");
num->display(text);
}
But when I run my game the CPU usage is at about 13% on a 2,5Ghz i5. I know this is not problematic but it sure is ridiculous for a stupid clock.
Am I doing it completely wrong or is this common practice ?!
Many thanks in advance.
Start(1) sets the timer to trigger every millisecond
You then want to format a string and print it on the screen 16times faster than the screen is probably updating anyway