вопрос
От: milkpot Россия  
Дата: 15.03.22 11:03
Оценка:
Здравствуйте,
разработка идёт в версии Qt 5.6.2 + mingw-w64, ОС Windows 10 64-bit.
Вывод данных выполняется с помощью QGraphicsView, QGraphicsScene и QOpenGLWidget.
Запускается процедура отображения данных нажатием кнопки "Multiple files" и управление
передаётся в рабочую нить. В нити формируется QImage из которого получается QPixmap и выводится на экран в цикле.
Если k<2 (место _1_), то на глаз ещё можно наблюдать за тем, как отрисовывается картинка т.е. QPixmap . Если k<100, то
возникает ощущение, что картинка отрисовывается не полностью, а при k<500 всё наглядит как будто одна картинка
не отрисовалась полностью и начинает отрисовываться следующая.
Возникает вопрос, как узнать, что QPixmap отрисовался полностью и чтобы картинки отрисовывались одна после другой?

void MainWindow::displayPixmap(const QPixmap &pixmap_data)
{
    QString str;
    counter++;
    if(counter==1)
        (0);
    else {
        pScene->removeItem(graphicspixmapItem);
        delete graphicspixmapItem;
    }
    graphicspixmapItem=pScene->addPixmap(pixmap_data);
    return;
}

void MainWindow::startWorkInAThread()
{
   /* WorkerThread * */workerThread = new WorkerThread;
    connect(workerThread, &WorkerThread::resultReady,this, &MainWindow::appendtoLogListBox);
    connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap);
    connect(workerThread,SIGNAL(finished()), workerThread,SLOT(deleteLater()) );
    workerThread->initInnerObjects();
    workerThread->start();
    return;
}

void MainWindow::initializeGL()
{
    QGraphicsView* pView =ui->graphicsView;


    QRect viewRect = pView->rect();
    QRectF viewRectF(viewRect);

    pScene = new QGraphicsScene(viewRectF,this);

    pView->setScene(pScene);

    pOpenGLWidget = new QOpenGLWidget( this );
    QSurfaceFormat format_srf;
    format_srf.setDepthBufferSize(32);
    format_srf.setStencilBufferSize(16);
    format_srf.setVersion(3,2);
    format_srf.setProfile( QSurfaceFormat::CoreProfile );

    pOpenGLWidget->setFormat(format_srf);

    pView->setViewport(pOpenGLWidget);
    return;
}


