Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: остаток времени в QTime
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt GUI
AD
В какой-то момент стартанули поток, процесс, таймер (не столь важно). Этот момент времени запомнили. Через какие-то промежутки времени берем текущее время. Узнаем разность. Но вопрос в том, как получить оставшееся время?
Litkevich Yuriy
Цитата(AD @ 11.6.2009, 21:56) *
оставшееся время?
а что это такое?
AD
А ну да... :) не так выразился...
Задали какое-то время выполнения чего-то! Ну к примеру, 5 минут, или же 2 часа. Стартанули выполнение. Как узнать, сколько времени выполняться осталось? :)
Litkevich Yuriy
Запомнить время начала и посчитать сколько должно быть по завершении.
Затем периодически проверять сколько сейчас времени. Ну а как посчитать сколько осталось зная "Сечас" и "Конец" -это из школьной арифметики.
AD
Цитата(Litkevich Yuriy @ 11.6.2009, 19:47) *
Запомнить время начала и посчитать сколько должно быть по завершении.
Затем периодически проверять сколько сейчас времени. Ну а как посчитать сколько осталось зная "Сечас" и "Конец" -это из школьной арифметики.

Блин, чуточку сам не додумался. Спасибо, в понедельник сделаю! :)))
AD
Не могу понять, как сделать, чтобы во время отсчета времени приложение не зависало, собственно для этого и было переведено в отдельный поток.

Вот код:
Thread
/// Класс потока - вращение вокруг осей заданное количество времени - длительное вращение
class ContinueRotation: public QThread
{
    Q_OBJECT

private:
    QTime _time;                                ///< счетчик времени вращения прожектора
    QTime starting_time, finished_time;            ///< время начала и окончания отсчета

private:
    void readAzimuth(int& geted_azimuth, double limit);
    void readAngleElevation(int& geted_angle_elev, double limit);

protected:
    virtual void run();

signals:
    void timeout(QTime);

public:
    ContinueRotation(QObject *parent);
    ~ContinueRotation();
    QTime elapsedTime() const { return _time; }
    QTime startingTime() const { return starting_time; }
    void setTime(const QTime& t) { _time = t; }
    void setTime(const int h, const int m) { _time.setHMS(h, m, 0, 0); }
    void setStartingTime(const QTime& t);
};


/// Установка времен начала и окончания работы прожектора
void ContinueRotation::setStartingTime(const QTime& t)
{
    starting_time = t;
    finished_time.setHMS(starting_time.hour() + _time.hour(), starting_time.minute() + _time.minute(),
                         starting_time.second() + _time.second(), starting_time.msec() + _time.msec());
}

/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
    while(_time.hour() || _time.minute() || _time.second() || _time.msec())
    {
        int secs = QDateTime::currentDateTime().time().secsTo(finished_time);
        QTime t;    t = t.addSecs(secs);
        _time = t;
        emit timeout(_time);
    }
}


Main Thread
/// Класс отображения параметров работы в автоматическом режиме продолжительное время
class ContinuousWork: public QWidget, public ContinuousWorkClass
{
    Q_OBJECT

private:
    ContinueRotation* _continue;                ///< указатель на класс потока, выполняющий необходимое вращение

private slots:
    void changeHour(int h);                                    
    void startControl();
    void elapsedTime(QTime t) { editElapsedTime -> setTime(t); }           ///< editElapsedTime  - имеет тип QTimeEdit

public:
    ContinuousWork(QWidget *parent = 0);
    ~ContinuousWork();
};

ContinuousWork::ContinuousWork(QWidget *parent): QWidget(parent)
                                           _continue(new ContinueRotation(parent))
{
        // anybody

    connect(btnStartControl, SIGNAL(clicked()), this, SLOT(startControl()));
    connect(_continue, SIGNAL(timeout(QTime)), SLOT(elapsedTime(QTime)));
}

/// Запуск работы прожектора
void ContinuousWork::startControl()
{
    _continue -> setTime(spinHours -> value(), spinMinutes -> value());
    _continue -> setStartingTime(QDateTime::currentDateTime().time());
    _continue -> start();
}


Приложение зависает на время выполнение работы. Как это поправить можно?
SABROG
Поправь меня, если я не прав, но тут посылается целый шквал эвентов timeout() и я не вижу условий, чтобы он прекратился, скорее всего очередь сообщений переполняется и GUI просто не успевает их всех обработать.

