Russian Qt Forum

Qt => Общие вопросы => Тема начата: Noir от Июнь 07, 2009, 03:52



Название: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 03:52
Добрый день!

подскажите, пожалуйста, как прикрутить будильник в данной программе? перепробовал разные варианты, пытался всунуть QTimer::singleshot в метод getAlarmTime, но, однако, не получается :( По идее, нужна ежесекундная проверка на соответствие текущего времени заданному пользователем, но никак не могу додуматься, как это реализовать ...

widget.cpp
Код:
#include <QtGui>
#include "widget.h"

void Timer::updateTime()
{
    QTime time = QTime::currentTime();
    QString text = time.toString("hh:mm");
    lcd->display(text);
}

void Timer::playAlarm()
{
    QMessageBox::information(this, "Alarm", "Good Morning");
    // добавить воспроизведение мелодии
}

void Timer::getAlarmTime()
{
    bool OK;
    int hours = QInputDialog::getInt(this, "Input Hours",
                                 "Hour: ", 12, 0, 23, 1, &OK);

    int minutes = QInputDialog::getInt(this, "Input Minutes",
                                 "Minutes: ", 30, 0, 59, 1, &OK);
}

Timer::Timer()
{
    timer = new QTimer;

    set = new QPushButton("Set");
    quit = new QPushButton("Quit");

    set->setMinimumSize(160, 20);
    quit->setMinimumSize(160, 20);

    lcd = new QLCDNumber;
    lcd->setSegmentStyle(QLCDNumber::Flat);
    lcd->setFrameStyle(2);
    lcd->setMinimumSize(160, 50);

    layout = new QVBoxLayout;

    layout->setMargin(10);
    layout->setSpacing(10);

    layout->addWidget(lcd);
    layout->addWidget(set);
    layout->addWidget(quit);

    this->setLayout(layout);

    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(updateTime()));
    timer->start(500);

    updateTime();

    QObject::connect(quit, SIGNAL(clicked()),
                     qApp, SLOT(quit()));

    QObject::connect(set, SIGNAL(clicked()),
                     this, SLOT(getAlarmTime()));
}

PS. Да, исполнение задания времени будильника крайне халтурно, но ничего не поделать, я слишком новичок..


Название: Re: Вопрос по реализации будильника в программе
Отправлено: ритт от Июнь 07, 2009, 04:55
слабенько, слабенько...не вижу даже установки таймера.
а в остальном - всё довольно примитивно - я бы сделал циклический таймер и по таймауту сравнивал бы текущее время с предустаноленным. таким макаром в будущем можно завести множество будильников на одном таймере.
секундный таймаут имело бы устанавливать только для ежесекундного обновления счётчика (или часов); либо же можно ограничиться интервалом порядка, скажем, 10-20 секунд...


Название: Re: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 06:31
слабенько, слабенько...не вижу даже установки таймера.
а в остальном - всё довольно примитивно - я бы сделал циклический таймер и по таймауту сравнивал бы текущее время с предустаноленным. таким макаром в будущем можно завести множество будильников на одном таймере.
секундный таймаут имело бы устанавливать только для ежесекундного обновления счётчика (или часов); либо же можно ограничиться интервалом порядка, скажем, 10-20 секунд...

Спасибо за ответ

На самом деле, делал уже вот так:
Код:
void Timer::playAlarm()
{
    QMessageBox::information(this, "Alarm", "Good Morning");
    // добавить воспроизведение мелодии
}

