Russian Qt Forum

Qt => Вопросы новичков => Тема начата: grig_p от Июль 09, 2021, 16:46



Название: QTimer::singleShot и удаление объекта
Отправлено: grig_p от Июль 09, 2021, 16:46
Здравствуйте!
Есть некий виджет, который асинхронно, с определенной периодичностью получает данные и отображает их на себе и зажигает индикатор их приема. После получения данных, через, скажем 100 мсек, этот индикатор должен быть погашен. Я это сделал так:

Код:
void MyWidget::getData(DataType *data)
{
    ....

     //! Зажжем индикатор
     ui->Indicator->setValue(1);

    //! Погасим индикатор через 100 мс
    QTimer::singleShot(100, [=]
    {
            ui->Indicator->setValue(0);
    });
    ....


Все прекрасно работает до удаления виджета. Возникает нерегулярный сбой.
Поставил ловушки:

Код:

MyWidget::~MyWidget()
{
    qDebug() << "destroy";
    delete ui;
}

void MyWidget::getData(DataType *data)
{
    ....

     //! Зажжем индикатор
     ui->Indicator->setValue(1);

    //! Погасим индикатор через 100 мс
    QTimer::singleShot(100, [=]
    {
            qDebug() << "singleshot";
            ui->Indicator->setValue(0);
    });
    ....

 Выводит в консоль:
singleshot
singleshot
singleshot
destroy
singleshot

и сбой.
Как правильно обойти эту проблему?
Придумал вариант поставить семафор:

Код:

class MyWidget ...
{

    bool m_isFinish {false};
}


MyWidget::~MyWidget()
{
    qDebug() << "destroy";
    m_isFinish = true;
    delete ui;
}

void MyWidget::getData(DataType *data)
{
    ....

     //! Зажжем индикатор
     ui->Indicator->setValue(1);

    //! Погасим индикатор через 100 мс
    QTimer::singleShot(100, [=]
    {
            if (!m_isFinish)
            {
                qDebug() << "singleshot";
                ui->pbPulse->setValue(0);
            }
    });
    ....

только правильно ли это?


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: Old от Июль 09, 2021, 16:56
Просто добавьте объект QTimer в класс и при разрушении виджета разрушайте и таймер.


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: kuzulis от Июль 09, 2021, 17:15
Цитата: cpp
QTimer::singleShot(100, this, [this]
    {
            qDebug() << "singleshot";
            ui->Indicator->setValue(0);
    });

?


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: grig_p от Июль 09, 2021, 17:36
Просто добавьте объект QTimer в класс и при разрушении виджета разрушайте и таймер.
Спасибо, попробую!


Цитата: cpp
QTimer::singleShot(100, this, [this]
    {
            qDebug() << "singleshot";
            ui->Indicator->setValue(0);
    });

?

Не понял, что не так
А такого у меня нет: 100, this, [this]


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: Old от Июль 09, 2021, 17:37
Цитата: cpp
QTimer::singleShot(100, this, [this]
    {
            qDebug() << "singleshot";
            ui->Indicator->setValue(0);
    });

?
Захват указателя this никак не блокирует разрущение объекта. Это на shared_ptr. :)


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: sergek от Июль 10, 2021, 10:12
Просто добавьте объект QTimer в класс и при разрушении виджета разрушайте и таймер.
Что это изменит, если singshort является статической функцией?


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: Old от Июль 10, 2021, 10:43
Просто добавьте объект QTimer в класс и при разрушении виджета разрушайте и таймер.
Что это изменит, если singshort является статической функцией?
Это позволит ее не использовать, т.к. она не управляемая после запуска.


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: sergek от Июль 10, 2021, 11:56
С этим согласен. Но TC это понял? 


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: grig_p от Июль 12, 2021, 10:20
Спасибо всем ответившим. Надеюсь, что понял.

Код:
QTimer *m_timer;
...
m_timer = new QTimer();

...

m_timer.singleShot(100, [=]
    {
            ui->Indicator->setValue(0);
    });

...

delete m_timer;

После
Код:
delete m_timer;
singleShot сработает?


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: sergek от Июль 12, 2021, 10:59
Нет, не поняли)) Синглшот - статическая функция, а это значит, что она не принадлежит к созданному вами объекту, и не прекратит свою работу после его уничтожения. Собственно, вызовы m_timer.singleShot и QTimer::singleShot семантически ничем не отличаются.
Если вам так нужен однократный запуск таймера, то используйте методы setSingleShot и start.


Название: Re: QTimer::singleShot и удаление объекта
Отправлено: grig_p от Июль 12, 2021, 11:32
спасибо