MandelbrotWidget Class Reference

#include <mandelbrotwidget.h>

Inheritance diagram for MandelbrotWidget:

Inheritance graph
[legend]
Collaboration diagram for MandelbrotWidget:

Collaboration graph
[legend]
List of all members.

Detailed Description

Definition at line 32 of file mandelbrotwidget.h.

Public Member Functions

 MandelbrotWidget (QWidget *parent=0)

Protected Member Functions

void paintEvent (QPaintEvent *event)
void resizeEvent (QResizeEvent *event)
void keyPressEvent (QKeyEvent *event)
void wheelEvent (QWheelEvent *event)
void mousePressEvent (QMouseEvent *event)
void mouseMoveEvent (QMouseEvent *event)
void mouseReleaseEvent (QMouseEvent *event)

Private Slots

void updatePixmap (const QImage &image, double scaleFactor)

Private Member Functions

void zoom (double zoomFactor)
void scroll (int deltaX, int deltaY)

Private Attributes

RenderThread thread
QPixmap pixmap
QPoint pixmapOffset
QPoint lastDragPos
double centerX
double centerY
double pixmapScale
double curScale


Constructor & Destructor Documentation

MandelbrotWidget::MandelbrotWidget ( QWidget parent = 0  ) 

Definition at line 38 of file mandelbrotwidget.cpp.

References centerX, centerY, QObject::connect(), Qt::CrossCursor, curScale, DefaultCenterX, DefaultCenterY, DefaultScale, pixmapScale, QWidget::resize(), QWidget::setCursor(), QWidget::setWindowTitle(), SIGNAL, SLOT, QObject::thread(), and updatePixmap().

00039     : QWidget(parent)
00040 {
00041     centerX = DefaultCenterX;
00042     centerY = DefaultCenterY;
00043     pixmapScale = DefaultScale;
00044     curScale = DefaultScale;
00045 
00046     qRegisterMetaType<QImage>("QImage");
00047     connect(&thread, SIGNAL(renderedImage(const QImage &, double)),
00048             this, SLOT(updatePixmap(const QImage &, double)));
00049 
00050     setWindowTitle(tr("Mandelbrot"));
00051     setCursor(Qt::CrossCursor);
00052     resize(550, 400);
00053 }

Here is the call graph for this function:


Member Function Documentation

void MandelbrotWidget::paintEvent ( QPaintEvent event  )  [protected, virtual]

This event handler can be reimplemented in a subclass to receive paint events which are passed in the event parameter.

A paint event is a request to repaint all or part of the widget. It can happen as a result of repaint() or update(), or because the widget was obscured and has now been uncovered, or for many other reasons.

Many widgets can simply repaint their entire surface when asked to, but some slow widgets need to optimize by painting only the requested region: QPaintEvent::region(). This speed optimization does not change the result, as painting is clipped to that region during event processing. QListView and QTableView do this, for example.

Qt also tries to speed up painting by merging multiple paint events into one. When update() is called several times or the window system sends several paint events, Qt merges these events into one event with a larger region (see QRegion::united()). repaint() does not permit this optimization, so we suggest using update() whenever possible.

When the paint event occurs, the update region has normally been erased, so that you're painting on the widget's background.

The background can be set using setBackgroundRole() and setPalette().

From Qt 4.0, QWidget automatically double-buffers its painting, so there's no need to write double-buffering code in paintEvent() to avoid flicker.

Note: Under X11 it is possible to toggle the global double buffering by calling qt_x11_set_global_double_buffer(). Example usage:

See also:
event(), repaint(), update(), QPainter, QPixmap, QPaintEvent, {Analog Clock Example}

Reimplemented from QWidget.

Definition at line 55 of file mandelbrotwidget.cpp.

References QRect::adjusted(), Qt::AlignCenter, Qt::black, curScale, QPainter::drawPixmap(), QPainter::drawRect(), QPainter::drawText(), QPainter::fillRect(), QPainter::fontMetrics(), QPixmap::height(), int, QMatrix::inverted(), QPixmap::isNull(), QMatrix::mapRect(), QPainter::matrix(), metrics(), Qt::NoPen, pixmap, pixmapOffset, pixmapScale, QWidget::rect(), QPainter::restore(), QPainter::save(), QPainter::scale(), QPainter::setBrush(), QPainter::setPen(), QPainter::translate(), Qt::white, QPixmap::width(), QWidget::width(), QPoint::x(), and QPoint::y().