void ContinueRotation::run()
{
    while(_time.hour() || _time.minute() || _time.second() || _time.msec())
    {
        int secs = QDateTime::currentDateTime().time().secsTo(finished_time);
        QTime t;    t = t.addSecs(secs);
        _time = t;
        emit timeout(_time);
    }
}
AD
Цитата(SABROG @ 15.6.2009, 13:59) *
Поправь меня, если я не прав, но тут посылается целый шквал эвентов timeout() и я не вижу условий, чтобы он прекратился, скорее всего очередь сообщений переполняется и GUI просто не успевает их всех обработать.

Ну а как тогда лучше сделать? Ну как заставить его посылать эти эвенты раз в секунду?
SABROG
Цитата(AD @ 15.6.2009, 14:16) *
Ну а как тогда лучше сделать? Ну как заставить его посылать эти эвенты раз в секунду?


Через QTimer созданный в run()? Ну или раз ты решил через diff делать, то проверяй, если прошло больше или равно 1000 мс, то посылать сигнал.
kwisp
Цитата(AD @ 15.6.2009, 14:16) *
Ну как заставить его посылать эти эвенты раз в секунду?

это точно так необходимо? без этого никак?
Цитата(Litkevich Yuriy @ 11.6.2009, 19:47) *
Запомнить время начала и посчитать сколько должно быть по завершении.
Затем периодически проверять сколько сейчас времени. Ну а как посчитать сколько осталось зная "Сечас" и "Конец" -это из школьной арифметики.

была такая проблемка и у меня.
если я правильно понял, то Запомнить время начала это запомнить системное время? так?
я сначала так и сделал, но потом от шефа получил по рукам.
шеф мотивировал тем что если время выполнения большое к примеру более 1 минуты то пользователь сможет поменять системное время и тогда будет ерунда.

наверное самому время надо считать в смысле заводить таймер и наращивать время.
AD
Цитата(kwisp @ 15.6.2009, 14:46) *
была такая проблемка и у меня.
если я правильно понял, то Запомнить время начала это запомнить системное время? так?
я сначала так и сделал, но потом от шефа получил по рукам.
шеф мотивировал тем что если время выполнения большое к примеру более 1 минуты то пользователь сможет поменять системное время и тогда будет ерунда.

наверное самому время надо считать в смысле заводить таймер и наращивать время.

Ты о чем вообще? :)))

Вот решение проблемы, которое предложил SABROG, за что ему огромное спасибо:
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
    while(_time.hour() || _time.minute() || _time.second() || _time.msec())
    {
        int secs = QDateTime::currentDateTime().time().secsTo(finished_time);
        QTime t;    t = t.addSecs(secs);
        int el_t = t.hour() * 60 * 60 * 1000 + t.minute() * 60 * 1000 + t.second() * 1000 + t.msec();
        int _t = _time.hour() * 60 * 60 * 1000 + _time.minute() * 60 * 1000 + _time.second() * 1000 + _time.msec();
        int diff = _t - el_t;
        _time = t;
        if(diff >= 1000) emit timeout(_time);
    }
}
igor_bogomolov
Цитата(AD)
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
    while(_time.hour() || _time.minute() || _time.second() || _time.msec())
    {
        int secs = QDateTime::currentDateTime().time().secsTo(finished_time);
        QTime t;    t = t.addSecs(secs);
        int el_t = t.hour() * 60 * 60 * 1000 + t.minute() * 60 * 1000 + t.second() * 1000 + t.msec();
        int _t = _time.hour() * 60 * 60 * 1000 + _time.minute() * 60 * 1000 + _time.second() * 1000 + _time.msec();
        int diff = _t - el_t;
        _time = t;
        if(diff >= 1000) emit timeout(_time);
    }
}


1) Если ты не учитываешь дату, зачем используешь QDateTime, достаточно QTime
int secs = QTime::currentTime().secsTo(finished_time);