class WorkerThread : public QThread
{
    Q_OBJECT
public:
    QMutex mutex;
    QWaitCondition wtc_worker2;
    void initInnerObjects()
    {
        wait_cnd=false;
        lock_cnd=false;
        fileSize=0;
    }
    void run() Q_DECL_OVERRIDE {
        QString result;
        forever {
            mutex.lock();
            qDebug() << "--- Worker: run() func, after lock call";
            wait_cnd=wtc_worker2.wait(&mutex,/*5000*/one_and_a_half_hour_wait);
            if(false==wait_cnd)
            {
                mutex.unlock();
                continue;
            }
            else if(true==wait_cnd)
            {
//                prepare_data();
                prepare_generate_data();
                result=QString(tr("--- wait_cnd is true"));
                do_send_result(result);
            }
            qDebug() << "--- wait_cnd is " << wait_cnd;
            qDebug() << "--- Worker: run() func, after wait call";
            mutex.unlock();
        }
    }
private:
    void prepare_generate_data()
    {
        QString str;
       // str.append(" --- slot button6Clicked() ");
       // appendtoLogListBox(str);
        QString filePath;
        QFile file;
        QDataStream dstrm;
        int data_quant=0;
        std::vector<unsigned short> buffer_vect;
        QSize rct_size(320,256);

        QPixmap myPixmap;

        QImage loc_img(rct_size,QImage::Format_RGB32 /*QImage::Format_RGBX8888*/);

        QRgb *line;

        pixmap_vect.clear();

        QBuffer hr;

        unsigned long/* long */ start_time=GetTickCount();
        for(int k=0;k<2;k++) // (_1_)
        for(int i=0;i<256;i++)
        {
            for(int y=0;y<loc_img.height();y++)
            {
               // QRgb *line=reinterpret_cast<QRgb*>(loc_img.scanLine(y));
                line=static_cast<QRgb *>(static_cast<void *>(loc_img.scanLine(y)));
                for(int x=0;x<loc_img.width();x++)
                {
                    if(x<256-i)
                        line[x]=qRgb(x,x,x);
                    else
                        line[x]=qRgb(0x80,0x80,0x80);
                }
            }
            pixmap_copy=QPixmap::fromImage( loc_img);
            if(b_counter==false)
            {
                b_counter=true;
            }
            else
            {
               // (_2_)
               // ::Sleep(1);
            }
            emit sendData(pixmap_copy);
        }

        unsigned long/* long */ end_time=GetTickCount();
        unsigned long/* long */ loc_delta=end_time-start_time;
         str=QString(tr("  --- loc_delta = %1")).arg(loc_delta);
         do_send_result(str);
        loc_list.clear();
        return;
    }
public /*slots*/:
    void launch_threadfunc()
    {
        wtc_worker2.wakeOne();
    }
signals:
    void resultReady(const QString &s);
    void sendData(const QPixmap &pixmap);
public slots:
    void do_send_result(const QString &info_msg)
    {
        emit resultReady(info_msg);
    }
...
};
Re: вопрос
От: SаNNy Россия  
Дата: 15.03.22 11:33
Оценка:
Попрбуйте
connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap, Qt::QueuedConnection);
Re[2]: вопрос
От: milkpot Россия  
Дата: 15.03.22 12:49
Оценка:
Здравствуйте, SаNNy, Вы писали:

SNN>Попрбуйте

SNN>
SNN>connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap, Qt::QueuedConnection);
SNN>


Попробовал, поведение программы не изменилось.
Re[3]: вопрос
От: Zhendos  
Дата: 15.03.22 13:03
Оценка: 3 (1)
Здравствуйте, milkpot, Вы писали:

M>Здравствуйте, SаNNy, Вы писали:


SNN>>Попрбуйте

SNN>>
SNN>>connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap, Qt::QueuedConnection);
SNN>>


M>Попробовал, поведение программы не изменилось.


Думаю здесь две проблемы.
Первая как уже указали есть гонка по данным.
Потому что workerThread на самом деле принадлежит не "сам" себе,
то есть "workerThread.thread()" возврашает главный поток
и функция отрисовки:
connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap);

будет вызываться не в главном потоке.

Все остальные "connect" с workerThread тоже приводят к гонке данных.
Именно поэтому рекомендует не наследовать QThread.

Вторая проблема как я понял что все отрисовывается слишком быстро и
видно части предыдущего кадра?

Думаю нужно исправить все гонки данных, а только потом с этой проблемой разбираться.
Отредактировано 17.03.2022 16:26 Zhendos . Предыдущая версия .
Re[4]: вопрос
От: milkpot Россия  
Дата: 15.03.22 15:59
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Здравствуйте, milkpot, Вы писали:


M>>Здравствуйте, SаNNy, Вы писали:


SNN>>>Попрбуйте

SNN>>>
SNN>>>connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap, Qt::QueuedConnection);
SNN>>>


M>>Попробовал, поведение программы не изменилось.


Z>Думаю здесь две проблемы.

Z>Первая как уже указали есть гонка по данным.
Z>Потому что workerThread на самом деле принадлежит не "сам" себе,
Z>то есть "workerThread.thread()" возврашает главный поток
Z>и функция отрисовки:
Z>
Z>connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap);
Z>

Z>будет вызываться в главном потоке.

Z>Все остальные "connect" с workerThread тоже приводят к гонке данных.

Z>Именно поэтому рекомендует не наследовать QThread.

