При работе приложения с оконным интерфейсом важно обеспечить отсутствие зависаний. Для этого сложные вычисления стоит запускать в отдельной нити. Концепция многопоточного приложения отлично сочетается с подходом сигналы-слоты Qt, при этом совершенно не нужно переопределять никакой метод run().
Основная идея. В многопоточном приложении вычисления проводятся в отдельной ните, по окончанию излучается сигнал, передающий результат в своих аргументах. Слот, принадлежащий уже MainWindow, будет вызван. Результаты вычислений окажутся в аргументах слота и не составит труда вывести их.
Проводя аналогию с микроконтроллерами, сигнал — это переход по вектору прерывания, а слот — сам обработчик прерывания. Чтобы возникло «прерывание», сигнал необходимо излучить: emit mysignalvoid(); тогда Qt начнёт искать ему «обработчик» (слот). В Qt можно на один сигнал повесить много слотов.
На следующем рисунке представлен алгоритм работы демонстрационного приложения. Нить обработки ежесекундно опрашивает по легенде USB HID устройство. Затем излучается (emit) сигнал, который обрабатывает слот, принадлежащий уже MainWindow и имеющий соответственно возможность рисовать на форме.
Итак, имеем классы, способные использовать подход сигналы-слоты. Для этого в их объявлении используется макрос Q_OBJECT.
class Worker : public QObject
{
Q_OBJECT //теперь можем использовать сигналы-слоты в классе
public:
QTimer *timerDeviceRead; //будем каждую секунду вызывать собственный слот GuiUpdateCallback
Worker();
public slots:
void updateElectropipData();
signals:
void GuiUpdatePlease(uint8_t const *arrptr,size_t);
};
class MainWindow : public QMainWindow //класс окна с GUI
{
Q_OBJECT
public slots:
void GuiUpdateCallback(uint8_t const *arrptr, size_t);
private:
Ui::MainWindow *ui; //доступ к кнопкам и иже с ними
QThread *thread;
Worker::Worker(){
qRegisterMetaType<std::size_t>("size_t");
qRegisterMetaType<uint8_t const *>("uint8_t const *");
this->timerDeviceRead = new QTimer();
connect(Worker::timerDeviceRead, &QTimer::timeout, this, &Worker::updateUSBDataCallback);
this->timerDeviceRead->start();
void Worker::updateUSBDataCallback(){
size_t mysize = 65;
uint8_t buf[65] = { "I like USB HID" };
emit GuiUpdatePlease(buf,mysize); //излучение сигнала
//Подмена:
for(int i =0;i<64;i++){
buf[i]=i+'0';
if (i+'0' > 250) i=0;
}
}
MainWindow::MainWindow{
connect(worker, &Worker::GuiUpdatePlease, this, &MainWindow::GuiUpdateCallback, Qt::BlockingQueuedConnection);
typedef uint8_t const * TU8PTR;
К сожалению, не доступен сервер mySQL