2) По идее твой run должен грузить проц на 100%. Дабавь в цикл QThread::msleep.
3) Зачем для токого функционала выделять доп. поток?
4) _time не защищен мьютексом.
5) Уверен ли ты что поток гарантированно завершится по прошествии нужного времени
kwisp
AD,
значит я чего-то не допонял.:)
igor_bogomolov
Цитата(kwisp @ 15.6.2009, 15:50) *
значит я чего-то не допонял.
Помоему все правильно ты говоришь. Только такая ситуация моловероятна. Но от дураков защититься можно ;)
AD
Цитата(igor_bogomolov @ 15.6.2009, 15:45) *
1) Если ты не учитываешь дату, зачем используешь QDateTime, достаточно QTime
int secs = QTime::currentTime().secsTo(finished_time);

2) По идее твой run должен грузить проц на 100%. Дабавь в цикл QThread::msleep.
3) Зачем для токого функционала выделять доп. поток?
4) _time не защищен мьютексом.
5) Уверен ли ты что поток гарантированно завершится по прошествии нужного времени

1) Да. Поправил. Бывает.... Спасибо.
2) Куда и как добавить? Подскажи, пожалуйста.
3) Доп. поток, потому что это только начало работы потока. Там более сложная структура.
4) Зачем мьютекс?
5) Цикл завершится - в этом уверен. Раз цикл завершится, то run ничего делать не будет.
igor_bogomolov
Цитата(AD @ 15.6.2009, 13:33) *
QTime starting_time, finished_time; ///< время начала и окончания отсчета


Такую ситуацию ты не предусматриваешь?
starting_time = 23,59,00
finished_time = 00,02,00

finished_time лучше сделать не конечным временем, а интервалом
AD
Цитата(igor_bogomolov @ 15.6.2009, 16:08) *
Цитата(AD @ 15.6.2009, 13:33) *
QTime starting_time, finished_time; ///< время начала и окончания отсчета


Такую ситуацию ты не предусматриваешь?
starting_time = 23,59,00
finished_time = 00,02,00

finished_time лучше сделать не конечным временем, а интервалом

Что с msleep то?

На счет ситуации не знаю пока.

Такую ситуацию сам Qtime отследит: :)
Цитата
int QTime::secsTo ( const QTime & t ) const
Returns the number of seconds from this time to t. If t is earlier than this time, the number of seconds returned is negative.
Because QTime measures time within a day and there are 86400 seconds in a day, the result is always between -86400 and 86400.
See also addSecs() and QDateTime::secsTo().
igor_bogomolov
Цитата(AD @ 15.6.2009, 16:04) *
1) Да. Поправил. Бывает.... Спасибо.
2) Куда и как добавить? Подскажи, пожалуйста.
3) Доп. поток, потому что это только начало работы потока. Там более сложная структура.
4) Зачем мьютекс?
5) Цикл завершится - в этом уверен. Раз цикл завершится, то run ничего делать не будет.

1) Не за что
2) В любом месте цикла while, лучше в конце.
3) Ок.
4) Для того чтобы защитить данные в _time. Он у тебя может измениться из вне. И emit timeout(_time) отправит не правильные данные.
5) А я вот совершенно не уверен (по тому коду, что сейчас есть). Что произойдет, когда int secs станет отрицательным. t = t.addSecs(secs) останется инициализированным нулями? Я не проверял такого поведения.


Цитата(AD @ 15.6.2009, 16:17) *
Такую ситуацию сам Qtime отследит:
Возвратит отрицательное значение. ;)
AD
Цитата(igor_bogomolov @ 15.6.2009, 16:23) *
Возвратит отрицательное значение. ;)

Цитата
QTime QTime::addSecs ( int s ) const
Returns a QTime object containing a time s seconds later than the time of this object (or earlier if s is negative).
Note that the time will wrap if it passes midnight.
Example:
QTime n(14, 0, 0); // n == 14:00:00
QTime t;
t = n.addSecs(70); // t == 14:01:10
t = n.addSecs(-70); // t == 13:58:50
t = n.addSecs(10 * 60 * 60 + 5); // t == 00:00:05
t = n.addSecs(-15 * 60 * 60); // t == 23:00:00
See also addMSecs(), secsTo(), and QDateTime::addSecs().
kwisp
Цитата(kwisp @ 15.6.2009, 15:50) *
значит я чего-то не допонял.:)

