dieterkrv
Гость
|
|
« Ответ #6 : Январь 11, 2007, 16:38 » |
|
Для Qt3 - берется книга - "Qt3: программирование GUI на С++". Глава 5 - раздел "Двойная буферизация". А вот и код:
///////////////////////////////////////////////////////////////// plotter.h //////////////////////////////////////////////////////////////// #ifndef PLOTTER_H #define PLOTTER_H
#include <qpixmap.h> #include <qwidget.h>
#include <map> #include <vector>
class QToolButton; class PlotSettings;
typedef std::vector<double> CurveData;
class Plotter : public QWidget { Q_OBJECT public: Plotter(QWidget *parent = 0, const char *name = 0, WFlags flags = 0);
void setPlotSettings(const PlotSettings &settings); void setCurveData(int id, const CurveData &data); void clearCurve(int id); QSize minimumSizeHint() const; QSize sizeHint() const;
public slots: void zoomIn(); void zoomOut();
protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *event); void wheelEvent(QWheelEvent *event);
private: void updateRubberBandRegion(); void refreshPixmap(); void drawGrid(QPainter *painter); void drawCurves(QPainter *painter);
enum { Margin = 40 };
QToolButton *zoomInButton; QToolButton *zoomOutButton; std::map<int, CurveData> curveMap; std::vector<PlotSettings> zoomStack; int curZoom; bool rubberBandIsShown; QRect rubberBandRect; QPixmap pixmap; };
class PlotSettings { public: PlotSettings();
void scroll(int dx, int dy); void adjust(); double spanX() const { return maxX - minX; } double spanY() const { return maxY - minY; }
double minX; double maxX; int numXTicks; double minY; double maxY; int numYTicks;
private: void adjustAxis(double &min, double &max, int &numTicks); };
#endif
///////////////////////////////////////////////////////////////// plotter.cpp //////////////////////////////////////////////////////////////// #include <qpainter.h> #include <qstyle.h> #include <qtoolbutton.h>
#include <cmath> using namespace std;
#include "plotter.h"
Plotter::Plotter(QWidget *parent, const char *name, WFlags flags) : QWidget(parent, name, flags | WNoAutoErase) { setBackgroundMode(PaletteDark); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setFocusPolicy(StrongFocus); rubberBandIsShown = false;
zoomInButton = new QToolButton(this); zoomInButton->setIconSet(QPixmap::fromMimeSource("zoomin.png")); zoomInButton->adjustSize(); connect(zoomInButton, SIGNAL(clicked()), this, SLOT(zoomIn()));
zoomOutButton = new QToolButton(this); zoomOutButton->setIconSet( QPixmap::fromMimeSource("zoomout.png")); zoomOutButton->adjustSize(); connect(zoomOutButton, SIGNAL(clicked()), this, SLOT(zoomOut()));
setPlotSettings(PlotSettings()); }
void Plotter::setPlotSettings(const PlotSettings &settings) { zoomStack.resize(1); zoomStack[0] = settings; curZoom = 0; zoomInButton->hide(); zoomOutButton->hide(); refreshPixmap(); }
void Plotter::zoomOut() { if (curZoom > 0) { --curZoom; zoomOutButton->setEnabled(curZoom > 0); zoomInButton->setEnabled(true); zoomInButton->show(); refreshPixmap(); } }
void Plotter::zoomIn() { if (curZoom < (int)zoomStack.size() - 1) { ++curZoom; zoomInButton->setEnabled( curZoom < (int)zoomStack.size() - 1); zoomOutButton->setEnabled(true); zoomOutButton->show(); refreshPixmap(); } }
void Plotter::setCurveData(int id, const CurveData &data) { curveMap[id] = data; refreshPixmap(); }
void Plotter::clearCurve(int id) { curveMap.erase(id); refreshPixmap(); }
QSize Plotter::minimumSizeHint() const { return QSize(4 * Margin, 4 * Margin); }
QSize Plotter::sizeHint() const { return QSize(8 * Margin, 6 * Margin); }
void Plotter::paintEvent(QPaintEvent *event) { QMemArray<QRect> rects = event->region().rects(); for (int i = 0; i < (int)rects.size(); ++i) bitBlt(this, rects.topLeft(), &pixmap, rects);
QPainter painter(this);
if (rubberBandIsShown) { painter.setPen(colorGroup().light()); painter.drawRect(rubberBandRect.normalize()); } if (hasFocus()) { style().drawPrimitive(QStyle::PE_FocusRect, &painter, rect(), colorGroup(), QStyle::Style_FocusAtBorder, colorGroup().dark()); } }
void Plotter::resizeEvent(QResizeEvent *) { int x = width() - (zoomInButton->width() + zoomOutButton->width() + 10); zoomInButton->move(x, 5); zoomOutButton->move(x + zoomInButton->width() + 5, 5); refreshPixmap(); }
void Plotter::mousePressEvent(QMouseEvent *event) { if (event->button() == LeftButton) { rubberBandIsShown = true; rubberBandRect.setTopLeft(event->pos()); rubberBandRect.setBottomRight(event->pos()); updateRubberBandRegion(); setCursor(crossCursor); } }
void Plotter::mouseMoveEvent(QMouseEvent *event) { if (event->state() & LeftButton) { updateRubberBandRegion(); rubberBandRect.setBottomRight(event->pos()); updateRubberBandRegion(); } }
void Plotter::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == LeftButton) { rubberBandIsShown = false; updateRubberBandRegion(); unsetCursor();
QRect rect = rubberBandRect.normalize(); if (rect.width() < 4 || rect.height() < 4) return; rect.moveBy(-Margin, -Margin);
PlotSettings prevSettings = zoomStack[curZoom]; PlotSettings settings; double dx = prevSettings.spanX() / (width() - 2 * Margin); double dy = prevSettings.spanY() / (height() - 2 * Margin); settings.minX = prevSettings.minX + dx * rect.left(); settings.maxX = prevSettings.minX + dx * rect.right(); settings.minY = prevSettings.maxY - dy * rect.bottom(); settings.maxY = prevSettings.maxY - dy * rect.top(); settings.adjust();
zoomStack.resize(curZoom + 1); zoomStack.push_back(settings); zoomIn(); } }
void Plotter::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Key_Plus: zoomIn(); break; case Key_Minus: zoomOut(); break; case Key_Left: zoomStack[curZoom].scroll(-1, 0); refreshPixmap(); break; case Key_Right: zoomStack[curZoom].scroll(+1, 0); refreshPixmap(); break; case Key_Down: zoomStack[curZoom].scroll(0, -1); refreshPixmap(); break; case Key_Up: zoomStack[curZoom].scroll(0, +1); refreshPixmap(); break; default: QWidget::keyPressEvent(event); } }
void Plotter::wheelEvent(QWheelEvent *event) { int numDegrees = event->delta() / 8; int numTicks = numDegrees / 15;
if (event->orientation() == Horizontal) zoomStack[curZoom].scroll(numTicks, 0); else zoomStack[curZoom].scroll(0, numTicks); refreshPixmap(); }
void Plotter::updateRubberBandRegion() { QRect rect = rubberBandRect.normalize(); update(rect.left(), rect.top(), rect.width(), 1); update(rect.left(), rect.top(), 1, rect.height()); update(rect.left(), rect.bottom(), rect.width(), 1); update(rect.right(), rect.top(), 1, rect.height()); }
void Plotter::refreshPixmap() { pixmap.resize(size()); pixmap.fill(this, 0, 0); QPainter painter(&pixmap, this); drawGrid(&painter); drawCurves(&painter); update(); }
void Plotter::drawGrid(QPainter *painter) { QRect rect(Margin, Margin, width() - 2 * Margin, height() - 2 * Margin); PlotSettings settings = zoomStack[curZoom]; QPen quiteDark = colorGroup().dark().light(); QPen light = colorGroup().light();
for (int i = 0; i <= settings.numXTicks; ++i) { int x = rect.left() + (i * (rect.width() - 1) / settings.numXTicks); double label = settings.minX + (i * settings.spanX() / settings.numXTicks); painter->setPen(quiteDark); painter->drawLine(x, rect.top(), x, rect.bottom()); painter->setPen(light); painter->drawLine(x, rect.bottom(), x, rect.bottom() + 5); painter->drawText(x - 50, rect.bottom() + 5, 100, 15, AlignHCenter | AlignTop, QString::number(label)); } for (int j = 0; j <= settings.numYTicks; ++j) { int y = rect.bottom() - (j * (rect.height() - 1) / settings.numYTicks); double label = settings.minY + (j * settings.spanY() / settings.numYTicks); painter->setPen(quiteDark); painter->drawLine(rect.left(), y, rect.right(), y); painter->setPen(light); painter->drawLine(rect.left() - 5, y, rect.left(), y); painter->drawText(rect.left() - Margin, y - 10, Margin - 5, 20, AlignRight | AlignVCenter, QString::number(label)); } painter->drawRect(rect); }
void Plotter::drawCurves(QPainter *painter) { static const QColor colorForIds[6] = { red, green, blue, cyan, magenta, yellow }; PlotSettings settings = zoomStack[curZoom]; QRect rect(Margin, Margin, width() - 2 * Margin, height() - 2 * Margin);
painter->setClipRect(rect.x() + 1, rect.y() + 1, rect.width() - 2, rect.height() - 2);
map<int, CurveData>::const_iterator it = curveMap.begin(); while (it != curveMap.end()) { int id = (*it).first; const CurveData &data = (*it).second; int numPoints = 0; int maxPoints = data.size() / 2; QPointArray points(maxPoints);
for (int i = 0; i < maxPoints; ++i) { double dx = data[2 * i] - settings.minX; double dy = data[2 * i + 1] - settings.minY; double x = rect.left() + (dx * (rect.width() - 1) / settings.spanX()); double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY()); if (fabs(x) < 32768 && fabs(y) < 32768) { points[numPoints] = QPoint((int)x, (int)y); ++numPoints; } } points.truncate(numPoints); painter->setPen(colorForIds[(uint)id % 6]); painter->drawPolyline(points); ++it; } }
PlotSettings::PlotSettings() { minX = 0.0; maxX = 10.0; numXTicks = 5;
minY = 0.0; maxY = 10.0; numYTicks = 5; }
void PlotSettings::scroll(int dx, int dy) { double stepX = spanX() / numXTicks; minX += dx * stepX; maxX += dx * stepX;
double stepY = spanY() / numYTicks; minY += dy * stepY; maxY += dy * stepY; }
void PlotSettings::adjust() { adjustAxis(minX, maxX, numXTicks); adjustAxis(minY, maxY, numYTicks); }
void PlotSettings::adjustAxis(double &min, double &max, int &numTicks) { const int MinTicks = 4; double grossStep = (max - min) / MinTicks; double step = pow(10, floor(log10(grossStep)));
if (5 * step < grossStep) step *= 5; else if (2 * step < grossStep) step *= 2;
numTicks = (int)(ceil(max / step) - floor(min / step)); min = floor(min / step) * step; max = ceil(max / step) * step; }
///////////////////////////////////////////////////////////////// main.cpp //////////////////////////////////////////////////////////////// #include <qapplication.h> #include <qfile.h>
#include "plotter.h"
void readFlightCurves(Plotter *plotter, const QString &fileName) { CurveData data[6]; double factX = 0.0013; double factY[6] = { 0.0008, 0.1, 0.2, 0.2, 0.1, 0.8 }; double offsetY[6] = { +500, -55, +309, +308, 0, 0 }; int pos[6] = { 3, 6, 7, 8, 9, 10 }; QFile file(fileName); double offsetX = 0.0;
if (file.open(IO_ReadOnly)) { QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); QStringList coords = QStringList::split(" ", line); if (coords.size() >= 6) { double x = factX * coords[0].toDouble(); if (data[0].size() == 0) offsetX = x; for (int i = 0; i < 6; ++i) { double y = coords[pos].toDouble(); data.push_back(x - offsetX); data.push_back(factY * (y - offsetY)); } } } } plotter->setCurveData(0, data[0]); plotter->setCurveData(1, data[1]); plotter->setCurveData(2, data[2]); plotter->setCurveData(3, data[3]); plotter->setCurveData(4, data[4]); plotter->setCurveData(5, data[5]); }
int main(int argc, char *argv[]) { QApplication app(argc, argv); Plotter plotter; plotter.setCaption(QObject::tr("Plotter")); readFlightCurves(&plotter, "in1.txt"); app.setMainWidget(&plotter); plotter.show(); return app.exec(); }
Проект, думаю, соберете.
|