Z>Вторая проблема как я понял что все отрисовывается слишком быстро и

Z>видно части предыдущего кадра?
Да. Когда k<500.

Z>Думаю нужно исправить все гонки данных, а только потом с этой проблемой разбираться.
Re[4]: вопрос
От: milkpot Россия  
Дата: 17.03.22 15:29
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Здравствуйте, milkpot, Вы писали:


M>>Здравствуйте, SаNNy, Вы писали:


SNN>>>Попрбуйте

SNN>>>
SNN>>>connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap, Qt::QueuedConnection);
SNN>>>


M>>Попробовал, поведение программы не изменилось.


Z>Думаю здесь две проблемы.

Z>Первая как уже указали есть гонка по данным.
Z>Потому что workerThread на самом деле принадлежит не "сам" себе,
Z>то есть "workerThread.thread()" возврашает главный поток
Z>и функция отрисовки:
Z>
Z>connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap);
Z>

Z>будет вызываться в главном потоке.

Z>Все остальные "connect" с workerThread тоже приводят к гонке данных.

Z>Именно поэтому рекомендует не наследовать QThread.

Z>Вторая проблема как я понял что все отрисовывается слишком быстро и

Z>видно части предыдущего кадра?

Z>Думаю нужно исправить все гонки данных, а только потом с этой проблемой разбираться.


Вот фрагмент кода с изменениями

class Worker : public QObject
{
    Q_OBJECT
public:
    QMutex mutex;
    QWaitCondition wtc_worker;
    QPixmap pixmap_copy;
    bool wait_cnd;
    bool b_counter;
public slots:
    void doWork(const QString &parameter) {
        QString result;
        bool booL_condition=true;
        b_counter=false;

        /* ... here is the expensive or blocking operation ... */
        while(booL_condition)
        {
            mutex.lock();
            wait_cnd=wtc_worker.wait(&mutex, 5400000/*one_and_a_half_hour_wait*/);
       // emit resultReady(result);
           // do_send_result(result);
           // mutex.unlock();
            if(false==wait_cnd)
            {
                result=QString(tr("*** wait_cnd Worker _ is false"));
                do_send_result(result);
                mutex.unlock();
                continue;
            }
            else if(true==wait_cnd)
            {
                prepare_generate_data();
                result=QString(tr("--- wait_cnd _ is true"));
                do_send_result(result);
                mutex.unlock();
            }

        }
    }
public:
    void prepare_generate_data()
    {
        QString str;
       // str.append(" --- slot button6Clicked() ");
       // appendtoLogListBox(str);
        QString filePath;
        QFile file;
        QDataStream dstrm;
        int data_quant=0;
        std::vector<unsigned short> buffer_vect;
        QSize rct_size(320,256);

        QPixmap myPixmap;

        QImage loc_img(rct_size,QImage::Format_RGB32 /*QImage::Format_RGBX8888*/);

        QRgb *line;

       // pixmap_vect.clear();

        QBuffer hr;

        unsigned long/* long */ start_time=GetTickCount();
        for(int k=0;k<2;k++)// (_1_)
        for(int i=0;i<256;i++)
        {
            for(int y=0;y<loc_img.height();y++)
            {
               // QRgb *line=reinterpret_cast<QRgb*>(loc_img.scanLine(y));
                line=static_cast<QRgb *>(static_cast<void *>(loc_img.scanLine(y)));
                for(int x=0;x<loc_img.width();x++)
                {
                    if(x<256-i)
                        line[x]=qRgb(x,x,x);
                    else
                        line[x]=qRgb(0x80,0x80,0x80);
                }
            }
            pixmap_copy=QPixmap::fromImage( loc_img);
            if(b_counter==false)
            {
                b_counter=true;
            }
            else
            {
               //
               // ::Sleep(1);
            }
            ;
            emit sendData(pixmap_copy);
        }

        unsigned long/* long */ end_time=GetTickCount();
        unsigned long/* long */ loc_delta=end_time-start_time;
         str=QString(tr("  --- loc_delta = %1")).arg(loc_delta);
         do_send_result(str);
       // loc_list.clear();
        return;
    }
    void do_send_result(const QString &info_msg)
    {
        emit resultReady(info_msg);
    }

signals:
    void resultReady(const QString &result);
    void sendData(const QPixmap &pixmap);
};

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
    Worker *worker;