если честно тоже не пойму зачем доп. поток?
мне просто скоро тоже вплотную со временем работать.
расскажи поподробнее что по чем. зачем тебе сигналить timout`ом каждую секунду?
SABROG
Таймер и другой поток необходимы в ситуации, когда по таймауту вызываются "долгоиграющие" методы, которые блокируют цикл сообщений и соответственно подвешивают GUI. Как вариант можно по таймауту запускать существующий поток на выполнение, после того как он сделает своё черное дело усыплять его. Естественно при такой схеме таймер будет существовать в основном потоке.
AD
Задается определенное время, например 15 минут или 2 часа и запускается поток работы прожектора (прожектор начинает вращаться в 2 плоскостях - вертикальной и горизонтальной) - чтобы приложение в этот момент не висело, то вынесено в отдельный поток (заодно идет обучение правильной работы с доп. потоком). При этом запускаются часы, которые показывают оставшееся время работы прожектора.
igor_bogomolov
Цитата(AD @ 15.6.2009, 16:17) *
Такую ситуацию сам Qtime отследит:
Еще раз говорю, что не отследит.
    QTime finished_time(0,0,0);
    int secs = QTime::currentTime().secsTo(finished_time);
    qDebug() << secs;
Цитата
warning: -66787

Т.е. если ты включил свой прожектор в один день, например, в 23.00, а выключить надо в 00.15 уже другого дня, ты получишь отрицательное время.

Цитата(AD)
заодно идет обучение правильной работы с доп. потоком
Прежде чем работать с потоками, нужно разобраться со способами синхронизации потоков.
AD
Цитата(igor_bogomolov @ 15.6.2009, 18:44) *
Цитата(AD)
заодно идет обучение правильной работы с доп. потоком
Прежде чем работать с потоками, нужно разобраться со способами синхронизации потоков.

Вот именно с этим и разбираюсь на практике. Можно как-то не так нравоучительно! ;) Ну честное слово, все-таки не школяр какой-то.... :)

что-то я даже подзапутался. Мне необходимо, чтобы определенное действие происходило 1 раз в минуту в течение заданного времени. Как это сделать? Еще один таймер заводить и запускать его уже в доп. потоке?
kwisp
Цитата(AD @ 15.6.2009, 19:29) *
Мне необходимо, чтобы определенное действие происходило 1 раз в минуту в течение заданного времени.

ну если раз в минуту то могу предложить
стартовать таймер в программе предположим каждые 10 секунд завести член класса QTime time наращивать его в timerEvent`e на десять секунд. при достижении определенного времени останавливать таймер сбрасывать время. как то так.
igor_bogomolov
Цитата(AD @ 15.6.2009, 19:29) *
Мне необходимо, чтобы определенное действие происходило 1 раз в минуту в течение заданного времени. Как это сделать? Еще один таймер заводить и запускать его уже в доп. потоке?
Тут столько разных реализаций придумать можно. Несколько у тебя уже есть.

void ContinueRotation::run()
{
    const int pause = 1000 * 60;
    QDateTime startDT = QDateTime::currentDateTime();

    while(finish_datatime >= startDT) {
        msleep(pause);
        startDT = QDateTime::currentDateTime();
        //emit - эмитируем сигнал с периодом "pause".
    }
}
AD
Цитата(igor_bogomolov @ 15.6.2009, 23:43) *
        //emit - эмитируем сигнал с периодом "pause".

А как это сделать? Разность опять рассчитывать или же в самом emit что-то сделать?
Litkevich Yuriy
Цитата(AD @ 16.6.2009, 12:44) *
или же в самом emit что-то сделать?
а что ты в нём можешь сделать?
AD
вызвать сигнал, который ассоциирую со слотом, выполняющим нужные мне вращения прожектора.


igor_bogomolov, прости, но я в упор не понимаю, чем плохо то, что получилось отрицательное число?
вот я задал такой код:
QTime p(0, 0, 25, 100);
int secs = QTime::currentTime().secsTo(p);
QTime t;    t = t.addSecs(secs);

