简介:界面线程是主线程,工作线程负责绘制图像,然后通过使用信号槽的方式传递给界面线程进行显示。
工作线程与界面线程之间的信号槽
connect(&thread, SIGNAL(renderedImage(QImage,double)), this, SLOT(updatePixmap(QImage,double)));
工作线程重写run函数,实现图像绘制
//! [3]
void RenderThread::run()
{
forever {
mutex.lock();
QSize resultSize = this->resultSize;
double scaleFactor = this->scaleFactor;
double centerX = this->centerX;
double centerY = this->centerY;
mutex.unlock();
//! [3]
//! [4]
int halfWidth = resultSize.width() / 2;
//! [4] //! [5]
int halfHeight = resultSize.height() / 2;
QImage image(resultSize, QImage::Format_RGB32);
const int NumPasses = 8;
int pass = 0;
while (pass < NumPasses) {
const int MaxIterations = (1 << (2 * pass + 6)) + 32;
const int Limit = 4;
bool allBlack = true;
for (int y = -halfHeight; y < halfHeight; ++y) {
if (restart)
break;
if (abort)
return;
uint *scanLine =
reinterpret_cast<uint *>(image.scanLine(y + halfHeight));
double ay = centerY + (y * scaleFactor);
for (int x = -halfWidth; x < halfWidth; ++x) {
double ax = centerX + (x * scaleFactor);
double a1 = ax;
double b1 = ay;
int numIterations = 0;
do {
++numIterations;
double a2 = (a1 * a1) - (b1 * b1) + ax;
double b2 = (2 * a1 * b1) + ay;
if ((a2 * a2) + (b2 * b2) > Limit)
break;
++numIterations;
a1 = (a2 * a2) - (b2 * b2) + ax;
b1 = (2 * a2 * b2) + ay;
if ((a1 * a1) + (b1 * b1) > Limit)
break;
} while (numIterations < MaxIterations);
if (numIterations < MaxIterations) {
*scanLine++ = colormap[numIterations % ColormapSize];
allBlack = false;
} else {
*scanLine++ = qRgb(0, 0, 0);
}
}
}
if (allBlack && pass == 0) {
pass = 4;
} else {
if (!restart)
emit renderedImage(image, scaleFactor);
//! [5] //! [6]
++pass;
}
//! [6] //! [7]
}
//! [7]
//! [8]
mutex.lock();
//! [8] //! [9]
if (!restart)
condition.wait(&mutex);
restart = false;
mutex.unlock();
}
}
界面线程重写鼠标移动、鼠标*移动等函数,实现改变绘图焦点
#ifndef QT_NO_WHEELEVENT
//! [12]
void MandelbrotWidget::wheelEvent(QWheelEvent *event)
{
int numDegrees = event->delta() / 8;
double numSteps = numDegrees / 15.0f;
zoom(pow(ZoomInFactor, numSteps));
}
//! [12]
#endif
//! [13]
void MandelbrotWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
lastDragPos = event->pos();
}
//! [13]
//! [14]
void MandelbrotWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
pixmapOffset += event->pos() - lastDragPos;
lastDragPos = event->pos();
update();
}
}
通过这个示例,我们知道了在qt中如何添加工作线程,并与界面线程进行交互。使用线程还有一些细节,比如锁还有条件锁。
举例:条件锁
在run函数里condition.wait(&mutex);使程序卡住,然后在render中触发condition.wakeOne();使得程序在卡住的地方继续运行。