void Timer::getAlarmTime()
{
    bool OK;
    int alarm_hour = QInputDialog::getInt(this, "Input Hours",
                                 "Hour: ", 12, 0, 23, 1, &OK);

    int alarm_minute = QInputDialog::getInt(this, "Input Minutes",
                                 "Minutes: ", 30, 0, 59, 1, &OK);

    QTime qtime_time = QTime::currentTime();

    QString qstring_hour = qtime_time.toString("hh");
    QString qstring_minute = qtime_time.toString("mm");

    int current_hour = qstring_hour.toInt();
    int current_minute = qstring_hour.toInt();

    int delay_hour;

    if (current_hour > alarm_hour)
    {
        delay_hour = ((24 - current_hour) + alarm_hour);
    } else if ((current_hour == alarm_hour) && (current_minute < alarm_minute))
    {
        delay_hour = 0;
    } else if ((current_hour == alarm_hour) && (current_minute > alarm_minute))
    {
        delay_hour = 23;
    } else
        delay_hour = (alarm_hour - current_hour);

    int delay_minute;

    if (current_minute > alarm_minute)
    {
        delay_minute = ((60 - current_minute) + alarm_minute);
    } else
    {
        delay_minute = (alarm_minute - current_minute);
    }

    int delay = (((alarm_hour * 3600) + (alarm_minute * 60)) * 1000);

    QTimer::singleShot(delay, this, SLOT(playAlarm()));
}

Но, по окончанию работы таймера слот playAlarm() никак не хочет вызываться. Не пойму совершенно, что не так =\


Название: Re: Вопрос по реализации будильника в программе
Отправлено: lit-uriy от Июнь 07, 2009, 08:33
Посмотри пример: %QTDIR%\examples\widgets\analogclock
там таймер каждую секунду перерисовывает часы. Ну а ты будешь вместо перерисовки исполнять какие-то действия.


Название: Re: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 13:34
Посмотри пример: %QTDIR%\examples\widgets\analogclock
там таймер каждую секунду перерисовывает часы. Ну а ты будешь вместо перерисовки исполнять какие-то действия.

простите, а чем отличается таймер аналоговых часов в экзампле
Код:
     QTimer *timer = new QTimer(this);
     connect(timer, SIGNAL(timeout()), this, SLOT(update()));
     timer->start(1000);

от написанного в конструкторе (см. первый пост)

Код:
    QObject::connect(timer, SIGNAL(timeout()), this, SLOT(updateTime()));
    timer->start(500);

я уже пробовал вместо QTime::singleShot запускать отдельный таймер, типа
Код:
    
    ...
    QObject::connect(alarm_timer, SIGNAL(timeout()), this, SLOT(playAlarm()));
    alarm_timer->start(delay);

но после задания желаемого времени будильника приложение "неожиданно закрывается", т.е., по видимому, сегфолт..


Название: Re: Вопрос по реализации будильника в программе
Отправлено: lit-uriy от Июнь 07, 2009, 15:38
>>простите, а чем отличается таймер аналоговых часов в экзампле
тем, что в примере ему начзначается родитель, и после удаления родителя, его детё (таймер) будет тоже удалено. Т.е. высвободится память.

>>приложение "неожиданно закрывается"
Закоментируй весь код в слоте, и проверь как программа себя вести будет.


Название: Re: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 17:03
>>приложение "неожиданно закрывается"
Закоментируй весь код в слоте, и проверь как программа себя вести будет.

Код:
void Timer::playAlarm()
{
    //QMessageBox::information(this, "Alarm", "Good Morning");
    // добавить воспроизведение мелодии
}

если это то, что вы имели ввиду, то ничего ровным счетом не изменилось.


Название: Re: Вопрос по реализации будильника в программе
Отправлено: igor_bogomolov от Июнь 07, 2009, 17:07
Timer::Timer()
    QObject::connect(alarm_timer, SIGNAL(timeout()), this, SLOT(playAlarm()));

