PDA

View Full Version : A Stopwatch in qt GUI ?



020394
15th July 2013, 09:42
Hello all ,
I am trying to make a stopwatch for my GUI when i click the start button
I been Researching and tried out alot of examples in the internet.I tried to minus the the current time (InfusionTime)minus the time(CurrentTime) i click on the button by using.



void Infusion::GetDuration()
{
int x;
x=InfusionTime.secsTo(CurrentTime);
}


i also include

QTimer *duration= new QTimer(this);
connect(duration, SIGNAL(timeout()),this, SLOT(GetDuration()));
Stopwatch.start(); //QTime Stopwatch; in header file
duration->start(50);
to check for the number everytime.
But I think i am doing it wrong as whenever i click the button . I keep getting the current time which is not moving(eg. Time Stamp)


Can anyone help me ? Or maybe teach me another way to implement a stopwatch in my gui.
Thanks

Santosh Reddy
15th July 2013, 10:22
class StopWatch : public QWidget
{
Q_OBJECT
public:
explicit StopWatch(QWidget * parent = 0)
: QWidget(parent)
, mRunning(false)
, mStartTime()
, mLabel(new QLabel("0:0:0:0"))
{
QHBoxLayout * hBoxLayout = new QHBoxLayout(this);
QPushButton * startButton = new QPushButton("Start");
QPushButton * stopButton = new QPushButton("Stop");

hBoxLayout->addWidget(startButton);
hBoxLayout->addWidget(stopButton);
hBoxLayout->addWidget(mLabel);

connect(startButton, SIGNAL(clicked()), SLOT(start()));
connect(stopButton, SIGNAL(clicked()), SLOT(stop()));

startTimer(0);
}

public slots:
void start(void)
{
mStartTime = QDateTime::currentDateTime();
mRunning = true;
}

void stop(void)
{
mRunning = false;
}

protected:
void timerEvent(QTimerEvent *)
{
if(mRunning)
{
qint64 ms = mStartTime.msecsTo(QDateTime::currentDateTime());
int h = ms / 1000 / 60 / 60;
int m = (ms / 1000 / 60) - (h * 60);
int s = (ms / 1000) - (m * 60);
ms = ms - (s * 1000);
QString diff = QString("%1:%2:%3:%4").arg(h).arg(m).arg(s).arg(ms);
mLabel->setText(diff);
}
}

private:
bool mRunning;
QDateTime mStartTime;
QLabel * mLabel;
};

020394
15th July 2013, 11:06
Thank you Santosh Reddy,
I am able to show the stopwatch thanks to your help. Anyway , I realised that the void Stop(), really stop the whole timing and will be reset after i click again . is there anyway to like just resume .Is the anyway to beautify the label of the stop watch . Now when it is running , it is like 0.0.5.123, can i make it 00.00.05,123?
Thanks for your help again , really appreciate it

Added after 5 minutes:

Anyway , Regarding the codes , I was wondering whether the qint64 can be use in Linux? Because in the end i will be importing my codes into Kubuntu (Digi Esp). So wondering whether that code can be used in all platform ?

Santosh Reddy
15th July 2013, 11:10
I am able to show the stopwatch thanks to your help. Anyway , I realised that the void Stop(), really stop the whole timing and will be reset after i click again . is there anyway to like just resume .
Yes, you need to maintain a session time variable and keep adding the time to it so that the sum is retainted over the start-pause sessions


Is the anyway to beautify the label of the stop watch
Yes, you could use style sheets or just simply set the desired font using setFont()


Now when it is running , it is like 0.0.5.123, can i make it 00.00.05,123?
Yes, for that you will need to learn VUDOO :). Change QString("%1:%2:%3,%4")...

020394
15th July 2013, 11:23
[QUOTE=Santosh Reddy;247633]Yes, you need to maintain a session time variable and keep adding the time to it so that the sum is retainted over the start-pause sessions


Can You teach me a method how ? What i can think of is jus makiing a
QString a=ui->label->text();
But i dont it will work as I will have to Resume it to start counting . Anyway to do it ?