00056 {
00057     QPainter painter(this);
00058     painter.fillRect(rect(), Qt::black);
00059 
00060     if (pixmap.isNull()) {
00061         painter.setPen(Qt::white);
00062         painter.drawText(rect(), Qt::AlignCenter,
00063                          tr("Rendering initial image, please wait..."));
00064         return;
00065     }
00066 
00067     if (curScale == pixmapScale) {
00068         painter.drawPixmap(pixmapOffset, pixmap);
00069     } else {
00070         double scaleFactor = pixmapScale / curScale;
00071         int newWidth = int(pixmap.width() * scaleFactor);
00072         int newHeight = int(pixmap.height() * scaleFactor);
00073         int newX = pixmapOffset.x() + (pixmap.width() - newWidth) / 2;
00074         int newY = pixmapOffset.y() + (pixmap.height() - newHeight) / 2;
00075 
00076         painter.save();
00077         painter.translate(newX, newY);
00078         painter.scale(scaleFactor, scaleFactor);
00079         QRectF exposed = painter.matrix().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1);
00080         painter.drawPixmap(exposed, pixmap, exposed);
00081         painter.restore();
00082     }
00083 
00084     QString text = tr("Use mouse wheel to zoom. "
00085                       "Press and hold left mouse button to scroll.");
00086     QFontMetrics metrics = painter.fontMetrics();
00087     int textWidth = metrics.width(text);
00088 
00089     painter.setPen(Qt::NoPen);
00090     painter.setBrush(QColor(0, 0, 0, 127));
00091     painter.drawRect((width() - textWidth) / 2 - 5, 0, textWidth + 10,
00092                      metrics.lineSpacing() + 5);
00093     painter.setPen(Qt::white);
00094     painter.drawText((width() - textWidth) / 2,
00095                      metrics.leading() + metrics.ascent(), text);
00096 }

Here is the call graph for this function:

void MandelbrotWidget::resizeEvent ( QResizeEvent event  )  [protected, virtual]

This event handler can be reimplemented in a subclass to receive widget resize events which are passed in the event parameter. When resizeEvent() is called, the widget already has its new geometry. The old size is accessible through QResizeEvent::oldSize().

The widget will be erased and receive a paint event immediately after processing the resize event. No drawing need be (or should be) done inside this handler.

See also:
moveEvent(), event(), resize(), QResizeEvent, paintEvent(), {Scribble Example}

Reimplemented from QWidget.

Definition at line 98 of file mandelbrotwidget.cpp.

References centerX, centerY, curScale, QWidget::size(), and QObject::thread().

00099 {
00100     thread.render(centerX, centerY, curScale, size());
00101 }

Here is the call graph for this function:

void MandelbrotWidget::keyPressEvent ( QKeyEvent event  )  [protected, virtual]

This event handler, for event event, can be reimplemented in a subclass to receive key press events for the widget.

A widget must call setFocusPolicy() to accept focus initially and have focus in order to receive a key press event.

If you reimplement this handler, it is very important that you ignore() the event if you do not understand it, so that the widget's parent can interpret it.

The default implementation closes popup widgets if the user presses Esc. Otherwise the event is ignored.

See also:
keyReleaseEvent(), QKeyEvent::ignore(), setFocusPolicy(), focusInEvent(), focusOutEvent(), event(), QKeyEvent, {Tetrix Example}

Reimplemented from QWidget.

Definition at line 103 of file mandelbrotwidget.cpp.

References QWidget::event(), Qt::Key_Down, Qt::Key_Left, Qt::Key_Minus, Qt::Key_Plus, Qt::Key_Right, Qt::Key_Up, QWidget::keyPressEvent(), scroll(), ScrollStep, zoom(), ZoomInFactor, and ZoomOutFactor.