В Петербурге сейчас 10:50 (округленно). Он мне и посчитал, что до окончания работы должно пройти 13 часов 10 минут. Ведь правильно? В чем проблемы? Т.е. в t занеслось вполне корректное время. Функция addSecs умеет обрабатывать заданные промежутки. Где может поломаться-то?
igor_bogomolov
Цитата(Игорь)
А я вот совершенно не уверен (по тому коду, что сейчас есть). Что произойдет, когда int secs станет отрицательным. t = t.addSecs(secs) останется инициализированным нулями? Я не проверял такого поведения.
Т.е. я не говорил, что это плохо, а только то что, не знаю как данный код отработает. Теперь буду знать, что addSecs может принимать отрицательное значение, и коректно его отрабатывать.


Тагда остается проблемма если твой прожектор должен крутиться больше суток :)
Если конечно такое возможно
AD
Цитата(igor_bogomolov @ 16.6.2009, 12:03) *
Тагда остается проблемма если твой прожектор должен крутиться больше суток :)
Если конечно такое возможно

Ну это не проблема! :) Больше чем 24 часа нельзя задать. SpinBox для задания времени ограничил специально! :)
AD
Никак не пойму, почему таймер не срабатывает. Делаю теперь так, учтя все советы:
Thread
/// Класс потока - вращение вокруг осей заданное количество времени - длительное вращение
class ContinueRotation: public QThread
{
    Q_OBJECT

private:
    INFO_TO_EXTERN_DEVICE inf_to_ed_packet;        ///< пакет данных внешнему устройству в режиме авто управления
    INFO_FROM_EXTERN_DEVICE inf_from_ed_packet;    ///< пакет данных от внешнего устройства в режиме авто управления
    const int MAXBYTES;                            ///< константа максимального количества байт
    ImitatorTSL* imitTsl;                        ///< указатель на класс главного окна
    QTime _time;                                ///< счетчик времени вращения прожектора
    QTime starting_time, finished_time;            ///< время начала и окончания отсчета
    QMutex mutex;                                ///< мьютекс блокировки работы
    QTimer _working_spotlight;                    ///< таймер работы прожектора

private:
    void readAzimuth(int& geted_azimuth, double limit);
    void readAngleElevation(int& geted_angle_elev, double limit);
    void originPosition();
    void readAngles();
    void timerTicks();

protected:
    virtual void run();

signals:
    void _timeout(QTime);

private slots:
    void workSpotlight();

public:
    ContinueRotation(QObject *parent);
    ~ContinueRotation();
    void tsl(ImitatorTSL* im) { imitTsl = im; }
    ImitatorTSL* tsl() const { return imitTsl; }
    INFO_TO_EXTERN_DEVICE continueControl();
    void fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp);
    void setToEDInfo(const INFO_TO_EXTERN_DEVICE& ed) { inf_to_ed_packet = ed; }
    void setFromEDInfo(const INFO_FROM_EXTERN_DEVICE& ed) { inf_from_ed_packet = ed; }
    INFO_TO_EXTERN_DEVICE toEDInfo() { return inf_to_ed_packet; }
    INFO_FROM_EXTERN_DEVICE fromEDInfo() { return inf_from_ed_packet; }
    QTime elapsedTime() const { return _time; }
    QTime startingTime() const { return starting_time; }
    void setTime(const QTime& t) { _time = t; }
    void setTime(const int h, const int m) { _time.setHMS(h, m, 0, 0); }
    void setStartingTime(const QTime& t);
};

ContinueRotation::ContinueRotation(QObject *parent): QThread(parent), MAXBYTES(256), imitTsl(0),
                    inf_to_ed_packet(INFO_TO_EXTERN_DEVICE()), inf_from_ed_packet(INFO_FROM_EXTERN_DEVICE())
{}

ContinueRotation::~ContinueRotation() {}

/// Получение азимута
void ContinueRotation::readAzimuth(int& geted_azimuth, double limit)
{
    if(!imitTsl) return;
    while(geted_azimuth < ((limit - 1.5) * 10) || geted_azimuth > ((limit + 1.5) * 10))
    {
        imitTsl -> readFromCtrlPage();
        geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
    }
}

/// Получение угла места
void ContinueRotation::readAngleElevation(int& geted_angle_elev, double limit)
{
    if(!imitTsl) return;
    while(geted_angle_elev < ((limit - 1.5) * 10) || geted_angle_elev > ((limit + 1.5) * 10))
    {
        imitTsl -> readFromCtrlPage();
        geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
    }
}