Santosh Reddy
15th July 2013, 12:06
class StopWatch : public QWidget
{
Q_OBJECT
public:
explicit StopWatch(QWidget * parent = 0)
: QWidget(parent)
, mRunning(false)
, mStartTime()
, mLabel(new QLabel("00:00:00,000"))
, mTotalTime(0)
, mStart(new QPushButton("Start"))
, mPause(new QPushButton("Pause"))
, mStop(new QPushButton("Stop"))
{
QGridLayout * gridLayout = new QGridLayout(this);

gridLayout->addWidget(mLabel, 0, 0, 1, 3);
gridLayout->addWidget(mStart, 1, 0, 1, 1);
gridLayout->addWidget(mPause, 1, 1, 1, 1);
gridLayout->addWidget(mStop, 1, 2, 1, 1);

connect(mStart, SIGNAL(clicked()), SLOT(start()));
connect(mPause, SIGNAL(clicked()), SLOT(pause()));
connect(mStop, SIGNAL(clicked()), SLOT(stop()));

QFont font("Arial", 24, QFont::Bold);
QPalette palette = mLabel->palette();
palette.setColor(QPalette::WindowText, Qt::blue);
mLabel->setPalette(palette);
mLabel->setFont(font);
gridLayout->setAlignment(mLabel, Qt::AlignCenter);

mStart->setEnabled(true);
mPause->setEnabled(false);
mStop->setEnabled(false);

startTimer(0);
}

public slots:
void start(void)
{
mStartTime = QDateTime::currentDateTime();
mRunning = true;
mStart->setEnabled(false);
mPause->setEnabled(true);
mStop->setEnabled(true);
}

void pause(void)
{
mStart->setEnabled(true);
mPause->setEnabled(false);
mStop->setEnabled(true);
timerEvent(new QTimerEvent(0));
mTotalTime += mSessionTime;
mRunning = false;
}

void stop(void)
{
mStart->setEnabled(true);
mPause->setEnabled(false);
mStop->setEnabled(false);
mTotalTime = 0;
mRunning = false;
}

protected:
void timerEvent(QTimerEvent *)
{
if(mRunning)
{
mSessionTime = mStartTime.msecsTo(QDateTime::currentDateTime());
qint64 time = mTotalTime + mSessionTime;
unsigned int h = time / 1000 / 60 / 60;
unsigned int m = (time / 1000 / 60) - (h * 60);
unsigned int s = (time / 1000) - (m * 60);
unsigned int ms = time - (s + ((m + (h * 60))* 60)) * 1000;
const QString diff = QString("%1:%2:%3,%4")
.arg(h, 2, 10, QChar('0'))
.arg(m, 2, 10, QChar('0'))
.arg(s, 2, 10, QChar('0'))
.arg(ms, 3, 10, QChar('0'));
mLabel->setText(diff);
}
}

private:
bool mRunning;
QDateTime mStartTime;
QLabel * mLabel;
qint64 mTotalTime;
qint64 mSessionTime;

QPushButton * mStart;
QPushButton * mPause;
QPushButton * mStop;
};

020394
15th July 2013, 12:49
Thanks again . And thanks for helping me with the "VUDOO" which u mention just now . From your codes
.arg(ms,3,10,QChar('0'));
I know the 3 is for the number of integer in the text . But i am unsure of the 10.Can you explain why we need to include that ?

Santosh Reddy
15th July 2013, 12:54
QString QString::arg(uint a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char( ' ' )) const
The a argument is expressed in base base, which is 10 by default and must be between 2 and 36. For bases other than 10, a is treated as an unsigned integer.

fieldWidth specifies the minimum amount of space that a is padded to and filled with the character fillChar. A positive value produces right-aligned text; a negative value produces left-aligned text.

If fillChar is '0' (the number 0, ASCII 48), the locale's zero is used. For negative numbers, zero padding might appear before the minus sign.

also there is small problem in the earlier code, here is the correction


void timerEvent(QTimerEvent *)
{
if(mRunning)
{
mSessionTime = mStartTime.msecsTo(QDateTime::currentDateTime());
qint64 time = mTotalTime + mSessionTime;
time *= 111;
unsigned int h = time / 1000 / 60 / 60;
unsigned int m = (time / 1000 / 60) - (h * 60);
unsigned int s = (time / 1000) - ((m + (h * 60))* 60); //<<<<<<<<<<<<<<<<<<<<<<
unsigned int ms = time - (s + ((m + (h * 60))* 60)) * 1000;
const QString diff = QString("%1:%2:%3,%4")
.arg(h, 2, 10, QChar('0'))
.arg(m, 2, 10, QChar('0'))
.arg(s, 2, 10, QChar('0'))
.arg(ms, 3, 10, QChar('0'));
mLabel->setText(diff);
}
}

020394
2nd September 2013, 11:51
Hey Sorry to make this thread alive again , I recently encountered a problem with the stopwatch . I let it run for a while just to make sure no errors occurs . The stopwatch is working perfectly fine but there seem to be an error after an Hour . The StopWatch became like this 1:39:1234. The sec hands shld be a 2 digit number but instead it becomes a 4 digit number . It is kinda wierd though as the Stopwatch is working perfectly fine until that happens

Santosh Reddy
2nd September 2013, 13:50
Did you take the corrected code from my previous post.

Anyway here it is again


class StopWatch : public QWidget
{
Q_OBJECT
public:
explicit StopWatch(QWidget * parent = 0)
: QWidget(parent)
, mRunning(false)
, mStartTime()
, mLabel(new QLabel("00:00:00,000"))
, mTotalTime(0)
, mStart(new QPushButton("Start"))
, mPause(new QPushButton("Pause"))
, mStop(new QPushButton("Stop"))
{
QGridLayout * gridLayout = new QGridLayout(this);

gridLayout->addWidget(mLabel, 0, 0, 1, 3);
gridLayout->addWidget(mStart, 1, 0, 1, 1);
gridLayout->addWidget(mPause, 1, 1, 1, 1);
gridLayout->addWidget(mStop, 1, 2, 1, 1);

connect(mStart, SIGNAL(clicked()), SLOT(start()));
connect(mPause, SIGNAL(clicked()), SLOT(pause()));
connect(mStop, SIGNAL(clicked()), SLOT(stop()));

QFont font("Arial", 24, QFont::Bold);
QPalette palette = mLabel->palette();
palette.setColor(QPalette::WindowText, Qt::blue);
mLabel->setPalette(palette);
mLabel->setFont(font);
gridLayout->setAlignment(mLabel, Qt::AlignCenter);

mStart->setEnabled(true);
mPause->setEnabled(false);
mStop->setEnabled(false);

startTimer(0);
}

public slots:
void start(void)
{
mStartTime = QDateTime::currentDateTime();
mRunning = true;
mStart->setEnabled(false);
mPause->setEnabled(true);
mStop->setEnabled(true);
}

void pause(void)
{
mStart->setEnabled(true);
mPause->setEnabled(false);
mStop->setEnabled(true);
timerEvent(new QTimerEvent(0));
mTotalTime += mSessionTime;
mRunning = false;
}

void stop(void)
{
mStart->setEnabled(true);
mPause->setEnabled(false);
mStop->setEnabled(false);
mTotalTime = 0;
mRunning = false;
}

protected:
void timerEvent(QTimerEvent *)
{
if(mRunning)
{
mSessionTime = mStartTime.msecsTo(QDateTime::currentDateTime());
qint64 time = mTotalTime + mSessionTime;
time *= 111;
unsigned int h = time / 1000 / 60 / 60;
unsigned int m = (time / 1000 / 60) - (h * 60);
unsigned int s = (time / 1000) - ((m + (h * 60))* 60);
unsigned int ms = time - (s + ((m + (h * 60))* 60)) * 1000;
const QString diff = QString("%1:%2:%3,%4")
.arg(h, 2, 10, QChar('0'))
.arg(m, 2, 10, QChar('0'))
.arg(s, 2, 10, QChar('0'))
.arg(ms, 3, 10, QChar('0'));
mLabel->setText(diff);
}
}

private:
bool mRunning;
QDateTime mStartTime;
QLabel * mLabel;
qint64 mTotalTime;
qint64 mSessionTime;

QPushButton * mStart;
QPushButton * mPause;
QPushButton * mStop;
};

020394
2nd September 2013, 18:49
Yea i followed the way you did it , just took away the adding of widget and the ms part . As i am using qt designer to add the buttons . The stopwatch is working perfectly fine just after the 1 hr 30min mark , something went wrong . I will counter check the code . Will update this post if there are still errors

020394
4th September 2013, 07:28
Ok , the problem is soved already , It seems that i did not copy the unsigned h part correctly . Thank you so much for the help Santoshb Reddy :)

CUTEE
22nd January 2015, 14:52
Hello, Santosh,

sorry to ask this, but how exactly can I get this code to run? I get lots of errors.

I know my question exposes huge deficit in most basic knowledge of the QT environment, however I need a cutom stopwatch next week :) So I was just googling for some code and found this.

I downloaded QT Creator and made a new project with the wizard, which generated three files: main.cpp, mainwindow.cpp and mainwindow.h

Where do I have to put your code to be able to run it?

Sorry for my ignorance, I will certainly dig deeper in near future, but I need a quick start right now. Yes, I understand what QT is, but I do not have experience in C++ - I speak some C, PHP, Python and web related things, so this is mainly about not understanding the formalities of the environment, I do indeed understand what your code does, but I have no clue how to accomodate the QT Creator to make it executable.

Thanks for your attention!
John