public:
    Controller() {
        /*Worker * */worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
        connect(this, &Controller::operate, worker, &Worker::doWork);
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        connect(worker, &Worker::sendData, this, &Controller::handlePicture);
       // workerThread.start();
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
    void do_start(const QString &param )
    {
        workerThread.start();
        do_contrl_send_msg(param);
    }
    void do_contrl_send_msg(const QString &msg)
    {
        emit operate(msg);
    }
    void processWaitCond()
    {
        worker->wtc_worker.wakeOne();
    }

public slots:
    void handleResults(const QString &str1)
    {
        emit writeResults(str1);
    }
    void handlePicture(const QPixmap &pixmap)
    {
        emit writePicture(pixmap);
    }

signals:
    void operate(const QString &);
    void writeResults(const QString &);
    void writePicture(const QPixmap &pixmap);
};



class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    Controller *cntrl;
...
};

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QString str;
    counter=0;
    str.append(" --- Worker");
    cntrl=new Controller();
    if(nullptr!=cntrl)
    {
        cntrl->do_start(str);
       // b_blocking_res_value=false;
    }

    connect(this->cntrl,&Controller::writeResults,this,&MainWindow::appendtoLogListBox);
    connect(this->cntrl,&Controller::writePicture,this,&MainWindow::displayPixmap,Qt::QueuedConnection);
    initializeGL();
}
void MainWindow::initializeGL()
{
    QGraphicsView* pView =ui->graphicsView;


    QRect viewRect = pView->rect();
    QRectF viewRectF(viewRect);

    pScene = new QGraphicsScene(viewRectF,this);

    pView->setScene(pScene);

    pOpenGLWidget = new QOpenGLWidget( this );
    QSurfaceFormat format_srf;
    format_srf.setDepthBufferSize(32);
    format_srf.setStencilBufferSize(16);
    format_srf.setVersion(3,2);
    format_srf.setProfile( QSurfaceFormat::CoreProfile );

    pOpenGLWidget->setFormat(format_srf);

    pView->setViewport(pOpenGLWidget);
    return;
}
void MainWindow::displayPixmap(const QPixmap &pixmap_data)
{
    QString str;
    counter++;
    if(counter==1)
        (0);
    else {
        pScene->removeItem(graphicspixmapItem);
        delete graphicspixmapItem;
    }
    graphicspixmapItem=pScene->addPixmap(pixmap_data);
    return;
}
Re[5]: вопрос
От: Zhendos  
Дата: 17.03.22 16:32
Оценка: 3 (1)
Здравствуйте, milkpot, Вы писали:

M>Здравствуйте, Zhendos, Вы писали:



M>Вот фрагмент кода с изменениями


M>
M>class Worker : public QObject
M>    void prepare_generate_data()
M>    {
M>        QString str;
M>       // str.append(" --- slot button6Clicked() ");
M>       // appendtoLogListBox(str);
M>        QString filePath;
M>        QFile file;
M>        QDataStream dstrm;
M>        int data_quant=0;
M>        std::vector<unsigned short> buffer_vect;
M>        QSize rct_size(320,256);

M>        QPixmap myPixmap;
M>


Вообще с QPixmap не совсем безопасно работать не из главного потока,
но возможно на вашей платформе все хорошо, вот фрагмент когда самого Qt:
 if (qApp->thread() != QThread::currentThread()) {
        bool fail = false;
        if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
            printf("Platform plugin does not support threaded pixmaps!\n");
            fail = true;
        }
        if (fail) {
            qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
            return false;
        }
    }


