canvas.h #pragma once #include <QColor> #include <QImage> #include <QWidget> #include <QPainter> #include <QPaintEvent> #include <QMouseEvent> #include <QRubberBand> // terület kiválasztáshoz struct RajzParameterek int penwidth = 1; Qt::PenStyle penstyle = Qt::SolidLine; Qt::PenCapStyle pencap = Qt::FlatCap; Qt::PenJoinStyle penjoin = Qt::MiterJoin; Qt::BrushStyle brushstyle = Qt::SolidPattern; QColor pencolor = qrgb(0, 0, 0), brushcolor = qrgb(255, 266, 255); ; class Canvas : public QWidget Q_OBJECT bool _modified = false; // ki kell rajzolni? bool _drawing = false; // szabadkézi rajzolás közben vagyunk? bool _freehand = false; // nem QPoint _lastpoint; // ebben a pontban volt az utolsó rajzolásnál az egérmutató QImage _canvas; RajzParameterek _param; // ide rajzolunk public: Canvas(QWidget *parent = 0); virtual ~Canvas() ; void SetParameters(RajzParameterek ¶m) _param = param; // Bármilyen képre jó, ha ez a _canvas, akkor a szülő méretére kell állítani! // Csak nagyobb newsize esetén változtatja meg a méretet void Resize(QImage *image, QSize newsize); void StartFreeHandDrawing() _freehand = true; void StopFreeHandDrawing() _freehand = false; // double buffer // lekérdezés bool IsModified() const return _modified; bool IsDrawing() const return _drawing; const QPoint &LastPos() const return _lastpoint; QColor GetPixel(const QPoint &pt) const return _canvas.pixel(pt); QColor PenColor() const return _param.pencolor; int PenWidth() const return _param.penwidth; Qt::PenStyle PenStyle() const return _param.penstyle;
Qt::PenCapStyle PenCapStyle() const return _param.pencap; Qt::PenJoinStyle PenJoinStyle()const return _param.penjoin; Qt::BrushStyle BrushStyle() const return _param.brushstyle; // Beállítás void SetPenWidth(int width) _param.penwidth = width; void SetPenColor(QColor color) _param.pencolor = color; void SetPenStyle (Qt::PenStyle &v) _param.penstyle= v; void SetPenCapStyle(Qt::PenCapStyle &v) _param.pencap= v; void SetPenJoinStyle(Qt::PenJoinStyle &v) _param.penjoin= v; void SetBrushStyle(Qt::BrushStyle &v) _param.brushstyle= v; // rajzolás void SetPixel(const QPoint &pt, QColor color); // egy pont kirajzolása void MoveTo(int x, int y) _lastpoint = QPoint(x, y); void DrawLine(const QPoint start, const QPoint end); void LineTo(const QPoint &endpoint); void DrawEllipse(const QRect &rect, bool fill = false); void DrawRect(const QRect & rect, bool fill = false); void DrawPolygon(const QVector<QPointF> points, bool fill = false); void DrawPolygon(const QPoint & pt, double sidelength, int sidecount, bool fill = false); void DrawTriangle(const QPoint & pt, double side, bool fill = false); // void DrawArc(double start, double end); void Clear(); protected: // esemányek. Q_DECL_OVERRIDE == C++ override identifier () // elhagyható lenne, de jó ha van (ellenőrzi, hogy valóban virtuális fv-t írtunk felül) #if QT_VERSION < 0x050000 // akkor nincs Q_DECL_OVERRIDE definiálva #define Q_DECL_OVERRIDE #endif void resizeevent(qresizeevent *event) Q_DECL_OVERRIDE; void mousepressevent(qmouseevent *event) Q_DECL_OVERRIDE; void mousemoveevent(qmouseevent *event) Q_DECL_OVERRIDE; void mousereleaseevent(qmouseevent *event) Q_DECL_OVERRIDE; void paintevent(qpaintevent *event) Q_DECL_OVERRIDE; ;
canvas.cpp #include "canvas.h" #include <cmath> Canvas::Canvas(QWidget *parent) : QWidget(parent) void Canvas::Resize(QImage *image, QSize newsize) if (newsize.width() < image->width()) newsize.setwidth(image->width()); if (newsize.height() < image->height()) newsize.setheight(image->height()); if (newsize.width() == image->width() && newsize.height() == image->height()) return; QImage newimage(newsize, QImage::Format_RGB32); newimage.fill(qrgb(255, 255, 255)); QPainter painter(&newimage); painter.drawimage(qpoint(0, 0), *image); *image = newimage; void Canvas::resizeEvent(QResizeEvent *event) int newwidth = qmax(width() + 128, _canvas.width()); int newheight = qmax(height() + 128, _canvas.height()); Resize(&_canvas, QSize(newWidth, newheight)); QWidget::resizeEvent(event); // a kirajzolás itt történik: _canvas-t rajzoljuk ki a képernyőre void Canvas::paintEvent(QPaintEvent *event) QPainter painter(this); QRect dirtyrect = event->rect(); painter.drawimage(dirtyrect, _canvas, dirtyrect); void Canvas::Clear() _canvas.fill(qrgb(255, 255, 255)); _lastpoint = QPoint(0, 0); update(); void Canvas::SetPixel(const QPoint &pt, QColor color) _canvas.setpixel(pt, color.rgb()); _lastpoint = pt; update(); // single point void Canvas::DrawLine(const QPoint start, const QPoint end)
_lastpoint = start; LineTo(end); void Canvas::LineTo(const QPoint &endpoint) painter.drawline(_lastpoint, endpoint); update(qrect(_lastpoint, endpoint).normalized().adjusted(-rad, -rad, +rad, +rad)); _lastpoint = endpoint; void Canvas::DrawEllipse(const QRect &rect, bool fill) if (fill) painter.setbrush(qbrush(_param.brushcolor, _param.brushstyle)); painter.drawellipse(rect); update(rect.normalized().adjusted(-rad, -rad, +rad, +rad)); void Canvas::DrawRect(const QRect & rect, bool fill) if (fill) painter.fillrect(rect, QBrush(_param.brushColor, _param.brushstyle)); else painter.drawrect(rect); update(rect.normalized().adjusted(-rad, -rad, +rad, +rad)); void Canvas::DrawPolygon(const QVector<QPointF> points, bool fill) if (points.size() < 3 points.size() > 100) // értelmes korlát a lehetséges pontokra
return; if (fill) painter.setbrush(qbrush(_param.brushcolor, _param.brushstyle)); painter.drawpolygon( points.data(), points.size() ); double minx = 10000, maxx = -10000, miny = 10000, maxy = -10000; for (int i = 0; i < points.size(); ++i) if (minx > points[i].x()) minx = points[i].x(); if (maxx < points[i].x()) maxx = points[i].x(); if (miny > points[i].y()) miny = points[i].y(); if (maxy < points[i].y()) maxy = points[i].y(); QRect rect = QRect(minx, miny, maxx, maxy); update(rect.normalized().adjusted(-rad, -rad, +rad, +rad)); void Canvas::DrawPolygon(const QPoint & pt, double sidelength, int sidecount, bool fill) if (sidecount < 3 sidecount > 100) // értelmes korlát a lehetséges oldalszámra return; szög QVector<QPointF> points(sidecount); double angle = 2 * 3.1415926535897931159979634685442 / sidecount, // középponti r = sidelength / sin(angle/2) / 2; // beírható kör sugara _lastpoint = pt; const_cast<qpoint&>(pt) += QPoint(0, r); // középpont double x, y; for (int i = 0; i < sidecount; ++i) x = pt.x() - r * sin(i*angle); y = pt.y() - r * cos(i*angle); points[i] = QPointF(x, y); DrawPolygon(points, fill); void Canvas::DrawTriangle(const QPoint & pt, double side, bool fill) QVector<QPointF> points; points.push_back(pt); double d = side * 1.7320508075688771931766041234368 / 2.0; QPoint qp; qp.setx(pt.x() + side / 2.0); qp.sety(pt.y() + d); points.push_back(qp); qp.setx(pt.x() - side / 2.0); points.push_back(qp);
DrawPolygon(points, fill); void Canvas::mousePressEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) _lastpoint = event->pos(); if(_freehand) _drawing = true; void Canvas::mouseMoveEvent(QMouseEvent *event) if (_drawing) LineTo(event->pos()); void Canvas::mouseReleaseEvent(QMouseEvent *event) if (_drawing & event->button() == Qt::LeftButton) LineTo(event->pos()); _lastpoint = event->pos(); _drawing = false;