Сигналы и слоты (http://www.doc.crossplatform.ru/qt/4.4.3/signalsandslots.html#a-small-example)
Цитировать
Все классы, содержащие сигналы и слоты, должны упомянуть макрос Q_OBJECT в начале своей декларации. Также они должны происходить (прямо или косвенно) от QObject.


Название: Re: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 17:29
Timer::Timer()
    QObject::connect(alarm_timer, SIGNAL(timeout()), this, SLOT(playAlarm()));

Сигналы и слоты (http://www.doc.crossplatform.ru/qt/4.4.3/signalsandslots.html#a-small-example)
Цитировать
Все классы, содержащие сигналы и слоты, должны упомянуть макрос Q_OBJECT в начале своей декларации. Также они должны происходить (прямо или косвенно) от QObject.

Если я вас правильно понял, то это есть:
widget.h
Код:
class Timer : public QWidget
{
    Q_OBJECT
...
}


Название: Re: Вопрос по реализации будильника в программе
Отправлено: igor_bogomolov от Июнь 07, 2009, 17:52
Попробуй немного переделать конструктор класса

Код
C++ (Qt)
Timer(QWidget *parent = 0);
 
Timer::Timer(QWidget *parent) : QWidget(parent)
{
   ....
}


Название: Re: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 18:03
Попробуй немного переделать конструктор класса

Код
C++ (Qt)
Timer(QWidget *parent = 0);
 
Timer::Timer(QWidget *parent) : QWidget(parent)
{
   ....
}

переделал:
widget.h
Код
C++ (Qt)
class Timer : public QWidget
{
   Q_OBJECT
 
public:
   Timer(QWidget *parent = 0);
...
}
 

widget.cpp
Код
C++ (Qt)
void Timer::getAlarmTime()
{
   ...
   QTimer::singleShot(delay, this, SLOT(playAlarm()));
}
 

Код
C++ (Qt)
Timer::Timer(QWidget *parent) : QWidget(parent)
{
  ...
  QObject::connect(set, SIGNAL(clicked()),
                    this, SLOT(getAlarmTime()));
}

программа на синглшот все еще не реагирует вообще никак, а если использовать обычный таймер - опять же вылетает.


Название: Re: Вопрос по реализации будильника в программе
Отправлено: igor_bogomolov от Июнь 07, 2009, 18:08
Если хочешь, приатач проект, я посмотрю что не так


Название: Re: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 18:13
Если хочешь, приатач проект, я посмотрю что не так

ну, вот... Спасибо вам большое заранее  ;)


Название: Re: Вопрос по реализации будильника в программе
Отправлено: sLiva от Июнь 07, 2009, 18:56
Если хочешь, приатач проект, я посмотрю что не так

ну, вот... Спасибо вам большое заранее  ;)

Глубоко не смотрел но сразу же дебагом увидел неправильный расчет задержки delay, которая при задание будильника на минуту показывает delay_minute = 34, delay = 71580000

Проверяй расчет задержки...


Название: Re: Вопрос по реализации будильника в програ&
Отправлено: igor_bogomolov от Июнь 07, 2009, 18:57
Ну ты конечно начудил с расчетом времени. Текущее время 19,30. Завожу на 19,31. deley = 70260000  :o

Подправил тебе. Диалог выбора времени сам доделаешь, идея и так должна быть понятна. Сейчас выставляешь требуемое время, и нажимаешь крестик. В нужное время будильник сработает :)

---
Да, расчет паузы тоже сам доделаешь. Сейчас можно менять только секунды. Пользуйся QTimeEdit


Название: Re: Вопрос по реализации будильника в программе
Отправлено: igor_bogomolov от Июнь 07, 2009, 19:10
Ошибся я слегка. Замени
int delay = alarm.msecsTo(QTime::currentTime());
на
int delay = QTime::currentTime().msecsTo(alarm);

и все должно быть нормально для любого времени :)


Название: Re: Вопрос по реализации будильника в программе
Отправлено: Noir от Июнь 07, 2009, 19:18
Ошибся я слегка. Замени
int delay = alarm.msecsTo(QTime::currentTime());
на
int delay = QTime::currentTime().msecsTo(alarm);

и все должно быть нормально для любого времени :)

поправил уже сам, когда увидел в дебаге отрицательные числа :)

спасибо вам большое за помощь, all works! =)