Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

235 }

Функция drawGrid чертит сетку под кривыми и осями. Область для вычерчивания сетки задается прямоугольником rect. Если размеры виджета недостаточны для размещения графика, мы сразу возвращаем управление.

Первый цикл for проводит вертикальные линии сетки и отметки по оси x. Второй цикл for выводит горизонтальные линии и отметки по оси y. В конце мы рисуем прямоугольники по окаймляющей кромке. Функция drawText применяется для

вывода числовых значений для отметок обеиз осей.

Вызовы функции drawText имеют следующий формат:

painter.drawText(x, у, ширина, высота, смещение, текст);

где (x, у, ширина, высота) определяют прямоугольник, смещение задает позицию текста в этом прямоугольнике и текст представляет собой выводимый текст.

236 void Plotter::drawCurves(QPainter *painter)

237 {

238 static const QColor colorForIds[6] = {

239 Qt::red, Qt::green, Qt::blue, Qt::cyan, Qt::magenta, Qt::yellow };

240 PlotSettings settings = zoomStack[curZoom];

241 QRect rect(Margin, Margin,

242 width - 2 * Margin, height - 2 * Margin);

243 if (!rect.isValid)

244 return;

245 painter->setClipRect(rect.adjusted(+1, +1, -1, -1));

246 QMapIterator<int, QVector<QPointF> > i(curveMap);

247 while (i.hasNext) {

248 i.next;

249 int id = i.key;

250 const QVector<QPointF> &data = i.value;

251 QPolygonF polyline(data.count);

252 for (int j = 0; j < data.count; ++j) {

253 double dx = data[j].x - settings.minX;

254 double dy = data[j].y - settings.minY;

255 double x = rect.left + (dx * (rect.width - 1)

256 / settings.spanX);

257 double у = rect.bottom - (dy * (rect.height - 1)

258 / settings.spanY);

259 polyline[j] = QPointF(x, у);

260 }

261 painter->setPen(colorForIds[uint(id) % 6]);

262 painter->drawPolyline(polyline);

263 }

264 }

Функция drawCurves рисует кривые поверх сетки. Мы начинаем с вызова функции setClipRect для ограничения области отображения QPainter прямоугольником, содержащим кривые (без окаймляющей кромки и рамки вокруг графика). После этого QPainter будет игнорировать вывод пикселей вне этой области.

Затем мы выполняем цикл по всем кривым, используя итератор в стиле Java, и для каждой кривой мы выполняем цикл по ее точкам QPointF. Функция key позволяет получить идентификатор кривой, а функция value — данные соответствующей

кривой в виде вектора QVector<QPointF>. Внутри цикла for производятся преобразование всех точек QPointF из системы координат построителя графика в систему координат виджета и сохранение их в переменной polyline.

После преобразования всех точек кривой в систему координат виджета мы устанавливаем цвет пера для кривой (используя один из наборов заранее определенных цветов) и вызываем drawPolyline для вычерчивания линии, которая проходит по всем точкам кривой.

Этим мы завершаем построение класса Plotter. Остается только рассмотреть несколько функций настроек графика PlotSettings.

265 PlotSettings::PlotSettings

266 {

267 minX = 0.0;

268 maxX = 10.0;

269 numXTicks = 5;

270 minY = 0.0;

271 maxY = 10.0;

272 numYTicks = 5;

273 }

Конструктор PlotSettings инициализирует обе оси координат диапазоном от 0 до 10 с пятью отметками.

274 void PlotSettings::scroll(int dx, int dy)

275 {

276 double stepX = spanX / numXTicks;

277 minX += dx * stepX;

278 maxX += dx * stepX;

279 double stepY = spanY / numYTicks;

280 minY += dy * stepY;

281 maxY += dy *stepY;

282 }

Функция scroll увеличивает (или уменьшает) minX, maxX, minY и maxY на интервал между двух отметок, помноженный на заданное число. Данная функция применяется для реализации скроллинга в функции Plotter::keyPressEvent.

283 void PlotSettings::adjust

284 {

285 adjustAxis(minX, maxX, numXTicks);

286 adjustAxis(minY, maxY, numYTicks);

287 }

Функция adjust вызывается из mouseReleaseEvent для округления значений minX, maxX, minY и maxY, чтобы получить «удобные» значения, и определения количества меток на каждой оси. Закрытая фyнкция adjustAxis выполняет эти действия отдельно для каждой оси.

288 void PlotSettings::adjustAxis(double &min, double &max, int &numTiсks)

289 {

290 const int MinTicks = 4;

291 double grossStep = (max - min) / MinTicks;

292 double step = pow(10.0, floor(log10(grossStep)));

293 if (5 * step < grossStep) {

294 step *= 5;

295 } else if (2* step < grossStep) {

296 step *= 2;

Поделиться с друзьями: