source: trunk/examples/threads/mandelbrot/mandelbrotwidget.cpp@ 983

Last change on this file since 983 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 6.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:BSD$
10** You may use this file under the terms of the BSD license as follows:
11**
12** "Redistribution and use in source and binary forms, with or without
13** modification, are permitted provided that the following conditions are
14** met:
15** * Redistributions of source code must retain the above copyright
16** notice, this list of conditions and the following disclaimer.
17** * Redistributions in binary form must reproduce the above copyright
18** notice, this list of conditions and the following disclaimer in
19** the documentation and/or other materials provided with the
20** distribution.
21** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22** the names of its contributors may be used to endorse or promote
23** products derived from this software without specific prior written
24** permission.
25**
26** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include <QtGui>
42
43#include <math.h>
44
45#include "mandelbrotwidget.h"
46
47//! [0]
48const double DefaultCenterX = -0.637011f;
49const double DefaultCenterY = -0.0395159f;
50const double DefaultScale = 0.00403897f;
51
52const double ZoomInFactor = 0.8f;
53const double ZoomOutFactor = 1 / ZoomInFactor;
54const int ScrollStep = 20;
55//! [0]
56
57//! [1]
58MandelbrotWidget::MandelbrotWidget(QWidget *parent)
59 : QWidget(parent)
60{
61 centerX = DefaultCenterX;
62 centerY = DefaultCenterY;
63 pixmapScale = DefaultScale;
64 curScale = DefaultScale;
65
66 qRegisterMetaType<QImage>("QImage");
67 connect(&thread, SIGNAL(renderedImage(QImage,double)),
68 this, SLOT(updatePixmap(QImage,double)));
69
70 setWindowTitle(tr("Mandelbrot"));
71#ifndef QT_NO_CURSOR
72 setCursor(Qt::CrossCursor);
73#endif
74 resize(550, 400);
75}
76//! [1]
77
78//! [2]
79void MandelbrotWidget::paintEvent(QPaintEvent * /* event */)
80{
81 QPainter painter(this);
82 painter.fillRect(rect(), Qt::black);
83
84 if (pixmap.isNull()) {
85 painter.setPen(Qt::white);
86 painter.drawText(rect(), Qt::AlignCenter,
87 tr("Rendering initial image, please wait..."));
88//! [2] //! [3]
89 return;
90//! [3] //! [4]
91 }
92//! [4]
93
94//! [5]
95 if (curScale == pixmapScale) {
96//! [5] //! [6]
97 painter.drawPixmap(pixmapOffset, pixmap);
98//! [6] //! [7]
99 } else {
100//! [7] //! [8]
101 double scaleFactor = pixmapScale / curScale;
102 int newWidth = int(pixmap.width() * scaleFactor);
103 int newHeight = int(pixmap.height() * scaleFactor);
104 int newX = pixmapOffset.x() + (pixmap.width() - newWidth) / 2;
105 int newY = pixmapOffset.y() + (pixmap.height() - newHeight) / 2;
106
107 painter.save();
108 painter.translate(newX, newY);
109 painter.scale(scaleFactor, scaleFactor);
110 QRectF exposed = painter.matrix().inverted().mapRect(rect()).adjusted(-1, -1, 1, 1);
111 painter.drawPixmap(exposed, pixmap, exposed);
112 painter.restore();
113 }
114//! [8] //! [9]
115
116 QString text = tr("Use mouse wheel or the '+' and '-' keys to zoom. "
117 "Press and hold left mouse button to scroll.");
118 QFontMetrics metrics = painter.fontMetrics();
119 int textWidth = metrics.width(text);
120
121 painter.setPen(Qt::NoPen);
122 painter.setBrush(QColor(0, 0, 0, 127));
123 painter.drawRect((width() - textWidth) / 2 - 5, 0, textWidth + 10,
124 metrics.lineSpacing() + 5);
125 painter.setPen(Qt::white);
126 painter.drawText((width() - textWidth) / 2,
127 metrics.leading() + metrics.ascent(), text);
128}
129//! [9]
130
131//! [10]
132void MandelbrotWidget::resizeEvent(QResizeEvent * /* event */)
133{
134 thread.render(centerX, centerY, curScale, size());
135}
136//! [10]
137
138//! [11]
139void MandelbrotWidget::keyPressEvent(QKeyEvent *event)
140{
141 switch (event->key()) {
142 case Qt::Key_Plus:
143 zoom(ZoomInFactor);
144 break;
145 case Qt::Key_Minus:
146 zoom(ZoomOutFactor);
147 break;
148 case Qt::Key_Left:
149 scroll(-ScrollStep, 0);
150 break;
151 case Qt::Key_Right:
152 scroll(+ScrollStep, 0);
153 break;
154 case Qt::Key_Down:
155 scroll(0, -ScrollStep);
156 break;
157 case Qt::Key_Up:
158 scroll(0, +ScrollStep);
159 break;
160 default:
161 QWidget::keyPressEvent(event);
162 }
163}
164//! [11]
165
166//! [12]
167void MandelbrotWidget::wheelEvent(QWheelEvent *event)
168{
169 int numDegrees = event->delta() / 8;
170 double numSteps = numDegrees / 15.0f;
171 zoom(pow(ZoomInFactor, numSteps));
172}
173//! [12]
174
175//! [13]
176void MandelbrotWidget::mousePressEvent(QMouseEvent *event)
177{
178 if (event->button() == Qt::LeftButton)
179 lastDragPos = event->pos();
180}
181//! [13]
182
183//! [14]
184void MandelbrotWidget::mouseMoveEvent(QMouseEvent *event)
185{
186 if (event->buttons() & Qt::LeftButton) {
187 pixmapOffset += event->pos() - lastDragPos;
188 lastDragPos = event->pos();
189 update();
190 }
191}
192//! [14]
193
194//! [15]
195void MandelbrotWidget::mouseReleaseEvent(QMouseEvent *event)
196{
197 if (event->button() == Qt::LeftButton) {
198 pixmapOffset += event->pos() - lastDragPos;
199 lastDragPos = QPoint();
200
201 int deltaX = (width() - pixmap.width()) / 2 - pixmapOffset.x();
202 int deltaY = (height() - pixmap.height()) / 2 - pixmapOffset.y();
203 scroll(deltaX, deltaY);
204 }
205}
206//! [15]
207
208//! [16]
209void MandelbrotWidget::updatePixmap(const QImage &image, double scaleFactor)
210{
211 if (!lastDragPos.isNull())
212 return;
213
214 pixmap = QPixmap::fromImage(image);
215 pixmapOffset = QPoint();
216 lastDragPos = QPoint();
217 pixmapScale = scaleFactor;
218 update();
219}
220//! [16]
221
222//! [17]
223void MandelbrotWidget::zoom(double zoomFactor)
224{
225 curScale *= zoomFactor;
226 update();
227 thread.render(centerX, centerY, curScale, size());
228}
229//! [17]
230
231//! [18]
232void MandelbrotWidget::scroll(int deltaX, int deltaY)
233{
234 centerX += deltaX * curScale;
235 centerY += deltaY * curScale;
236 update();
237 thread.render(centerX, centerY, curScale, size());
238}
239//! [18]
Note: See TracBrowser for help on using the repository browser.