00104 {
00105     switch (event->key()) {
00106     case Qt::Key_Plus:
00107         zoom(ZoomInFactor);
00108         break;
00109     case Qt::Key_Minus:
00110         zoom(ZoomOutFactor);
00111         break;
00112     case Qt::Key_Left:
00113         scroll(-ScrollStep, 0);
00114         break;
00115     case Qt::Key_Right:
00116         scroll(+ScrollStep, 0);
00117         break;
00118     case Qt::Key_Down:
00119         scroll(0, -ScrollStep);
00120         break;
00121     case Qt::Key_Up:
00122         scroll(0, +ScrollStep);
00123         break;
00124     default:
00125         QWidget::keyPressEvent(event);
00126     }
00127 }

Here is the call graph for this function:

void MandelbrotWidget::wheelEvent ( QWheelEvent event  )  [protected, virtual]

This event handler, for event event, can be reimplemented in a subclass to receive wheel events for the widget.

If you reimplement this handler, it is very important that you ignore() the event if you do not handle it, so that the widget's parent can interpret it.

The default implementation ignores the event.

See also:
QWheelEvent::ignore(), QWheelEvent::accept(), event(), QWheelEvent

Reimplemented from QWidget.

Definition at line 129 of file mandelbrotwidget.cpp.

References QWidget::event(), zoom(), and ZoomInFactor.

00130 {
00131     int numDegrees = event->delta() / 8;
00132     double numSteps = numDegrees / 15.0f;
00133     zoom(pow(ZoomInFactor, numSteps));
00134 }

Here is the call graph for this function:

void MandelbrotWidget::mousePressEvent ( QMouseEvent event  )  [protected, virtual]

This event handler, for event event, can be reimplemented in a subclass to receive mouse press events for the widget.

If you create new widgets in the mousePressEvent() the mouseReleaseEvent() may not end up where you expect, depending on the underlying window system (or X11 window manager), the widgets' location and maybe more.

The default implementation implements the closing of popup widgets when you click outside the window. For other widget types it does nothing.

See also:
mouseReleaseEvent(), mouseDoubleClickEvent(), mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}

Reimplemented from QWidget.

Definition at line 136 of file mandelbrotwidget.cpp.

References QWidget::event(), lastDragPos, and Qt::LeftButton.

00137 {
00138     if (event->button() == Qt::LeftButton)
00139         lastDragPos = event->pos();
00140 }

Here is the call graph for this function:

void MandelbrotWidget::mouseMoveEvent ( QMouseEvent event  )  [protected, virtual]

This event handler, for event event, can be reimplemented in a subclass to receive mouse move events for the widget.

If mouse tracking is switched off, mouse move events only occur if a mouse button is pressed while the mouse is being moved. If mouse tracking is switched on, mouse move events occur even if no mouse button is pressed.

QMouseEvent::pos() reports the position of the mouse cursor, relative to this widget. For press and release events, the position is usually the same as the position of the last mouse move event, but it might be different if the user's hand shakes. This is a feature of the underlying window system, not Qt.

See also:
setMouseTracking(), mousePressEvent(), mouseReleaseEvent(), mouseDoubleClickEvent(), event(), QMouseEvent, {Scribble Example}

Reimplemented from QWidget.

Definition at line 142 of file mandelbrotwidget.cpp.

References QWidget::event(), lastDragPos, Qt::LeftButton, pixmapOffset, and QWidget::update().

00143 {
00144     if (event->buttons() & Qt::LeftButton) {
00145         pixmapOffset += event->pos() - lastDragPos;
00146         lastDragPos = event->pos();
00147         update();
00148     }
00149 }

Here is the call graph for this function:

void MandelbrotWidget::mouseReleaseEvent ( QMouseEvent event  )  [protected, virtual]

This event handler, for event event, can be reimplemented in a subclass to receive mouse release events for the widget.

See also:
mousePressEvent(), mouseDoubleClickEvent(), mouseMoveEvent(), event(), QMouseEvent, {Scribble Example}

Reimplemented from QWidget.

Definition at line 151 of file mandelbrotwidget.cpp.

References QWidget::event(), QPixmap::height(), QWidget::height(), lastDragPos, Qt::LeftButton, pixmap, pixmapOffset, scroll(), QPixmap::width(), QWidget::width(), QPoint::x(), and QPoint::y().

00152 {
00153     if (event->button() == Qt::LeftButton) {
00154         pixmapOffset += event->pos() - lastDragPos;
00155         lastDragPos = QPoint();
00156 
00157         int deltaX = (width() - pixmap.width()) / 2 - pixmapOffset.x();
00158         int deltaY = (height() - pixmap.height()) / 2 - pixmapOffset.y();
00159         scroll(deltaX, deltaY);
00160     }
00161 }

