#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 и отдельного класса был уже описан в другом ответе.
Комментариев нет:
Отправить комментарий