/// Чтение углов
void ContinueRotation::readAngles()
{
    if(!imitTsl) return;
    int geted_azimuth, geted_angle_elev;
    QTime begining_time(QTime::currentTime());
    do
    {
        imitTsl -> readFromCtrlPage();
        geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
        geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
        int secs = begining_time.secsTo(QTime::currentTime());
        if(secs > 10) break;
    } while(geted_azimuth < 0 || geted_azimuth > 3 || geted_angle_elev < 0 || geted_angle_elev > 3);
}

/// Возвращение пакета с данными от внешнего устройства в режиме автоматического управления
INFO_TO_EXTERN_DEVICE ContinueRotation::continueControl()
{
    BYTE sum = 0;
    BYTE* ptr = (BYTE*) (&inf_to_ed_packet);
    for(register int i=0; i<(sizeof(inf_to_ed_packet) - 1); ++i) sum += ptr[i];
    inf_to_ed_packet.checksum = MAXBYTES - sum;
    return inf_to_ed_packet;
}

/// Установка пакета данных от внешнего управления в автоматической режиме работы
void ContinueRotation::fromExternalDevice(INFO_FROM_EXTERN_DEVICE& mp)
{
    BYTE sum = 0;
    BYTE* ptr = (BYTE*) (&mp);
    for(register int i=0; i<(sizeof(mp) - 1); ++i) sum += ptr[i];
    if((MAXBYTES - sum) == mp.checksum)
        inf_from_ed_packet = mp;
}

/// Установка времен начала и окончания работы прожектора
void ContinueRotation::setStartingTime(const QTime& t)
{
    starting_time = t;
    finished_time.setHMS(starting_time.hour() + _time.hour(), starting_time.minute() + _time.minute(),
                         starting_time.second() + _time.second(), starting_time.msec() + _time.msec());
}

/// Перемещение прожектора в исходную позицию
void ContinueRotation::originPosition()
{
    int geted_azimuth = VALFROMBYTES(inf_from_ed_packet.high_azim, inf_from_ed_packet.low_azim);
    int geted_angle_elev = VALFROMBYTES(inf_from_ed_packet.high_angle_elev, inf_from_ed_packet.low_angle_elev);
    if(geted_azimuth || geted_angle_elev)
    {
        int azimuth = 0, angle_elevation = 0;
        inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
        inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
        inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
        inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
        if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    }
}

/// Отсчет оставшегося времени работы прожектора
void ContinueRotation::timerTicks()
{
    int secs = QTime::currentTime().secsTo(finished_time);
    QTime t;    t = t.addSecs(secs);
    int el_t = t.hour() * 60 * 60 * 1000 + t.minute() * 60 * 1000 + t.second() * 1000 + t.msec();
    int _t = _time.hour() * 60 * 60 * 1000 + _time.minute() * 60 * 1000 + _time.second() * 1000 + _time.msec();
    float diff = _t - el_t;
    mutex.lock();
    _time = t;
    if(fabs(diff) >= 1000) emit _timeout(_time);
    mutex.unlock();
}

/// Слот работы прожектора - вращения в обеих плоскостях
void ContinueRotation::workSpotlight()
{
    timerTicks();

    int geted_angle_elev = -1, geted_azimuth = -1;

    /// Перемещение вниз и вправо до упора
    int angle_elevation = -110 * 10, azimuth = 172 * 10;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.);
    readAzimuth(geted_azimuth, (double) azimuth / 10.);

    timerTicks();

    /// Перемещение вверх и влево до упора
    angle_elevation = 10 * 10;        azimuth = -172 * 10;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.);
    readAzimuth(geted_azimuth, (double)azimuth / 10.);

    timerTicks();

    /// Возврат в исходное положение
    angle_elevation = 0;        azimuth = 0;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();

    timerTicks();
}

/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
    timerTicks();
    originPosition();
    readAngles();

    connect(&_working_spotlight, SIGNAL(timeout()), this, SLOT(workSpotlight()));
    const int working_time = 60 * 1000;
    _working_spotlight.start(working_time);

    while(QTime::currentTime() <= finished_time)
    {
        timerTicks();
        msleep(1000);
    }
    if(QTime::currentTime() > finished_time && _working_spotlight.isActive())
        _working_spotlight.stop();
}


