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

//! [0]
Window::Window()
{
    setWindowTitle(tr("2D Painting on Native and OpenGL Widgets"));

    Widget *native = new Widget(&helper, this);
    GLWidget *openGL = new GLWidget(&helper, this);
    //---
    //GLWidget *openGL2 = new GLWidget(&helper, this);
    //
    QLabel *nativeLabel = new QLabel(tr("Native"));
    nativeLabel->setAlignment(Qt::AlignHCenter);
    QLabel *openGLLabel = new QLabel(tr("OpenGL"));
    openGLLabel->setAlignment(Qt::AlignHCenter);
    //---
    listWidget=new QListWidget(this);

    QPushButton *button = new QPushButton(tr("&Push"),this);
    button->setMaximumWidth(80 );
    button->setMaximumHeight(30);
    QPushButton *button_2 = new QPushButton(tr("Cl&ean"),this);
    button_2->setMaximumWidth(80 );
    button_2->setMaximumHeight(30);
    QPushButton *button_3 = new QPushButton(tr("&Send"),this);
    button_3->setMaximumWidth(80 );
    button_3->setMaximumHeight(30);
    //

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(native, 0, 0);
    layout->addWidget(openGL, 0, 1);
    layout->addWidget(nativeLabel, 1, 0);
    layout->addWidget(openGLLabel, 1, 1);
    //---
    layout->addWidget(listWidget/*openGL2*/, 2,0);
    layout->addWidget(button, 2,1);
    //-
    layout->addWidget(button_2,3,0);
    layout->addWidget(button_3,3,1);
//    layout->addWidget(button, 2,0);
    //---
    setLayout(layout);

    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, native, &Widget::animate);
    connect(timer, &QTimer::timeout, openGL, &GLWidget::animate);
    //---
    /*connect(timer, &QTimer::timeout, openGL2, &GLWidget::animate); */
   // timer->start(50);
    timer->start(10);
    QString str,str2;
    str.append(" --- Worker");
    cntrl=new Controller();
    if(nullptr!=cntrl)
    {
        cntrl->do_start(str);
       // b_blocking_res_value=false;
    }
    connect(this->cntrl,&Controller::writeResults,this,&Window::appendtoLogListBox);
   // connect(this->cntrl,&Controller::writePicture,this,&MainWindow::displayPixmap,Qt::QueuedConnection);
    //connect(button,&QPushButton::clicked,this,&Window::launch);
    connect(button, SIGNAL(clicked()), this, SLOT(launch()));
    connect(button_2, SIGNAL(clicked()), listWidget, SLOT(clear()));
    connect(this->cntrl,&Controller::writePicture,this,&Window::displayImage,Qt::QueuedConnection);
}
//! [0]

void Window::displayImage(const QImage& img)
{
    img1=img;
    helper.img2=img1;
   // update();
   // qDebug() << "--- displayImage func";
    return;
}
void Window::launch()
{
    cntrl->processWaitCond();
    qDebug() << "--- launch Worker: doWork func";
    return;
}
void Window::appendtoLogListBox(const QString &str )
{
    listWidget->addItem(str);
    listWidget->scrollToBottom();
    return;
}

//--------------------------------------------------
class Helper
{
public:
    Helper();
    QImage img2;

public:
    void paint(QPainter *painter, QPaintEvent *event, int elapsed);
};

void Helper::paint(QPainter *painter, QPaintEvent *event, int elapsed)
{

    painter->translate(-1, 0);
    painter->drawImage(event->rect()/*320,256*/,img2);
}

//--------------------------------------------------
class GLWidget : public QOpenGLWidget
{
    Q_OBJECT

public:
    GLWidget(Helper *helper, QWidget *parent);

public slots:
    void animate();

protected:
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

private:
    Helper *helper;
    int elapsed;
    QTime m_time;//new
    int m_frames;//new
    QSurfaceFormat format1;
};

//! [0]
GLWidget::GLWidget(Helper *helper, QWidget *parent)
    : QOpenGLWidget(parent), helper(helper)
{
    elapsed = 0;
    m_frames=0;//init
   // setFixedSize(200, 200);
    setFixedSize(320, 256);
    setAutoFillBackground(false);
    format1.setDepthBufferSize(32);
    format1.setStencilBufferSize(16);
    format1.setVersion(3, 2);
    format1.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
    format1.setProfile(QSurfaceFormat::CoreProfile);
    setFormat(format1);
}
//! [0]

//! [1]
void GLWidget::animate()
{
    elapsed = (elapsed + qobject_cast<QTimer*>(sender())->interval()) % 1000;
    update();
}
//! [1]

//! [2]
void GLWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter;
    painter.begin(this);
    painter.setRenderHint(QPainter::Antialiasing);
    helper->paint(&painter, event, elapsed);
    //--- new
    if (const int elapsed_a = m_time.elapsed()) {
        QString framesPerSecond;
        framesPerSecond.setNum(m_frames /(elapsed_a / 1000.0), 'f', 2);
        painter.setPen(/*m_transparent ? Qt::black :*/ Qt::white);
        painter.drawText(20, 40, framesPerSecond + " paintGL calls / s");
    }
    //---
    ;
    painter.end();
    //--- new
    if (!(m_frames % 100)) {
        m_time.start();
        m_frames = 0;
    }
    // m_fAngle += 1.0f;
    ++m_frames;
    //---
}
//! [2]

//-------------------------------------------------------
//Рабочая нить
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();
            }

        }
    }
//private:
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<100;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(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;
    }
    void do_send_result(const QString &info_msg)
    {
        emit resultReady(info_msg);
    }

signals:
    void resultReady(const QString &result);
    void sendData(const /*QPixmap*/QImage &image);
};

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();
       // worker->doWork(QString(tr(" --- Controller: (1) do_start")));
       // do_contrl_send_msg(QString(tr(" --- Controller: (2) do_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 QImage/*QPixmap*/ &image)
    {
        emit writePicture(image);
    }

signals:
    void operate(const QString &);
    void writeResults(const QString &);
    void writePicture(const QImage/*QPixmap*/ &image);
};

//--------------------------------------------------------------
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.