#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QColorDialog> #include <QInputDialog> #include <QActionGroup> #include <QFileDialog> #include <QMainWindow> #include <QKeyEvent> #include <QToolBar> #include <QMenuBar> #include <QSlider> #include <QAction> #include <QColor> #include <QMenu> #include <QDial> #include <QLabel> #include "paint.h" #include "type.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); signals: void select_shape(type); void color_change(QColor); void brush_change(QColor); void width_change(int); void alpha_change(int); void openFile_SIGNAL(QString); void saveFile_SIGNAL(QString); void change_straight(bool); private slots: void color_SLOT(); void brush_SLOT(); void width_SLOT(); void draw_rect(); void draw_line(); void draw_pen(); void draw_polygon(); void draw_ellipse(); void change_widthLabel(int); void change_alphaLabel(int); void reset_dial(); private: QLabel *widthLabel; QDial *widthDial; QLabel *alphaLabel; QDial *alphaDial; virtual QSize sizeHint() const override; }; #endif // MAINWINDOW_H
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { ///////形状选择框架/////// QToolBar *shapeBar = this->addToolBar("Shape"); QActionGroup *shapeGroup = new QActionGroup(shapeBar); QAction *act_rect = new QAction(QIcon(":res/Rect.ico"),"Draw a Rect", shapeBar); act_rect->setCheckable(true); act_rect->setChecked(true); shapeGroup->addAction(act_rect); shapeBar->addAction(act_rect); QAction *act_line = new QAction(QIcon(":res/Line.ico"),"Draw A Line", shapeBar); act_line->setCheckable(true); shapeGroup->addAction(act_line); shapeBar->addAction(act_line); QAction *act_pen = new QAction(QIcon(":res/pen.ico"), "Draw With Pen", shapeBar); act_pen->setCheckable(true); shapeGroup->addAction(act_pen); shapeBar->addAction(act_pen); QAction *act_ellipse = new QAction(QIcon(":res/Ellipse.ico"), "Draw A Ellipse", shapeBar); act_ellipse->setCheckable(true); shapeGroup->addAction(act_ellipse); shapeBar->addAction(act_ellipse); QAction *act_polygon = new QAction(QIcon(":res/Polygon.ico"), "Draw A Polygon", shapeBar); act_polygon->setCheckable(true); shapeGroup->addAction(act_polygon); shapeBar->addAction(act_polygon); ////////操作选择框架///////////// QToolBar *operatorBar = this->addToolBar("Operator"); QActionGroup *operatorGroup = new QActionGroup(operatorBar); QAction *Undo = new QAction(QIcon(":/res/Undo.ico"), "Undo", operatorBar); Undo->setShortcut(tr("Ctrl+Z")); operatorGroup->addAction(Undo); operatorBar->addAction(Undo); QAction *Redo = new QAction(QIcon(":/res/Redo.ico"), "Redo", operatorBar); Redo->setShortcut(tr("Ctrl+Y")); operatorGroup->addAction(Redo); operatorBar->addAction(Redo); QAction *Reset = new QAction(QIcon(":/res/Reset.ico"), "Reset", operatorBar); Reset->setShortcut(tr("Ctrl+N")); operatorGroup->addAction(Reset); operatorBar->addAction(Reset); widthDial = new QDial(operatorBar); widthDial->setRange(1, 20); operatorBar->addWidget(widthDial); widthLabel = new QLabel("Size: 1", operatorBar); operatorBar->addWidget(widthLabel); alphaDial = new QDial(operatorBar); alphaDial->setRange(0, 100); alphaDial->setValue(100); operatorBar->addWidget(alphaDial); alphaLabel = new QLabel("Alpha: 100%", operatorBar); operatorBar->addWidget(alphaLabel); ////////////菜单区域//////////////// QMenu *file = menuBar()->addMenu(tr("&File")); QAction *newFile = new QAction(QIcon(":/res/New.ico"),tr("New"), file); newFile->setShortcut(tr("Ctrl+N")); file->addAction(newFile); QAction *openFile = new QAction(QIcon(":/res/open.ico"),tr("Open"), file); openFile->setShortcut(tr("Ctrl+O")); file->addAction(openFile); QAction *saveFile = new QAction(QIcon(":/res/Save.ico"),tr("Save"), file); saveFile->setShortcut(tr("Ctrl+S")); file->addAction(saveFile); QAction *quit = new QAction(QIcon(":/res/Quit.ico"),tr("Quit"), file); quit->setShortcut(tr("Ctrl+Q")); file->addAction(quit); QMenu *change = menuBar()->addMenu(tr("&Change")); QAction *changeColor = new QAction(QIcon(":/res/Color.ico"),tr("Color"), change); changeColor->setShortcut(tr("Ctrl+C")); change->addAction(changeColor); QAction *changeBrush = new QAction(QIcon(":/res/Brush.ico"),tr("Brush"), change); changeBrush->setShortcut(tr("Ctrl+B")); change->addAction(changeBrush); QAction *changeWidth = new QAction(QIcon(":/res/Width.ico"),tr("Width"), change); changeWidth->setShortcut(tr("Ctrl+W")); change->addAction(changeWidth); ////////////paint定义//////////// Paint *paint = new Paint(this); setCentralWidget(paint); ////////工具栏信号槽////////////////// QObject::connect(act_rect, SIGNAL(triggered()), this, SLOT(draw_rect())); QObject::connect(act_line, SIGNAL(triggered()), this, SLOT(draw_line())); QObject::connect(act_pen, SIGNAL(triggered()), this, SLOT(draw_pen())); QObject::connect(act_polygon, SIGNAL(triggered()), this, SLOT(draw_polygon())); QObject::connect(act_ellipse, SIGNAL(triggered()), this, SLOT(draw_ellipse())); QObject::connect(Undo, SIGNAL(triggered()), paint, SLOT(Undo())); QObject::connect(Redo, SIGNAL(triggered()), paint, SLOT(Redo())); QObject::connect(Reset, SIGNAL(triggered()), paint, SLOT(Reset())); QObject::connect(Reset, SIGNAL(triggered()), this, SLOT(reset_dial())); QObject::connect(widthDial, SIGNAL(valueChanged(int)), paint, SLOT(set_width(int))); QObject::connect(widthDial, SIGNAL(valueChanged(int)), this, SLOT(change_widthLabel(int))); QObject::connect(alphaDial, SIGNAL(valueChanged(int)), paint, SLOT(set_alpha(int))); QObject::connect(alphaDial, SIGNAL(valueChanged(int)), this, SLOT(change_alphaLabel(int))); ////////菜单栏信号槽////////////////// QObject::connect(newFile, SIGNAL(triggered()), paint, SLOT(Reset())); QObject::connect(openFile, SIGNAL(triggered()), paint, SLOT(open_file())); QObject::connect(saveFile, SIGNAL(triggered()), paint, SLOT(save_file())); QObject::connect(quit, SIGNAL(triggered()),this, SLOT(close())); QObject::connect(changeColor, SIGNAL(triggered()), this, SLOT(color_SLOT())); QObject::connect(changeBrush, SIGNAL(triggered()), this, SLOT(brush_SLOT())); QObject::connect(changeWidth, SIGNAL(triggered()), this, SLOT(width_SLOT())); /////////Paint交互信号槽/////////////////// QObject::connect(this, SIGNAL(select_shape(type)), paint, SLOT(set_shape(type))); QObject::connect(this, SIGNAL(color_change(QColor)), paint, SLOT(set_color(QColor))); QObject::connect(this, SIGNAL(brush_change(QColor)), paint, SLOT(set_brush(QColor))); QObject::connect(this, SIGNAL(width_change(int)), paint, SLOT(set_width(int))); QObject::connect(this, SIGNAL(change_straight(bool)), paint, SLOT(set_straight(bool))); } ///////信息发射/////////////// void MainWindow::keyPressEvent(QKeyEvent *k) { if (k->modifiers() == Qt::ShiftModifier) { emit change_straight(true); } } void MainWindow::keyReleaseEvent(QKeyEvent *k) { if (k->modifiers() == Qt::ShiftModifier) { emit change_straight(false); } } void MainWindow::color_SLOT() { QColor c = QColorDialog::getColor(Qt::black); emit color_change(c); } void MainWindow::brush_SLOT() { QColor c = QColorDialog::getColor(Qt::transparent); emit brush_change(c); } void MainWindow::width_SLOT() { int c = QInputDialog::getInt(this, tr("Width Set"), tr("Enter the Width"), true, 1, 20, 1); emit width_change(c); } void MainWindow::draw_rect() { emit select_shape(type_Rect); } void MainWindow::draw_line() { emit select_shape(type_Line); } void MainWindow::draw_pen() { emit select_shape(type_Pen); } void MainWindow::draw_polygon() { emit select_shape(type_Polygon); } void MainWindow::draw_ellipse() { emit select_shape(type_Ellipse); } ///////////////////槽函数//////////////// void MainWindow::change_widthLabel(int w) { widthLabel->setText("Size: " + QString::number(w)); } void MainWindow::change_alphaLabel(int w) { alphaLabel->setText("Alpha: " + QString::number(w) + "%"); } void MainWindow::reset_dial() { widthDial->setValue(1); alphaDial->setValue(100); widthLabel->setText("Size: 1"); alphaLabel->setText("Alpha: 100%"); } //////////其他////////// MainWindow::~MainWindow() { } QSize MainWindow::sizeHint() const { return QSize(1024, 768); }
#ifndef PAINT_H #define PAINT_H #include <QTextStream> #include <QFileDialog> #include <QMessageBox> #include <QMouseEvent> #include <QKeyEvent> #include <QWidget> #include <QBrush> #include <QStack> #include <QFile> #include <QPen> #include "ellipse.h" #include "polygon.h" #include "shape.h" #include "type.h" #include "line.h" #include "rect.h" #include "pen.h" class Paint : public QWidget { Q_OBJECT public: explicit Paint(QWidget *parent = 0); protected: void paintEvent(QPaintEvent *); void mouseMoveEvent(QMouseEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); public slots: void set_shape(type); void set_color(QColor); void set_brush(QColor); void set_width(int); void set_alpha(int); void set_straight(bool); void open_file(); void save_file(); void Undo(); void Redo(); void Reset(); private: type shapeType; QStack<Shape *>stack; QStack<Shape *>redoStack; //撤销恢复用 Shape *shape; QColor currentColor; QColor currentBrush; QString currentPath; int currentWidth; bool stop_polygon; bool is_straight; }; #endif // PAINT_H
#include "paint.h" Paint::Paint(QWidget *parent) :QWidget(parent), shape(nullptr), shapeType(type_Rect) { currentBrush = Qt::transparent; currentColor = Qt::black; currentWidth = 1; stop_polygon = true; is_straight = false; setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } void Paint::paintEvent(QPaintEvent *) { QPainter paint(this); paint.setBrush(Qt::white); paint.setPen(Qt::white); paint.drawRect(0, 0, size().width(), size().height()); foreach(Shape *shape, stack) { shape->paint(paint); } } void Paint::mousePressEvent(QMouseEvent *e) { ////////////Polygon特殊处理///////////////// while(!redoStack.empty()) { Shape *tmp = redoStack.top(); redoStack.pop(); delete tmp; } if(e->button() == Qt::RightButton) { stop_polygon = true; return; } if (shapeType == type_Polygon) { if(stop_polygon == true || stack.isEmpty()) { shape = new Polygon; Polygon *tmp = dynamic_cast<Polygon *>(shape); QPoint *p = new QPoint(e->pos()); tmp->push(p); QPoint *p2 = new QPoint(e->pos() + QPoint(0, 1)); tmp->push(p2); stack.push(shape); shape->set(currentColor, currentBrush, currentWidth); stop_polygon = false; } else { if (typeid(*stack.top()) != typeid(Polygon)) { stop_polygon = true; return; } Polygon *tmp = dynamic_cast<Polygon *>(shape); QPoint *p = new QPoint(e->pos()); tmp->push(p); } update(); return; } stop_polygon = true; switch(shapeType) { case type_Line: shape = new Line; break; case type_Rect: shape = new Rect; break; case type_Pen: shape = new Pen; break; case type_Ellipse: shape = new Ellipse; break; } if(shape != NULL) { if (shapeType == type_Pen) { Shape *zero = new Pen; zero->set_start(QPoint(0, 0)); zero->set_end(QPoint(0, 0)); stack.push(zero); }//制造间隔点 shape->set(currentColor, currentBrush, currentWidth); stack.push(shape); //shape->set_start(e->pos()); //shape->set_end(e->pos() + QPoint(0, 1)); //避免出现同一起点终点 shape->set_pos(e->pos(), e->pos() + QPoint(0, 1), is_straight); } update(); } void Paint::mouseMoveEvent(QMouseEvent *e) { if (shapeType == type_Polygon) { Polygon *tmp = dynamic_cast<Polygon *>(stack.top()); QPoint *p = tmp->top(); p->setX(e->x()); p->setY(e->y()); update(); return; } shape->set_pos(shape->get_start(), e->pos(), is_straight); if (shapeType == type_Pen) { shape = new Line; shape->set(currentColor, currentBrush, currentWidth); stack.push(shape); shape->set_start(e->pos()); shape->set_end(e->pos()); } update(); } void Paint::mouseReleaseEvent(QMouseEvent *) { if (shapeType== type_Pen) { Shape *zero = new Pen; zero->set_start(QPoint(0, 0)); zero->set_end(QPoint(0, 0)); stack.push(zero); }//制造间隔点 } void Paint::set_straight(bool c) { qDebug("%d", c); is_straight = c; } ///////////////////SLOT///////////// void Paint::set_color(QColor c) { currentColor = c; } void Paint::set_brush(QColor c) { currentBrush = c; } void Paint::set_shape(type new_shape) { shapeType = new_shape; } void Paint::set_width(int w) { currentWidth = w; } void Paint::set_alpha(int a) { currentBrush.setAlpha((100 - a) * 255 / 100); } void Paint::Undo() { if (!stack.empty()) { if(typeid(*stack.top()) == typeid(Pen))//运行期类型识别 { redoStack.push(stack.top()); stack.pop(); while(1) //寻找临界点 { if (stack.top()->get_start() == QPoint(0, 0) && stack.top()->get_end() == QPoint(0, 0)) break; redoStack.push(stack.top()); stack.pop(); } redoStack.push(stack.top()); //加入临界点 stack.pop(); } else { Shape *tmp = stack.top(); stack.pop(); redoStack.push(tmp); } } update(); } void Paint::Redo() { if (!redoStack.empty()) { if(typeid(*redoStack.top()) == typeid(Pen))//运行期类型识别 { stack.push(redoStack.top()); redoStack.pop(); while(1) //寻找临界点 { if (redoStack.top()->get_start() == QPoint(0, 0) && redoStack.top()->get_end() == QPoint(0, 0)) break; stack.push(redoStack.top()); redoStack.pop(); } stack.push(redoStack.top()); //加入临界点 redoStack.pop(); } else { Shape *tmp = redoStack.top(); redoStack.pop(); stack.push(tmp); } } update(); } void Paint::Reset() { currentBrush = Qt::transparent; currentColor = Qt::black; currentWidth = 1; stack.clear(); redoStack.clear(); stop_polygon = true; update(); } void Paint::open_file() { QString s = QFileDialog::getOpenFileName(this, "Select A File", "/", "Paint File(*.paint)"); if (s.isEmpty()) { QMessageBox::information(this, tr("INformation"), tr("Open failed!")); return; } int st = 0; int x1, y1, x2, y2; int r1, r2, g1, g2, b1, b2, a1, a2; int width; Reset(); currentPath = s; QFile file(currentPath); if (file.open(QFile::ReadOnly)) { QTextStream cin(&file); while(!cin.atEnd()) { st = 0; cin >>st; Shape *tmp; if (st == 0) break; //每次都会莫名其妙多读一行,,What A Fhuack if (st == 5) { tmp = new Polygon; int size; cin >> size; for(int i = 0; i < size; ++i) { cin >> x1 >> y1; QPoint *p = new QPoint(x1, y1); dynamic_cast<Polygon*>(tmp)->push(p); } cin >> r1>>g1>>b1>>a1>>r2>>g2>>b2>>a2>>width; tmp->set(QColor(r1, g1, b1, a1), QColor(r2, g2, b2, a2), width); stack.push(tmp); continue; } else cin >>x1>>y1>>x2>>y2>>r1>>g1>>b1>>a1>>r2>>g2>>b2>>a2>>width; switch(st) { case 1: tmp = new Rect; break; case 2: tmp = new Line; break; case 3: tmp = new Pen; break; case 4: tmp = new Ellipse; } tmp->set_start(QPoint(x1, y1)); tmp->set_end(QPoint(x2, y2)); tmp->set(QColor(r1, g1, b1, a1), QColor(r2, g2, b2, a2), width); stack.push(tmp); } } file.close(); update(); Polygon *p = dynamic_cast<Polygon*>(stack.top()); for(int i = 0; i < p->get_size(); ++i) qDebug("%d %d", p->index(i)->rx(), p->index(i)->ry()); } void Paint::save_file() { if (stack.empty()) { QMessageBox::information(this, tr("Information"), tr("Nothing To Be Save!")); return; } if (currentPath.isEmpty()) { QString s = QFileDialog::getSaveFileName(this, "Select A File", "/", "Paint File(*.paint)"); currentPath = s; } else { QMessageBox::information(this, tr("Information"), tr("Save Successful!")); } int r1, r2, g1, g2, b1, b2, a1, a2; QFile file(currentPath); if (file.open(QFile::WriteOnly)) { QTextStream cout(&file); foreach(Shape *shape, stack) { if (shape->get_typeid() == 5) { cout << "5 "; Polygon *p = dynamic_cast<Polygon*>(shape); cout << p->get_size() << " "; for(int i = 0; i < p->get_size(); ++i) cout << p->index(i)->rx() << " " << p->index(i)->ry() << " "; } else { cout << shape->get_typeid() << " " << shape->get_start().rx() << " " << shape->get_start().ry() << " " << shape->get_end().rx() << " " << shape->get_end().ry() << " "; } shape->get_color().getRgb(&r1, &g1, &b1, &a1); shape->get_brush().getRgb(&r2, &g2, &b2, &a2); cout <<r1<<" "<<g1<<" "<<b1<<" "<<a1<<" " <<r2<<" "<<g2<<" "<<b2<<" "<<a2<<" " << shape->get_width() << endl; } } file.close(); }
#ifndef SHAPE_H #define SHAPE_H #include <QPoint> #include <QPainter> #include <QColor> class Shape { public: Shape(); void set_start(QPoint p); void set_end(QPoint p); void set_pos(QPoint, QPoint, bool); void set(QColor, QColor, int); QPoint get_start(); QPoint get_end(); QColor get_color(); QColor get_brush(); int get_width(); virtual void paint(QPainter& painter) = 0; virtual int get_typeid() = 0; protected: QPoint start; QPoint end; QColor color; QColor brush; int width; }; #endif // SHAPE_H
#include "shape.h" Shape::Shape() :start(QPoint(0, 0)), end(QPoint(0, 0)) { ; } void Shape::set_end(QPoint p) { end = p; } void Shape::set_start(QPoint p) { start = p; } void Shape::set_pos(QPoint p1, QPoint p2, bool is_straight) { start = p1; if (is_straight) { if (abs(p1.rx() - p2.rx()) <= abs(p1.ry() - p2.ry())) { p2.setX(p1.rx() - p1.rx() + p2.rx()); p2.setY(p1.ry() - p1.rx() + p2.rx()); } else { p2.setX(p1.rx() - p1.ry() + p2.ry()); p2.setY(p1.ry() - p1.ry() + p2.ry()); } } end = p2; } QPoint Shape::get_end() { return end; } QPoint Shape::get_start() { return start; } QColor Shape::get_color() { return color; } QColor Shape::get_brush() { return brush; } int Shape::get_width() { return width; } void Shape::set(QColor c1, QColor c2, int w) { color = c1; brush = c2; width = w; }
#ifndef RECT_H #define RECT_H #include "shape.h" #include <QPainter> class Rect : public Shape { public: Rect(); private: virtual void paint(QPainter& paint) override; virtual int get_typeid() override; }; #endif // RECT_H
#include "rect.h" Rect::Rect() { } void Rect::paint(QPainter &paint) { paint.setPen(QPen(color, width)); paint.setBrush(brush); paint.drawRect(start.x(), start.y(),end.x() - start.x(), end.y() - start.y()); } int Rect::get_typeid() { return 1; }
#ifndef LINE_H #define LINE_H #include <QPainter> #include "shape.h" class Line : public Shape { public: Line(); private: virtual void paint(QPainter& paint) override; virtual int get_typeid() override; }; #endif // LINE_H
#include "line.h" Line::Line() { } void Line::paint(QPainter &paint) { paint.setPen(QPen(color, width)); paint.setBrush(brush); paint.drawLine(start, end); } int Line::get_typeid() { return 2; }
#ifndef PEN_H #define PEN_H #include "shape.h" #include <QPainter> class Pen : public Shape { public: Pen(); virtual void paint(QPainter& paint) override; virtual int get_typeid() override; }; #endif // PEN_H
#include "pen.h" Pen::Pen() { ; } void Pen::paint(QPainter &paint) { paint.setPen(QPen(color, width)); paint.setBrush(brush); paint.drawLine(start, end); } int Pen::get_typeid() { return 3; }
#ifndef CIRCLE_H #define CIRCLE_H #include "shape.h" class Ellipse : public Shape { public: Ellipse(); private: virtual void paint(QPainter& paint) override; virtual int get_typeid() override;};#endif // CIRCLE_H
#include "ellipse.h" Ellipse::Ellipse() { } void Ellipse::paint(QPainter &paint) { paint.setPen(QPen(color, width)); paint.setBrush(brush); paint.drawEllipse(start, end.rx() - start.rx(), end.ry() - start.ry()); } int Ellipse::get_typeid() { return 4; }
#ifndef POLYGON_H #define POLYGON_H #include "shape.h" #include <QPolygon> #include <QPoint> #include <QVector> class Polygon : public Shape { public: Polygon(); ~Polygon(); virtual void paint(QPainter&); virtual int get_typeid(); void push(QPoint *); QPoint *top(); int get_size(); QPoint *index(int pos); private: QVector<QPoint *>polygonStack; }; #endif // POLYGON_H
#include "polygon.h" Polygon::Polygon() { } void Polygon::paint(QPainter &paint) { paint.setPen(QPen(color, width)); paint.setBrush(brush); QPolygon polygon(polygonStack.size()); for(int i = 0; i < polygonStack.size(); ++i) { polygon.setPoint(i, *polygonStack[i]); } paint.drawPolygon(polygon); } int Polygon::get_typeid() { return 5; } void Polygon::push(QPoint *p) { polygonStack.push_back(p); } QPoint *Polygon::top() { return polygonStack[polygonStack.size() - 1]; } Polygon::~Polygon() { foreach(QPoint *p, polygonStack) { delete p; } } int Polygon::get_size() { return polygonStack.size(); } QPoint* Polygon::index(int pos) { return polygonStack[pos]; }
#ifndef TYPE_H #define TYPE_H enum type{type_Rect, type_Line, type_Pen, type_Ellipse, type_Polygon}; #endif // TYPE_H
程序截图: