[gelöst] QTimer Countdown

Alles rund um die Programmierung mit Qt
Antworten
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

[gelöst] QTimer Countdown

Beitrag von Mani99 »

Hallo,

ich möchte einen countdown starten, habe aber probleme mit der realisierung, und zwar erstelle ich ein QTime objekt und möchte darstellen, das immer eine sekunde bei timeout() abgezogen wird

Aber es ist so, das bei timeout() die aktuelle uhrzeit in dem lcd feld dargestellt wird minus einer sekunde, obwohl ich QTime mit 10 sekunden initialisiere.

Kann mir jemand sagen was ich falsch mache?

Code: Alles auswählen

class MyApp : public QMainWindow
{
    Q_OBJECT

    public:
        explicit MyApp(QWidget *parent = 0);
        ~MyApp();

    private:
        Ui::MyApp *ui;
        QTimer *my_timer;
        QTime *c_time;

    public slots:
        void timerAction();

private slots:
    void on_btnStartStop_toggled(bool checked);
};

Code: Alles auswählen

MyApp::MyApp(QWidget *parent) : QMainWindow(parent), ui(new Ui::MyApp)
{
    ui->setupUi(this);

    my_timer = new QTimer(this);
    c_time = new QTime();
    c_time->setHMS(0,0,10,0);
    my_timer->setInterval(1000);

    connect(my_timer, SIGNAL(timeout()), this, SLOT(timerAction()));

    ui->lcdNumber->display(c_time->toString("hh:mm:ss"));
}

void MyApp::timerAction()
{
    my_timer->addSecs(-1)
    QTime new_time = my_timer->addSecs(c_time->elapsed()*-1);
    ui->lcdNumber->display(new_time.toString("hh:mm:ss"));

    /*
    if(new_time == QTime(0,0,0,0))
    {
        qDebug("Timer abgelaufen!");
        my_timer->stop();
    }*/
}

void MyApp::on_btnStartStop_toggled(bool checked)
{
    if(checked)
    {
        my_timer->start();
        c_time->start();
        ui->btnStartStop->setIcon(QIcon(QString::fromUtf8(":/btn/img/player_play.png")));
    }
    else
    {
        blindTimer->stop();
        ui->btnStartStop->setIcon(QIcon(QString::fromUtf8(":/btn/img/player_pause.png")));
    }
}

MyApp::~MyApp()
{
    delete ui;
}
Zuletzt geändert von Mani99 am 9. Februar 2011 16:11, insgesamt 1-mal geändert.
dontinelli
Beiträge: 146
Registriert: 22. September 2006 20:53

Beitrag von dontinelli »

Hast du mal in der Doku nachgeschaut, was folgende Zeile bewirkt:

Code: Alles auswählen

c_time->start();
Lässt du diese weg, sollte es wohl klappen.
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

Hi,

danke für die antwort, hat soweit fuktioniert, aber jetzt wird genau von den 10 sekunden 1 abgezogen und dann aktualisiert sich QLCDNumber nicht mehr!
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

1. kann der Code nicht kompilieren - QTimer hat keine Funktion addSecs()
2. QTime::elapsed() bringt keine Sekunden zurück - Doku
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

Danke für die antworten und hinweise.

Ich hab mir das jetz noch einmal angesehen, und weiß jetzt das QTime::elapsed() millisekunden zurückliefert. Aber so ganz weiß ich noch immer nicht wie eine stopp uhr erstellen kann.

Was mir bei meinen tests noch aufgefallen ist, die zeit läuft nicht konstant mit dem timer. Einmal laufen wirklich die sekunden, dann ein sprung um zwei sekunden, etc.

Ich weiß das das damit zusammenhängt, das sich die GUI neu zeichnen muss, und ich das mit ein paar processEvent() verbessern kann.

Wäre es event. sinnvoll das mit einem thread zu lösen?

Könnte mir jemand bitte einen tipp geben was noch falsch läuft?

Danke!

Im anhang befindet sich das testprogramm.

timertest.h

Code: Alles auswählen

#include <QMainWindow>
#include <QTime>
#include <QTimer>

namespace Ui {
    class TimerTest;
}

class TimerTest : public QMainWindow
{
    Q_OBJECT

public:
    explicit TimerTest(QWidget *parent = 0);
    ~TimerTest();

    QTime *startTime;
    QTime *runningTime;

    QTimer *myTimer;

private:
    Ui::TimerTest *ui;

    void init();

public slots:
    void myTimer_TimeOut();

private slots:
    void on_btnStartStop_toggled(bool checked);
};
timertest.cpp

Code: Alles auswählen

#include "timertest.h"
#include "ui_timertest.h"

TimerTest::TimerTest(QWidget *parent) : QMainWindow(parent), ui(new Ui::TimerTest)
{
    ui->setupUi(this);

    init();
}

void TimerTest::init()
{
    startTime = new QTime(0,0,30,0);
    runningTime = new QTime();

    myTimer = new QTimer(this);
    myTimer->setInterval(1000);

    connect(myTimer, SIGNAL(timeout()), this, SLOT(myTimer_TimeOut()));

    ui->lcdNumber->display(startTime->toString("hh:mm:ss"));
}

void TimerTest::myTimer_TimeOut()
{
    QTime time_out = startTime->addMSecs(runningTime->elapsed()*-1);
    ui->lcdNumber->display(time_out.toString("hh:mm:ss"));

    if(time_out == QTime(0,0,0,0))
        myTimer->stop();
}

void TimerTest::on_btnStartStop_toggled(bool checked)
{
    if(checked)
    {
        startTime->start();
        myTimer->start();
    }
    else
    {
        myTimer->stop();
    }
}

TimerTest::~TimerTest()
{
    delete ui;
}

Dateianhänge
TimerTest.zip
(2.28 KiB) 162-mal heruntergeladen
dontinelli
Beiträge: 146
Registriert: 22. September 2006 20:53

Beitrag von dontinelli »

Also ich denke, du machst das reichlich kompliziert. Weshalb brauchst du startTime und runningTime? Ich würde das in etwa so machen (quick and dirty, d.h. ungetestet):

header:

Code: Alles auswählen

#include <QMainWindow>
#include <QTime>
#include <QTimer>

namespace Ui {
    class TimerTest;
}

class TimerTest : public QMainWindow
{
    Q_OBJECT

public:
    explicit TimerTest(QWidget *parent = 0);
    ~TimerTest();

    QTime *startTime;

    QTimer *myTimer;

private:
    Ui::TimerTest *ui;

    void init();

public slots:
    void myTimer_TimeOut();

private slots:
    void on_btnStartStop_toggled(bool checked);
}; 
cpp

Code: Alles auswählen

#include "timertest.h"
#include "ui_timertest.h"

TimerTest::TimerTest(QWidget *parent) : QMainWindow(parent), ui(new Ui::TimerTest)
{
    ui->setupUi(this);

    init();
}

void TimerTest::init()
{
    startTime = new QTime(0,0,30,0);

    myTimer = new QTimer(this);
    myTimer->setInterval(1000);

    connect(myTimer, SIGNAL(timeout()), this, SLOT(myTimer_TimeOut()));

    ui->lcdNumber->display(startTime->toString("hh:mm:ss"));
}

void TimerTest::myTimer_TimeOut()
{
    startTime->addMSecs(-1000);
    ui->lcdNumber->display(startTime.toString("hh:mm:ss"));

    if(startTime == QTime(0,0,0,0))
        myTimer->stop();
}

void TimerTest::on_btnStartStop_toggled(bool checked)
{
    if(checked)
    {
        myTimer->start();
    }
    else
    {
        myTimer->stop();
    }
}

TimerTest::~TimerTest()
{
    delete ui;
}
Musst dir halt immer bewusst sein, dass je nach Systemlast der QTimer nicht sehr genau ist. Wenn's etwas genauer sein sollte, würde ich den Interval herunter setzen und die Differenz berechnen (z.b. hiermit).

LG
Dontinelli
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

Hi,

danke für die antwort, nur folgendes kann nicht funktionieren:

Code: Alles auswählen

void TimerTest::myTimer_TimeOut()
{
    startTime->addMSecs(-1000);
    ui->lcdNumber->display(startTime.toString("hh:mm:ss"));

    if(startTime == QTime(0,0,0,0))
        myTimer->stop();
} 

Code: Alles auswählen

startTime->addMSecs(-1000);
zieht 1000 msecs ab und gibt ein const QTime zurück. Und bei jedem timeout() werden wieder von den anfänglichen 30 sekunden 1 sekunde abgezogen --> d.h. läuft ewig!

Code: Alles auswählen

if(startTime == QTime(0,0,0,0))
Das wird glaub ich so auch nicht hin hauen, weil startTime ein pointer ist!
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Abgesehen davon dass man einfach einen integer mit 10 initialisieren und bei jedem timeout() um 1 verringern könnte was das ganze wesentlich vereinfacht...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Mani99
Beiträge: 244
Registriert: 15. April 2009 10:46
Wohnort: München

Beitrag von Mani99 »

Hi,

danke, die einfache variante funktioniert ganz gut! :D
Antworten