#qt #многопоточность
Делаю сейчас программу, в которой второе окно должно мигать морзянкой сменяя черный
фон белым. Я уже и через таймер попробовал в самом коде окна и в отдельный поток выкладывал.
Сейчас у меня такой вариант(тестовый) и он не работает. Появляется белое окно, потом
проходит время равное сумме всех интервалов таймера и потом окно становится черным,
хотя задумка теста - окно должно мигать несколько раз с интервалом, заданным в таймере
for(int j = 0; j < 3; j++)
{
this->setPalette(QPalette(Qt::white));
this->show();
m_timer->start(2000);
}
коннект для приема сигнала от таймера
QObject::connect(m_timer, SIGNAL(timeout()), this, SLOT(BlackWindow()));
и сам слот
void morzewindow::BlackWindow()
{
this->setPalette(QPalette(Qt::black));
this->show();
m_timer->stop();
}
Может у кого-то была подобная задача реализованная средствами Qt? помогите. Мне как
новичку уже ни одной идеи в голову не приходит. Все что знал, о чем подозревал, все
перепробовал.
UPDATE:
запуск потока и функции в нем:
MorzeBlinkTimer.moveToThread(&MorzeBlinkThread);
QObject::connect(&MorzeBlinkTimer, SIGNAL(latency(bool)), SLOT(Blink(bool)));
MorzeBlinkThread.start();
MorzeBlinkTimer.startBlink(etalon2.GetReadyCodeMorzeForBlink());
функцию запускаю вручную, потому что она принимает указатель на массив с морзянкой.
//слот для смены цвета окна морзянки черный/белый
void morzewindow::Blink(bool BlackWhite)
{
if(BlackWhite)
{
this->setPalette(QPalette(Qt::white));
this->show();
}
else
{
this->setPalette(QPalette(Qt::black));
this->show();
}
}
и сама функция потока, которая вводит задержку(фрагмент):
void startBlink(int* morze)
{
for(int i = 0; i < 50; i++)
{
switch(morze[i])
{
case 0:
emit latency(true);
QThread::msleep(iDot);
emit latency(false);
QThread::msleep(iPauseSymbol);
break;
}
}
}
Ответы
Ответ 1
Все правильно, пока все функции не отработают и не "встанут" в ожидании событий в графическом интерфейсе - он не обновится. Делать надо отдельным потоком, но там есть тонкости, тоже долго получалось как у вас - что не реагировало окно ни на что, пока не отработают все события. Вот рабочий пример обновления графического интерфейса в отдельном потоке. В основной функции у вас должно быть примерено так: //Starting process in the new thread Worker * pWorker = new Worker; QThread * pThread = new QThread(); pWorker->moveToThread(pThread); connect(pThread, SIGNAL(started()), pWorker, SLOT(slotDummyUpdatingRequest())); // сигнал старта потока соединяем с функцией имеющей задержки connect(pWorker, SIGNAL(sigDummyNextRequestStage()), this, SLOT(slotStageRequestPrint())); // сигнал от объекта осуществляющего задержки на обновление окна соединяем со слотом обновления окна текущего оъекта pThread->start(); И сам слот обновления графики, срабатывающий асинхронно: void UpdatingRequestState::slotStageRequestPrint() { //здесь идет установка внешнего вида элементов, в моем случае используется QML QObject * pList = m_pQmlObject->findChild("requestList"); m_strListView.append(tr("requesting info...")); pList->setProperty("model", m_strListView); } Ну и собственно функция, выполняемая в отдельном потоке, по сигналам которой интерфейс обновляется void Worker::slotDummyUpdatingRequest() { //dummy imitation of the work for (int i = 0; i < 5; i++) { QThread::msleep(500); // задержка emit sigDummyNextRequestStage(); qDebug() << "Updating Request..."; } } Ответ 2
Реализовано с использованием стандартных потоков (нет необходимости создавать отдельные классы, просто выполняем функцию в отдельном потоке, не прерывая выполнение GUI-потока): #include#include #include #include void blinkBackground(QWidget* w) { for (int i = 0; i < 3; ++i) { // 1 секунду показываем красный цвет. w->setStyleSheet("background-color: red;"); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 0.5 секунды показываем желтый цвет. w->setStyleSheet("background-color: yellow;"); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } } int main(int argc, char** argv) { QApplication app(argc, argv); QWidget w; w.show(); std::thread t(blinkBackground, &w); t.detach(); return app.exec(); } Похожий функционал, но используя QT Threads, можно также реализовать через QtConcurrent::run, например: void blinkBackgroundQt(QWidget* w) { for (int i = 0; i < 3; ++i) { w->setStyleSheet("background-color: red;"); QThread::msleep(1000); w->setStyleSheet("background-color: yellow;"); QThread::msleep(500); } } int main(int argc, char** argv) { ... QtConcurrent::run(blinkBackgroundQt, &w); ... } И третий способ с использованием QThread и отдельного класса был уже описан в другом ответе.
Комментариев нет:
Отправить комментарий