crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в остаток времени в QTime
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
Теги
Выровнять по центру
Ссылка на тему
Ссылка на сообщение
Скрытый текст
Сокращение
Код с подсветкой
Offtopic
 
Удалить форматирование
Спец. элементы
Шрифт
Размер
 
Цвет шрифта
 
Отменить ввод
Вернуть ввод
Полужирный
Курсив
Подчеркнутый
 
 
Смайлики
Вставить изображение
Вставить адрес электронной почты
Цитата
Код
Раскрывающийся текст
 
Увеличить отступ
По левому краю
По центру
По правому краю
Вставить список
Вставить список

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
AD Дата 17.6.2009, 17:50
  Ну разобрался, наконец-то! :)
Вот окончательная версия:
/// В классе.
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();
}
AD Дата 17.6.2009, 15:52
  igor_bogomolov, видимо, я так не смогу сам определить, как надо сделать, можешь подсказать? Не понимаю, что за эмит надо сделать? Какой счетчик? Где?
AD Дата 17.6.2009, 12:08
 
Цитата(igor_bogomolov @ 17.6.2009, 12:30) *
Высылай сигнал раз в секунду. А в обработчике, создай счетчик прореживания. Как счетчик станет равным 60, выполняй нужное действие.

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

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

Это ты имел в виду? :)
AD Дата 17.6.2009, 9:29
 
Цитата(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".
    }
}

Это насколько я попытался сделать не совсем то, что мне нужно! Время должно передаваться раз в секунду (ну как секундомер, часы....). А вот выполняться действие уже раз в минуту. Подскажите, пожалуйста! Что-то действительно не получается. Не знаю, как исправить....
AD Дата 16.6.2009, 14:23
  Никак не пойму, почему таймер не срабатывает. Делаю теперь так, учтя все советы:
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 Дата 16.6.2009, 11:38
 
Цитата(igor_bogomolov @ 16.6.2009, 12:03) *
Тагда остается проблемма если твой прожектор должен крутиться больше суток :)
Если конечно такое возможно

Ну это не проблема! :) Больше чем 24 часа нельзя задать. SpinBox для задания времени ограничил специально! :)
igor_bogomolov Дата 16.6.2009, 11:03
 
Цитата(Игорь)
А я вот совершенно не уверен (по тому коду, что сейчас есть). Что произойдет, когда int secs станет отрицательным. t = t.addSecs(secs) останется инициализированным нулями? Я не проверял такого поведения.
Т.е. я не говорил, что это плохо, а только то что, не знаю как данный код отработает. Теперь буду знать, что addSecs может принимать отрицательное значение, и коректно его отрабатывать.


Тагда остается проблемма если твой прожектор должен крутиться больше суток :)
Если конечно такое возможно
AD Дата 16.6.2009, 9:56
  вызвать сигнал, который ассоциирую со слотом, выполняющим нужные мне вращения прожектора.


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 умеет обрабатывать заданные промежутки. Где может поломаться-то?
Litkevich Yuriy Дата 16.6.2009, 8:55
 
Цитата(AD @ 16.6.2009, 12:44) *
или же в самом emit что-то сделать?
а что ты в нём можешь сделать?
Просмотр темы полностью (откроется в новом окне)
RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 6.7.2025, 3:26