Here is the call graph for this function:

void MandelbrotWidget::updatePixmap ( const QImage image,
double  scaleFactor 
) [private, slot]

Definition at line 163 of file mandelbrotwidget.cpp.

References QPixmap::fromImage(), image, QPoint::isNull(), lastDragPos, pixmap, pixmapOffset, pixmapScale, and QWidget::update().

Referenced by MandelbrotWidget().

00164 {
00165     if (!lastDragPos.isNull())
00166         return;
00167 
00168     pixmap = QPixmap::fromImage(image);
00169     pixmapOffset = QPoint();
00170     lastDragPos = QPoint();
00171     pixmapScale = scaleFactor;
00172     update();
00173 }

void MandelbrotWidget::zoom ( double  zoomFactor  )  [private]

Definition at line 175 of file mandelbrotwidget.cpp.

References centerX, centerY, curScale, QWidget::size(), QObject::thread(), and QWidget::update().

Referenced by keyPressEvent(), and wheelEvent().

00176 {
00177     curScale *= zoomFactor;
00178     update();
00179     thread.render(centerX, centerY, curScale, size());
00180 }

Here is the call graph for this function:

void MandelbrotWidget::scroll ( int  deltaX,
int  deltaY 
) [private]

Scrolls the widget including its children dx pixels to the right and dy downward. Both dx and dy may be negative.

After scrolling, the widgets will receive paint events for the areas that need to be repainted. For widgets that Qt knows to be opaque, this is only the newly exposed parts. For example, if an opaque widget is scrolled 8 pixels to the left, only an 8-pixel wide stripe at the right edge needs updating.

Since widgets propagate the contents of their parents by default, you need to set the autoFillBackground property, or use setAttribute() to set the Qt::WA_OpaquePaintEvent attribute, to make a widget opaque.

For widgets that use contents propagation, a scroll will cause an update of the entire scroll area.

See also:
{Transparency and Double Buffering}

Reimplemented from QWidget.

Definition at line 182 of file mandelbrotwidget.cpp.

References centerX, centerY, curScale, QWidget::size(), QObject::thread(), and QWidget::update().

Referenced by keyPressEvent(), and mouseReleaseEvent().

00183 {
00184     centerX += deltaX * curScale;
00185     centerY += deltaY * curScale;
00186     update();
00187     thread.render(centerX, centerY, curScale, size());
00188 }

Here is the call graph for this function:


Member Data Documentation

RenderThread MandelbrotWidget::thread [private]

Definition at line 55 of file mandelbrotwidget.h.

QPixmap MandelbrotWidget::pixmap [private]

Definition at line 56 of file mandelbrotwidget.h.

Referenced by mouseReleaseEvent(), paintEvent(), and updatePixmap().

QPoint MandelbrotWidget::pixmapOffset [private]

Definition at line 57 of file mandelbrotwidget.h.

Referenced by mouseMoveEvent(), mouseReleaseEvent(), paintEvent(), and updatePixmap().

QPoint MandelbrotWidget::lastDragPos [private]

Definition at line 58 of file mandelbrotwidget.h.

Referenced by mouseMoveEvent(), mousePressEvent(), mouseReleaseEvent(), and updatePixmap().

double MandelbrotWidget::centerX [private]

Definition at line 59 of file mandelbrotwidget.h.

Referenced by MandelbrotWidget(), resizeEvent(), scroll(), and zoom().

double MandelbrotWidget::centerY [private]

Definition at line 60 of file mandelbrotwidget.h.

Referenced by MandelbrotWidget(), resizeEvent(), scroll(), and zoom().

double MandelbrotWidget::pixmapScale [private]

Definition at line 61 of file mandelbrotwidget.h.

Referenced by MandelbrotWidget(), paintEvent(), and updatePixmap().

double MandelbrotWidget::curScale [private]

Definition at line 62 of file mandelbrotwidget.h.

Referenced by MandelbrotWidget(), paintEvent(), resizeEvent(), scroll(), and zoom().


The documentation for this class was generated from the following files:
Generated on Thu Mar 15 15:11:10 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1