Более надежно было бы если бы вспомогательный поток предедавал бы QImage в главный,
а уже тот (если нужно) делал из него QPixmap.
Ну теперь осталось в главном потоке сделать ограничение на FPS и все,
что-нибудь типа:
void onNewData() {
  if (delayedTimer->isActive()) {
     return;
  }
  delayedTimer->start(std::milliseconds(100));
}
Re[6]: вопрос
От: milkpot Россия  
Дата: 24.03.22 15:56
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Здравствуйте, milkpot, Вы писали:


M>>Здравствуйте, Zhendos, Вы писали:



M>>Вот фрагмент кода с изменениями


M>>
M>>class Worker : public QObject
M>>    void prepare_generate_data()
M>>    {
M>>        QString str;
M>>       // str.append(" --- slot button6Clicked() ");
M>>       // appendtoLogListBox(str);
M>>        QString filePath;
M>>        QFile file;
M>>        QDataStream dstrm;
M>>        int data_quant=0;
M>>        std::vector<unsigned short> buffer_vect;
M>>        QSize rct_size(320,256);

M>>        QPixmap myPixmap;
M>>


Z>Вообще с QPixmap не совсем безопасно работать не из главного потока,

Z>но возможно на вашей платформе все хорошо, вот фрагмент когда самого Qt:
Z>
Z> if (qApp->thread() != QThread::currentThread()) {
Z>        bool fail = false;
Z>        if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
Z>            printf("Platform plugin does not support threaded pixmaps!\n");
Z>            fail = true;
Z>        }
Z>        if (fail) {
Z>            qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
Z>            return false;
Z>        }
Z>    }
Z>


Z>Более надежно было бы если бы вспомогательный поток предедавал бы QImage в главный,

Z>а уже тот (если нужно) делал из него QPixmap.
Z>Ну теперь осталось в главном потоке сделать ограничение на FPS и все,
Z>что-нибудь типа:
Z>
Z>void onNewData() {
Z>  if (delayedTimer->isActive()) {
Z>     return;
Z>  }
Z>  delayedTimer->start(std::milliseconds(100));
Z>}
Z>


Вот исправленный код:

    void prepare_generate_data()
    {
        QString str;
       // str.append(" --- slot button6Clicked() ");
       // appendtoLogListBox(str);
        QString filePath;
        QFile file;
        QDataStream dstrm;
        int data_quant=0;
        std::vector<unsigned short> buffer_vect;
        QSize rct_size(320,256);

       // QPixmap myPixmap;

        QImage loc_img(rct_size,QImage::Format_RGB32 /*QImage::Format_RGBX8888*/);

        QRgb *line;

       // pixmap_vect.clear();

        QBuffer hr;

        unsigned long/* long */ start_time=GetTickCount();
        for(int k=0;k<5;k++)
        for(int i=0;i<256;i++)
        {
            for(int y=0;y<loc_img.height();y++)
            {
               // QRgb *line=reinterpret_cast<QRgb*>(loc_img.scanLine(y));
                line=static_cast<QRgb *>(static_cast<void *>(loc_img.scanLine(y)));
                for(int x=0;x<loc_img.width();x++)
                {
                    if(x<256-i)
                        line[x]=qRgb(x,x,x);
                    else
                        line[x]=qRgb(0x80,0x80,0x80);
                }
            }
           // pixmap_copy=QPixmap::fromImage( loc_img);
            if(b_counter==false)
            {
                b_counter=true;
            }
            else
            {
               //
               // ::Sleep(1);
            }
            ;
            emit sendData(loc_img/*pixmap_copy*/);
        }

        unsigned long/* long */ end_time=GetTickCount();
        unsigned long/* long */ loc_delta=end_time-start_time;
         str=QString(tr("  --- loc_delta = %1")).arg(loc_delta);
         do_send_result(str);
       // loc_list.clear();
        return;
    }



