Здравствуйте,
разработка идёт в версии 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 ¶meter) {
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 ¶m )
{
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);
};
//--------------------------------------------------------------