Думаю, если есть неточности в коде, то они кроются в функции run():
/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
    timerTicks();
    originPosition();
    readAngles();

    connect(&_working_spotlight, SIGNAL(timeout()), this, SLOT(workSpotlight()));
    const int working_time = 60 * 1000;
    _working_spotlight.start(working_time);

    while(QTime::currentTime() <= finished_time)
    {
        timerTicks();
        msleep(1000);
    }
    if(QTime::currentTime() > finished_time && _working_spotlight.isActive())
        _working_spotlight.stop();
}
AD
Цитата(igor_bogomolov @ 15.6.2009, 23:43) *
Тут столько разных реализаций придумать можно. Несколько у тебя уже есть.
void ContinueRotation::run()
{
    const int pause = 1000 * 60;
    QDateTime startDT = QDateTime::currentDateTime();

    while(finish_datatime >= startDT) {
        msleep(pause);
        startDT = QDateTime::currentDateTime();
        //emit - эмитируем сигнал с периодом "pause".
    }
}

Это насколько я попытался сделать не совсем то, что мне нужно! Время должно передаваться раз в секунду (ну как секундомер, часы....). А вот выполняться действие уже раз в минуту. Подскажите, пожалуйста! Что-то действительно не получается. Не знаю, как исправить....
igor_bogomolov
Цитата(AD @ 17.6.2009, 10:29) *
Это насколько я попытался сделать не совсем то, что мне нужно! Время должно передаваться раз в секунду (ну как секундомер, часы....). А вот выполняться действие уже раз в минуту. Подскажите, пожалуйста! Что-то действительно не получается. Не знаю, как исправить....
Высылай сигнал раз в секунду. А в обработчике, создай счетчик прореживания. Как счетчик станет равным 60, выполняй нужное действие.

Это ты имел в виду? :)
AD
Цитата(igor_bogomolov @ 17.6.2009, 12:30) *
Высылай сигнал раз в секунду. А в обработчике, создай счетчик прореживания. Как счетчик станет равным 60, выполняй нужное действие.

Это ты имел в виду? :)

Смутно как-то я понял это, но попробую, как только исправлю баг в приложении.
AD
igor_bogomolov, видимо, я так не смогу сам определить, как надо сделать, можешь подсказать? Не понимаю, что за эмит надо сделать? Какой счетчик? Где?
AD
Ну разобрался, наконец-то! :)
Вот окончательная версия:
/// В классе.
signals:
    void _timeout(QTime);
    void working_light();

/// Слот работы прожектора - вращения в обеих плоскостях
void ContinueRotation::workSpotlight()
{
    timerTicks();

    int geted_angle_elev = -1, geted_azimuth = -1;

    /// Перемещение вниз и вправо до упора
    int angle_elevation = -110 * 10, azimuth = 172 * 10;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.);
    readAzimuth(geted_azimuth, (double) azimuth / 10.);

    timerTicks();

    /// Перемещение вверх и влево до упора
    angle_elevation = 10 * 10;        azimuth = -172 * 10;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();
    readAngleElevation(geted_angle_elev, (double)angle_elevation / 10.);
    readAzimuth(geted_azimuth, (double)azimuth / 10.);

    timerTicks();

    /// Возврат в исходное положение
    angle_elevation = 0;        azimuth = 0;
    inf_to_ed_packet.low_angle_elev = LOWBYTE(angle_elevation);
    inf_to_ed_packet.high_angle_elev = HIGHBYTE(angle_elevation);
    inf_to_ed_packet.low_azim = LOWBYTE(azimuth);
    inf_to_ed_packet.high_azim = HIGHBYTE(azimuth);
    if(imitTsl) imitTsl -> writeFromCtrlContinuous();

    timerTicks();
}

/// Запуск потока вращения в обеих плоскостях длительный промежуток времени
void ContinueRotation::run()
{
    timerTicks();
    originPosition();
    readAngles();

    int timer_count = 0;
    connect(this, SIGNAL(working_light()), SLOT(workSpotlight()));
    while(QTime::currentTime() <= finished_time)
    {
        timerTicks();
        if(timer_count == 60) timer_count = 0;
        if(!timer_count) emit working_light();
        msleep(1000);
        ++timer_count;
    }
    if(QTime::currentTime() > finished_time && _working_spotlight.isActive())
        _working_spotlight.stop();
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.