class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    Controller *cntrl;
    QTimer *timer;
...
};

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QString str;
    counter=0;
    counter_img=0;
    str.append(" --- Worker");
    cntrl=new Controller();
    if(nullptr!=cntrl)
    {
        cntrl->do_start(str);
       // b_blocking_res_value=false;
    }

    connect(this->cntrl,&Controller::writeResults,this,&MainWindow::appendtoLogListBox);
    connect(this->cntrl,&Controller::writePicture,this,&MainWindow::displayImage,Qt::QueuedConnection);
    timer = new QTimer(this);
   // connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    connect(timer, SIGNAL(timeout()), this, SLOT(printData()));
    initializeGL();
}

void MainWindow::displayImage(const QImage &image_data)
{
    QString str;
    counter_img++;
    if(counter_img==1)
        (0);
    else {
        pScene->removeItem(graphicspixmapItem);
        delete graphicspixmapItem;
    }
    pixmap_copy=QPixmap::fromImage( image_data/*loc_img*/);
    graphicspixmapItem=pScene->addPixmap(pixmap_copy/*pixmap_data*/);
    //---
        if (timer->isActive()) {
          return;
        }
        timer->start(100);

}
void MainWindow::printData()
{
    QString str;
    str=QString(tr("  --- printData"));
    appendtoLogListBox(str);
    timer->stop();
    return;
}
Отредактировано 25.03.2022 14:09 milkpot . Предыдущая версия .
Re[6]: вопрос
От: milkpot Россия  
Дата: 25.03.22 14:39
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Здравствуйте, milkpot, Вы писали:


M>>Здравствуйте, Zhendos, Вы писали:



M>>Вот фрагмент кода с изменениями


M>>
M>>class Worker : public QObject
M>>    void prepare_generate_data()
M>>    {
M>>        QString str;
M>>       // str.append(" --- slot button6Clicked() ");
M>>       // appendtoLogListBox(str);
M>>        QString filePath;
M>>        QFile file;
M>>        QDataStream dstrm;
M>>        int data_quant=0;
M>>        std::vector<unsigned short> buffer_vect;
M>>        QSize rct_size(320,256);

M>>        QPixmap myPixmap;
M>>


Z>Вообще с QPixmap не совсем безопасно работать не из главного потока,

Z>но возможно на вашей платформе все хорошо, вот фрагмент когда самого Qt:
Z>
Z> if (qApp->thread() != QThread::currentThread()) {
Z>        bool fail = false;
Z>        if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
Z>            printf("Platform plugin does not support threaded pixmaps!\n");
Z>            fail = true;
Z>        }
Z>        if (fail) {
Z>            qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
Z>            return false;
Z>        }
Z>    }
Z>


Z>Более надежно было бы если бы вспомогательный поток предедавал бы QImage в главный,

Z>а уже тот (если нужно) делал из него QPixmap.
Z>Ну теперь осталось в главном потоке сделать ограничение на FPS и все,
Z>что-нибудь типа:
Z>
Z>void onNewData() {
Z>  if (delayedTimer->isActive()) {
Z>     return;
Z>  }
Z>  delayedTimer->start(std::milliseconds(100));
Z>}
Z>


Вот исправленный код:

    void prepare_generate_data()
    {
        QString str;
       // str.append(" --- slot button6Clicked() ");
       // appendtoLogListBox(str);
        QString filePath;
        QFile file;
        QDataStream dstrm;
        int data_quant=0;
        std::vector<unsigned short> buffer_vect;
        QSize rct_size(320,256);

       // QPixmap myPixmap;

        QImage loc_img(rct_size,QImage::Format_RGB32 /*QImage::Format_RGBX8888*/);

        QRgb *line;

       // pixmap_vect.clear();

        QBuffer hr;

        unsigned long/* long */ start_time=GetTickCount();
        for(int k=0;k<5;k++)
        for(int i=0;i<256;i++)
        {
            for(int y=0;y<loc_img.height();y++)
            {
               // QRgb *line=reinterpret_cast<QRgb*>(loc_img.scanLine(y));
                line=static_cast<QRgb *>(static_cast<void *>(loc_img.scanLine(y)));
                for(int x=0;x<loc_img.width();x++)
                {
                    if(x<256-i)
                        line[x]=qRgb(x,x,x);
                    else
                        line[x]=qRgb(0x80,0x80,0x80);
                }
            }
           // pixmap_copy=QPixmap::fromImage( loc_img);
            if(b_counter==false)
            {
                b_counter=true;
            }
            else
            {
               //
               // ::Sleep(1);
            }
            ;
            emit sendData(loc_img/*pixmap_copy*/);
        }

        unsigned long/* long */ end_time=GetTickCount();
        unsigned long/* long */ loc_delta=end_time-start_time;
         str=QString(tr("  --- loc_delta = %1")).arg(loc_delta);
         do_send_result(str);
       // loc_list.clear();
        return;
    }



class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    Controller *cntrl;
    QTimer *timer;
...
};

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QString str;
    counter=0;
    counter_img=0;
    str.append(" --- Worker");
    cntrl=new Controller();
    if(nullptr!=cntrl)
    {
        cntrl->do_start(str);
       // b_blocking_res_value=false;
    }

    connect(this->cntrl,&Controller::writeResults,this,&MainWindow::appendtoLogListBox);
    connect(this->cntrl,&Controller::writePicture,this,&MainWindow::displayImage,Qt::QueuedConnection);
    timer = new QTimer(this);
   // connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    connect(timer, SIGNAL(timeout()), this, SLOT(printData()));
    initializeGL();
}

void MainWindow::displayImage(const QImage &image_data)
{
    QString str;
    counter_img++;
    if(counter_img==1)
        (0);
    else {
        pScene->removeItem(graphicspixmapItem);
        delete graphicspixmapItem;
    }
    pixmap_copy=QPixmap::fromImage( image_data/*loc_img*/);
    graphicspixmapItem=pScene->addPixmap(pixmap_copy/*pixmap_data*/);
    //---
        if (timer->isActive()) {
          return;
        }
        timer->start(100);

}
void MainWindow::printData()
{
    QString str;
    str=QString(tr("  --- printData"));
    appendtoLogListBox(str);
    timer->stop();
    return;
}
Re: вопрос
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 26.03.22 01:06
Оценка: 3 (1)
Здравствуйте, milkpot, Вы писали:

M>Запускается процедура отображения данных нажатием кнопки "Multiple files" и управление

M>передаётся в рабочую нить. В нити формируется QImage из которого получается QPixmap и выводится на экран в цикле.
У тебя изначальна неверная концепция приложения. Такой рендеринг всегда организуется через render loop где и происходит реальная отрисовка/свап данных. Посмотри примеры 2drendering или 3d пример какой-то где они рисуют треугольники, либо очень внимательно почитай описания QGraphicsView, QGraphicsScene и QOpenGLWidget, ЕМНИП, надо перегружать painEvent в одном из классов и внутри его уже, по-готовности, свапать/рисовать в зависимости от подхода.
Алгоритм должен быть примерно такой. Ты жмякаешь кнопку, у тебя просыпается тред подготовки данных. По готовности этот тред выставляет флаг или перебрасывает указатель на то, что подготовлено в сигнале через эвент луп(QueuedConnection) чтобы не было вопросов гонки. После этого (я точно не помню надо ли принудительно дёрнуть update чтобы painEvent вызывался, давно такое делал) твой рендер луп внутри painEvent читает флаг или понимает, что пришли новые данные, и рисует по ним новый фрейм который OGL машина тебе показывает.
С QThread лучше не работать если используешь QObject-derived т.к. у него есть какие-то заморочки при передаче таких объектов между q-тредами. Не забывай, что вся работа с OGL должна осуществляться в основном треде приложения.
Sic luceat lux!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.