[Qt C++] 开发一个像素画工具

代码:http://download.csdn.net/detail/zju_fish1996/9608840

        像素画,是以像素为基本单位进行绘制的画。同时,它也是一种设计风格,常用于图标(ICon)设计、logo设计、表情设计以及经典像素风游戏设计。像素画的绘制上手比较容易,对创作者最基本的要求是对色彩的把握,如明度对比、纯度对比。因为在像素画中,具体的线条概念可以是不明确的,而更多是由色彩来表达形体的。

        开发这款工具的初衷,就是为了方便以后的设计。当然市面上也有类似的产品了,但是很多都不是免费的(当然本来也没有多少设计软件是免费的),我感觉它本身的实现并不难,所以就花了一点时间来自己动手写它。

        现在的功能还不那么完善,但是最基本的功能已经实现了,包括这款工具的所有图标都是用它自身绘制出来的。




代码框架

        

        button.h :  

            继承自QToolButton, 在其基础上添加了一些函数。主要用于改变按钮样式。

        colorbar.h:  

             实现渐变的颜色条,继承自QWidget, 颜色改变后,可向画板、颜色面板发出信号通知它们修改颜色。

        colorwindow.h:
            实现颜色选择面板,继承自QWidget, 除了给定颜色,还可以在颜色对话框中选择新颜色。
         newdialog.h:
            实现新建文件时的对话框,继承自QWidget。
         paint.h:
            实现画板,完成所有绘制,继承自QWidget。
         savedialog.h:
           实现保存文件时的对话框,继承自QWidget。
         pixel.h:
            主界面,继承自QObject。包含了工具栏、菜单栏、图像栏的设计,以及所有控件的布局,以及它们之间的通信。

功能介绍


        新建文件时,可以自定义窗口大小,考虑到性能问题,暂时只支持150X150以下的图像。

        


        同样,可以加载一般的图片,但是大小也限制在150X150以下。

        保存文件时,可以保存为原始大小,也提供了放大为原来的4倍,9倍的选项,放大图像采用了简单的重复进行上采样。
        在这里确实可以设计更多的选项,包括利用插值的上采样,以及更多的放大倍数,在这里由于时间关系没有进一步扩展,但是图像还可以在设计软件如ps中进行进一步加工。
        

        绘制方面,提供了单个像素点、矩形、圆形的绘制,另外,还提供了取色器、橡皮擦、油漆桶。
        一开始的时候,只打算提供单一像素的绘制,但是后来考虑了一下,又加上了矩形和圆形,更多的体素暂时没有完成。
        橡皮擦目前只支持擦除一个像素点,为了方便自己的使用,后续的维护过程中应该会陆续加上更多的功能。
        此外,可以撤销,也可以重做(最多支持30步),可以选择显示网格与否。

        
       
        颜色板中,除了自己摆的几个颜色外,还使用了qt内置的颜色对话框,可以选择丰富的颜色。
        此外,我没有找到qt中提供的渐变颜色选择器,然后就自己实现了一个。

        

        第一个是HSL空间中的明度变化图,第二个是透明度变化图。直接用鼠标点击就可以选择颜色。
        有了这两个工具后,设计时选择合适的颜色就变得容易了很多。

详细设计


(一)画板


          事件的重写

         主要的方法是重写了paintEvent(绘制事件), mouseMoveEvent(鼠标移动事件), mousePressEvent(鼠标点击事件), mouseReleaseEvent(鼠标抬起事件)。
         利用状态量来标识当前的绘制状态(如:绘制像素点,绘制空心圆,绘制实心圆……),然后在各种事件中根据当前状态,利用switch case来采取对应的操作,由于工具栏与画板在不同的cpp中,每次改变工具,主窗体都需要发射一个信号通知画板改变状态量,每次修改图像后,都要调用update()来刷新当前画面。

         为了实时显示鼠标移动过程中的绘制状态,需要在一开始启动鼠标轨迹追踪(setMouseTracing(true))。


         缓存


         在屏幕上显示的网格大小并不是真实的像素大小,而是要大一些。我们用map数组来存储每个网格的颜色信息,每次读取的时候遍历这个数组,把里面存储的颜色一个个显示到屏幕上。每次更新图像时,都要更新map数组。

         此外,因为鼠标移动时也会实时绘制,所以我们另外使用一个集合容器(currentPoint)来维护这些点,每次使用后就及时清空。

         除了当前画板的显示,我们在右侧还提供了实际图像的显示,这个图像由QImage暂存,因为QImage提供了像素点的底层操作。我们显示的时候,是将map数组的所有像素颜色直接调用setPixelColor复制过去的。又因为图像的显示是由主窗口控制的,所以我们提供了一个函数来返回包含这个QImage的QLabel的指针。由于新建的时候这个QImage将不再指向原来的内容,我们会发射一个信号通知主窗口更新图像指针。


        撤回与重做


         我们提供了撤回和重做的操作,在这里使用了最简单的方法来实现这一过程。在这里,我们支持30次回退,也就是说我们设计了30个map数组,每个map数组存储着某一时间状态下的完整图像,我们把所有图像当做一个队列来维护,所以我们事实上是通过front(队头), rear(队尾),layer(当前层)的修改来完成一系列操作的。这也就意味着,如果用户使用撤销后又继续绘制,新的绘制会覆盖用户原本可以重做的内容。这是因为我们保证了整个撤销重做是线性的,如果我们希望重做的内容不被覆盖,形成的将会是一个复杂的树形分支结构。

        绘制

       点和矩形的绘制就是普通的绘制,在这里,直线和圆的绘制都使用了Bresenham算法,它们具体是什么原理,可以参考 这里
       当然,这个算法虽然很经典,但是效果其实并不那么好,因为它最终形成的线是锯齿形的,而不是圆滑的。这并不是说这个算法是不正确的,这是用单一颜色绘制直线(圆)的最好效果了,但是为了达成圆滑的效果,我们往往采用灰度(明度)变化来表现线条的柔和,因为我不知道这个需要用什么算法,所以就没有进一步修改。

        混色
 
       由于这里使用了透明度来绘制,就会出现不同透明度颜色混合的现象,所以就要考虑混色,关于混色,可以参考 这里
  
        填色

       颜色填充使用的算法是种子填充法,也就是不断地向四周递归搜索,如果颜色相同的话。我们知道点的邻域有四邻域和八邻域,计算机图形学相关的书籍指出:在填充算法中,我们一般选择四邻域。八邻域往往会导致“过分”填充,而四邻域往往会导致填充“不足”,但是,相比之下,不足是可以弥补的,而过分填充却是难以弥补的,所以我们更倾向于四邻域填充算法。


(二)颜色条


        首先这里有两种颜色条,一个是明度颜色条,一个是渐变颜色条。渐变颜色条的实现很简单,就是不断地改变透明度(alpha通道)就可以了。
        关于明度变化,QColor中一般使用RGB来存储颜色信息的,一开始我以为要自己去写两种色彩空间(从RGB到HSL)的转换,后来发现qt本身提供了这种转换,所以就直接调用了QColor的这个方法,这样一来,明度变化也很简单的。
        至于这个渐变是怎样画出来的,实际上就是从0开始到255,不断变化明度(透明度),然后绘制一个个矩形。每个矩形的宽度就是width()/255,高度就是height()。在这里,我们的颜色与窗口坐标值是对应的,所以我们在点击这个颜色条的时候,也可以通过坐标值迅速的计算出选中的颜色。

图片资源(均有该像素画工具绘制)

                                                     

box.icon   choose.png circle.png  circle1.png  color.png   color1.png

                                                      

erase.png erase1.png fullcircle.png  fullcircle1.png  fullrect.png

                                                            

fullrect1.png  getcolor.png  getcolor1.png     grid.png     line.png    line1.png

                                                             

new.png       open.png       pixel.png      pixel1.png     rect.png      rect1.png

                 

redo.png     undo.png   save.png


代码


button.h
#ifndef BUTTON
#define BUTTON
#include<QToolButton>

class Button : public QToolButton
{
    Q_OBJECT
private:
    QIcon m_NormalIcon;
    QIcon m_FocusIcon;
    QIcon m_PressedIcon;
protected:
public:

    void setPressImg();
    void setReleaseImg();
    Button(QWidget *parent = 0);
    Button(QString &str1,QString &str2,QString &str3);
    virtual ~Button();
    void SetButtonIcons(const QIcon &normal,
        const QIcon &focus = QIcon(),
        const QIcon &pressed = QIcon() );
};

#endif // BUTTON

colorbar.h
#ifndef COLORBAR_H
#define COLORBAR_H
#include<QWidget>
class colorBarLight : public QWidget
{
    Q_OBJECT
public:
    static QColor color;
    colorBarLight(QWidget* parent = 0);
signals:
    void selectColor(QColor);
protected:
    void paintEvent(QPaintEvent *);
    void mousePressEvent(QMouseEvent *);
};

class colorBarAlpha : public QWidget
{
    Q_OBJECT
public:
    static QColor color;
    colorBarAlpha(QWidget* parent = 0);
signals:
    void selectColor(QColor);
protected:
    void paintEvent(QPaintEvent *);
    void mousePressEvent(QMouseEvent*);
};

#endif // COLORBAR_H

colorwindow.h
#ifndef COLORWINDOW_H
#define COLORWINDOW_H
#include<QWidget>
#include<QToolButton>
class QGroupBox;
class colorBarLight;
class colorBarAlpha;
class colorWindow:public QWidget
{
    Q_OBJECT
private:
    int chosenId;
    QToolButton* currentColorBtn;
    QString style[10];
    QToolButton* colorBtn[10];
    QGroupBox *btnGroup;
    QGroupBox *chosenColorGroup;
    colorBarLight* colorbar1;
    colorBarAlpha* colorbar2;
    QString getStyleSheet(const QColor& color);
    QString getStyleSheetAlpha(const QColor& color);
public:
    colorWindow(QWidget* parent = 0);
private slots:
    void changeColor(int);
    void changeColor(QColor);
    void changeColorLight(QColor);
    void changeColorAlpha(QColor);
    void colorDialog();

};


#endif // COLORWINDOW_H

newdialog.h
#ifndef NEWDIALOG_H
#define NEWDIALOG_H
#include<QWidget>
class QButtonGroup;
class QPushButton;
class QRadioButton;
class QLineEdit;
class QLabel;
class newDialog : public QWidget
{
    Q_OBJECT
private:
    QButtonGroup* radioGroup;
    QRadioButton* radio16;
    QRadioButton* radio32;
    QRadioButton* radio48;
    QRadioButton* radio64;
    QRadioButton* radioRandom;
    QPushButton* okBtn;
    QPushButton* cancelBtn;
    QLineEdit* startEdit;
    QLineEdit* finishEdit;
    QLabel* label1;
    QLabel* label2;
public:
    newDialog(QWidget* parent = 0);
private slots:
    void newFile();
    void radioChange();
signals:
    void sendIndex(int,int);
};

#endif // NEWDIALOG_H

paint.h
#ifndef PAINT_H
#define PAINT_H
#include<QWidget>
#include<QPaintEvent>
#include<QMouseEvent>
#include<QColor>
#include<set>
class QLabel;
class point{
public:
    int x;
    int y;
    QColor c;
    point();
    point(QColor color,int i = -1,int j = -1);
    friend bool operator <(const point& x,const point& y);
    friend bool operator ==(const point& x,const point& y);
};

class paintWindow:public QWidget
{
    Q_OBJECT
private:
    int XMAX;
    int YMAX;
    int size;

    enum{DRAWPIXEL,DRAWRECT,FILLCOLOR,DRAWFULLRECT,DRAWLINE,
        DRAWCIRCLE,DRAWFULLCIRCLE,ERASE,GETCOLOR};
    enum{TIMES=30};
    QImage *img;
    QLabel *picture;
    int state;
    QColor*** map;
    int layer;
    int front;
    int rear;
    int margin;
    std::set<point>currentPoint;

    bool isRelease;
    void updateMap();
    void bresenhamLine(int,int,int,int);
    void bresenhamLine(int,int,int,int,bool);
    void bresenhamCircle(int xc,int yc,int r);
    void bresenhamCircle(int xc,int yc,int x,int y);
    void bresenhamFullCircle(int xc,int yc,int r);
    void seedFilling(int i,int j);
    void updateImage();
    void drawTmpPixel();
    void drawOnScreenPixel();
    void setLayout(int,int);
    bool isShowGrid;
    inline int min(int x,int y){return x<y?x:y;}
    inline int max(int x,int y){return x>y?x:y;}
    QColor mixColor(const QColor& x,const QColor& y);

public:
    static QColor color;
    void saveImage(const QString &fileName,int s);
    void undo();
    void redo();
    void drawRect();
    void drawPixel();
    void fillColor();
    void drawFullRect();
    void drawLine();
    void drawCircle();
    void drawFullCircle();
    void erase();
    void showGrid();
    void getColor();
    QLabel* getImage();
    void newImage(QImage* image);
    paintWindow(QWidget *parent = 0);
    ~paintWindow();

protected:
    void paintEvent(QPaintEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void mousePressEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);

public slots:
    void changeSize(int,int);
signals:
    void changeColor(QColor);
    void changeImg();
};

#endif // PAINT_H

pixel.h
#ifndef PIXEL_H
#define PIXEL_H

#include <QObject>
#include "button.h"
#include "paint.h"
#include "colorwindow.h"
class Button;
class QWidget;
class QHBoxLayout;
class QVBoxLayout;
class QImage;
class QMenu;
class QMenuBar;
class QAction;
class QToolBar;
class QGroupBox;
class QPixmap;
class QPushButton;
class QPicture;
class QMainWindow;
class QDockWidget;
class pixel : public QObject
{
    Q_OBJECT

private:
    QString filename;

    //主窗口
    QMainWindow* mainWindow;
    QWidget* window;
    //菜单栏
    QMenu* fileMenu;
    QMenu* editMenu;
    QMenu* showMenu;
    QImage* img;
    QMenuBar* menuBar;
    QAction* actionNew;
    QAction* actionSave;
    QAction* actionOpen;
    QAction* actionUndo;
    QAction* actionRedo;
    QAction* actionShowGrid;

    //工具栏

    QToolBar* toolBar;
    QAction* newTool;
    QAction* saveTool;

    //左边的状态栏
    QWidget* leftWidget;
    Button*leftToolBar;
    Button* drawRectBtn;
    Button* drawPixelBtn;
    Button* colorBtn;
    Button* drawFullRectBtn;
    Button* drawLineBtn;
    Button* drawCircleBtn;
    Button* drawFullCircleBtn;
    Button* eraseBtn;
    Button* getColorBtn;
    void setLeftTool();

    //画板
    paintWindow* paint;
    //颜色
    colorWindow* color;

    //图像显示
    QDockWidget* dock1;

    void setLayout();
    void createMenu();
    void createTool();
    void createPixmap();
    void createColorGroup();
    void updateIcon(int);
    Button *pixel::createButton(QString &str1,QString &str2,QString &str3);
public:
    pixel(QObject *parent = 0);
    ~pixel();
public slots:
    bool save();
    void open();
    void undo();
    void redo();
    void drawRect();
    void fillColor();
    void drawPixel();
    void drawFullRect();
    void drawLine();
    void drawCircle();
    void drawFullCircle();
    void erase();
    void showGrid();
    void newFile();
    void updateImg();
    void getColor();
    void saveImg(int);
};

#endif // PIXEL_H

savedialog.h
#ifndef SAVEDIALOG_H
#define SAVEDIALOG_H
#include<QWidget>
class QButtonGroup;
class QPushButton;
class QRadioButton;
class QLineEdit;
class QLabel;
class saveDialog : public QWidget
{
    Q_OBJECT
private:
    QButtonGroup* radioGroup;
    QRadioButton* radio1;
    QRadioButton* radio2;
    QRadioButton* radio3;
    QPushButton* okBtn;
    QPushButton* cancelBtn;
public:
    saveDialog(QWidget* parent = 0);
private slots:
    void saveFile();
signals:
    void save(int);
};
#endif // SAVEDIALOG_H

button.cpp
#include"button.h"
#include<QPixmap>

Button::Button(QWidget *parent)
: QToolButton(parent)
{
    setDown(false);
    setFocusPolicy(Qt::NoFocus);
}

Button::Button(QString &str1,QString &str2,QString &str3)
{
    QPixmap img1,img2,img3;
    img1.load(str1);
    img2.load(str2);
    img3.load(str3);
    setFixedSize(img1.width()/4*3,img1.height()/4*3);
    SetButtonIcons(img1,img2,img3);
    setStyleSheet("border:0px 0px 0px 0px;");
    setIconSize(QSize(img1.width()/4*3,img1.height()/4*3));
}

Button::~Button()
{

}

void Button::setPressImg()
{
    setIcon(m_PressedIcon);
}

void Button::setReleaseImg()
{
    setIcon(m_NormalIcon);
}

void Button::SetButtonIcons(const QIcon &normal,
    const QIcon &focus, const QIcon &pressed)
{
    m_NormalIcon = normal;
    m_FocusIcon = focus;
    m_PressedIcon = pressed;
    setIcon(m_NormalIcon);
}

colorbar.cpp
 #include"colorbar.h"
#include<QPainter>
#include<QMouseEvent>
QColor colorBarLight::color(255,50,50,255);
QColor colorBarAlpha::color(255,50,50,255);
colorBarLight::colorBarLight(QWidget* parent)
    :QWidget(parent) {
    setFixedHeight(30);
}

void colorBarLight::paintEvent(QPaintEvent *)
{
    QPainter paint(this);
    int h,s,l;
    color.getHsl(&h,&s,&l);
    paint.setPen(Qt::NoPen);
    for(int i=0;i<width();i++){
        color.setHsl(h,s,(int)(1.0*i/width()*255));
        paint.setBrush(color);
        paint.drawRect(i,0,1,height());
   }

}

void colorBarLight::mousePressEvent(QMouseEvent *event)
{
    int x = event->pos().x();
    int h,s,l;
    color.getHsl(&h,&s,&l);
    QColor newColor;
    newColor.setHsl(h,s,(int)(1.0*x/width()*255));
    emit(selectColor(newColor));
}

colorBarAlpha::colorBarAlpha(QWidget* parent)
    :QWidget(parent) {
    setFixedHeight(30);
}

void colorBarAlpha::paintEvent(QPaintEvent *)
{
    QPainter paint(this);
    paint.setPen(Qt::NoPen);
    int size = 8;
    for(int i=0;i<=width()/size;i++){
        for(int j=0;j<=height()/size;j++){
            paint.setBrush(QColor(222,222,222));
            paint.drawRect(size*i, size*j, size/2, size/2);
            paint.drawRect(size*i + size/2, size*j+size/2, size/2, size/2);
            paint.setBrush(QColor(255,255,255));
            paint.drawRect(size*i+size/2, size*j, size/2, size/2);
            paint.drawRect(size*i, size*j+size/2, size/2, size/2);
        }
    }
    for(int i=0;i<width();i++){
        color.setAlpha((int)((1.0*i/width())*255));
        paint.setBrush(color);
        paint.drawRect(i,0,1,height());
   }
}

void colorBarAlpha::mousePressEvent(QMouseEvent *event)
{
    int x = event->pos().x();
    int alpha = (int)(1.0*x/width()*255);
    QColor newColor(color.red(),color.green(),color.blue(),alpha);
    emit(selectColor(newColor));
}

colorwindow.cpp
#include"colorwindow.h"
#include"paint.h"
#include"button.h"
#include"colorbar.h"
#include<QGridLayout>
#include<QVBoxLayout>
#include<QGroupBox>
#include<QSignalMapper>
#include<QColorDialog>

colorWindow::colorWindow(QWidget* parent)
    :QWidget(parent)
{
    colorbar1 = new colorBarLight;
    colorbar2 = new colorBarAlpha;
    QVBoxLayout* vlayout = new QVBoxLayout();
    QGridLayout* glayout = new QGridLayout();
    QGridLayout* glayout1 = new QGridLayout();
    QSignalMapper* signalMapper[10];
    QString str0 = "choose.png";
    Button* chooseNewColorBtn = new Button(str0,str0,str0);
    chooseNewColorBtn->setStyleSheet("border:1px solid #d1d1d1;");
    currentColorBtn = new QToolButton();
    btnGroup = new QGroupBox;
    chosenColorGroup = new QGroupBox;

    connect(chooseNewColorBtn,SIGNAL(clicked(bool)),this,SLOT(colorDialog()));
    QString str[] ={"border:1px solid #d1d1d1;background-color:rgb(255,50,50);",
                        "border:1px solid #d1d1d1;background-color:rgb(255,125,50);",
                        "border:1px solid #d1d1d1;background-color:rgb(255,50,255);",
                        "border:1px solid #d1d1d1;background-color:rgb(255,255,50);",
                        "border:1px solid #d1d1d1;background-color:rgb(50,255,50);",
                        "border:1px solid #d1d1d1;background-color:rgb(50,50,255);",
                        "border:1px solid #d1d1d1;background-color:rgb(50,255,255);",
                        "border:1px solid #d1d1d1;background-color:rgb(255,255,255);",
                        "border:1px solid #d1d1d1;background-color:rgb(50,50,50);",
                        "border:1px solid #d1d1d1;background-color:rgb(156,156,156);"};

    for(int i=0;i<10;i++){
        style[i] = str[i];

        signalMapper[i] = new QSignalMapper();

        colorBtn[i] = new QToolButton();
        colorBtn[i]->setStyleSheet(style[i]);
        connect(colorBtn[i],SIGNAL(clicked()),signalMapper[i],SLOT(map()));

        signalMapper[i]->setMapping(colorBtn[i],i);

        connect(signalMapper[i],SIGNAL(mapped(int)),this,SLOT(changeColor(int)));

        glayout->addWidget(colorBtn[i],i/2,i%2);
    }

    currentColorBtn->setStyleSheet(style[0]);
    glayout1->addWidget(currentColorBtn,0,0,1,1);
    glayout1->addWidget(chooseNewColorBtn,0,1,1,1);
    chosenColorGroup->setLayout(glayout1);

    btnGroup->setLayout(glayout);

    vlayout->addWidget(chosenColorGroup);
    vlayout->addWidget(btnGroup);
    vlayout->addWidget(colorbar1);
    vlayout->addWidget(colorbar2);
    vlayout->addStretch();

    setLayout(vlayout);
    setMaximumWidth(100);

    connect(colorbar1,SIGNAL(selectColor(QColor)),this,SLOT(changeColorLight(QColor)));
    connect(colorbar2,SIGNAL(selectColor(QColor)),this,SLOT(changeColorAlpha(QColor)));
}

void colorWindow::changeColor(int id)
{
    int num[10][3] = {
        255,50,50,255,125,50,255,50,255,255,255,50,50,255,50,50,50,255,50,255,255,
        255,255,255,50,50,50,156,156,156
    };
    currentColorBtn->setStyleSheet(style[id]);
    paintWindow::color = QColor(num[id][0],num[id][1],num[id][2]);
    colorBarLight::color = QColor(num[id][0],num[id][1],num[id][2]);
    colorBarAlpha::color = QColor(num[id][0],num[id][1],num[id][2]);
    colorbar1->update();
    colorbar2->update();
}

QString colorWindow::getStyleSheetAlpha(const QColor& color)
{
    QString str = "border:1px solid #d1d1d1;background-color:rgba(";

    str = str + QString::number(color.red()) + "," + QString::number(color.green()) + ","
            + QString::number(color.blue()) + "," + QString::number(1.0*color.alpha()/255*100) + "%);";
    return str;
}

QString colorWindow::getStyleSheet(const QColor& color)
{
    QString str = "border:1px solid #d1d1d1;background-color:rgb(";

    str = str + QString::number(color.red()) + "," + QString::number(color.green()) + ","
            + QString::number(color.blue()) + ");";
    return str;
}

void colorWindow::changeColorLight(QColor color)
{
    currentColorBtn->setStyleSheet(getStyleSheet(color));
    paintWindow::color = color;
    colorBarAlpha::color = color;
    colorbar2->update();
}

void colorWindow::changeColorAlpha(QColor color)
{
    currentColorBtn->setStyleSheet(getStyleSheetAlpha(color));
    paintWindow::color = color;
    colorBarAlpha::color = color;
    colorbar1->update();
}

void colorWindow::changeColor(QColor color)
{
    currentColorBtn->setStyleSheet(getStyleSheetAlpha(color));
    paintWindow::color = color;
    colorBarLight::color = color;
    colorBarAlpha::color = color;
    colorbar1->update();
    colorbar2->update();
}

void colorWindow::colorDialog()
{
    QColor color = QColorDialog::getColor(Qt::white, this);
    if(color==QColor::Invalid){
        color = paintWindow::color;
    }
    QString str = getStyleSheet(color);
    currentColorBtn->setStyleSheet(str);
    paintWindow::color = color;
    colorBarLight::color = color;
    colorBarAlpha::color = color;
    colorbar1->update();
    colorbar2->update();
}

newdialog.cpp
#include"newdialog.h"
#include<QRadioButton>
#include<QVBoxLayout>
#include<QHBoxLayout>
#include<QPushButton>
#include<QButtonGroup>
#include<QLineEdit>
#include<QLabel>
#include<QMessageBox>

newDialog::newDialog(QWidget* parent):QWidget(parent)
{
    QVBoxLayout* vlayout = new QVBoxLayout;
    QVBoxLayout* vlayout1 = new QVBoxLayout;
    QHBoxLayout* hlayout = new QHBoxLayout;
    QHBoxLayout* hlayout1 = new QHBoxLayout;
    startEdit = new QLineEdit();
    finishEdit = new QLineEdit();
    label1 = new QLabel(QStringLiteral("宽度:"));
    label2 = new QLabel(QStringLiteral("高度:"));


    startEdit->setEnabled(false);
    finishEdit->setEnabled(false);
    okBtn = new QPushButton(QStringLiteral("确定"));
    cancelBtn = new QPushButton(QStringLiteral("取消"));

    radioGroup = new QButtonGroup();
    radio16 = new QRadioButton("16x16",this);
    radio32 = new QRadioButton("32x32",this);
    radio48 = new QRadioButton("48x48",this);
    radio64 = new QRadioButton("64x64",this);
    radioRandom = new QRadioButton(QStringLiteral("自定义"),this);

    radio32->setChecked(true);
    radioGroup->addButton(radio16,1);
    radioGroup->addButton(radio32,2);
    radioGroup->addButton(radio48,3);
    radioGroup->addButton(radio64,4);
    radioGroup->addButton(radioRandom,5);

    vlayout1->addWidget(radio16);
    vlayout1->addWidget(radio32);
    vlayout1->addWidget(radio48);
    vlayout1->addWidget(radio64);
    vlayout1->addWidget(radioRandom);

    hlayout1->addLayout(vlayout1);
    hlayout1->addWidget(label1);
    hlayout1->addWidget(startEdit);
    hlayout1->addWidget(label2);
    hlayout1->addWidget(finishEdit);

    hlayout->addWidget(okBtn);
    hlayout->addWidget(cancelBtn);

    vlayout->addLayout(hlayout1);
    vlayout->addLayout(hlayout);

    connect(radio16, SIGNAL(clicked(bool)), this, SLOT(radioChange()));
    connect(radio32, SIGNAL(clicked(bool)), this, SLOT(radioChange()));
    connect(radio48, SIGNAL(clicked(bool)), this, SLOT(radioChange()));
    connect(radio64, SIGNAL(clicked(bool)), this, SLOT(radioChange()));
    connect(radioRandom, SIGNAL(clicked(bool)), this, SLOT(radioChange()));

    connect(okBtn,SIGNAL(clicked()),this,SLOT(newFile()));
    connect(cancelBtn,SIGNAL(clicked()),this,SLOT(close()));

    setLayout(vlayout);
    setWindowFlags(Qt::WindowStaysOnTopHint);
    setWindowModality(Qt::ApplicationModal);
    setWindowTitle(QStringLiteral("新建"));
}

void newDialog::radioChange()
{
    int id = radioGroup->checkedId();
    if(id==5){
        startEdit->setEnabled(true);
        finishEdit->setEnabled(true);
    }
    else{
        startEdit->setEnabled(false);
        finishEdit->setEnabled(false);
    }
}

void newDialog::newFile()
{
    int id = radioGroup->checkedId();
    if(id>=1&&id<=4){
        int num = id*16;
        emit(sendIndex(num,num));
    }
    else{
        int num1 = startEdit->text().toInt();
        int num2 = finishEdit->text().toInt();
        if(num1<150&&num2<150&&num1>0&&num2>0){
            emit(sendIndex(num1,num2));
        }
        else{
            QMessageBox msg(QMessageBox::Warning, "warning", QStringLiteral("指定大小超过限制/不符规范"),
                                 QMessageBox::Yes, NULL);
            msg.exec();
        }
    }
    close();
}

paint.cpp
#include"paint.h"
#include<QPainter>
#include<QApplication>
#include<QLabel>
QColor paintWindow::color(255,50,50,255);

point::point(QColor color,int i,int j):
    x(i),y(j) {
    c = color;
}

bool operator <(const point& a,const point& b)
{
    return a.x<b.x||(a.x==b.x&&a.y<b.y);
}

bool operator ==(const point& a,const point& b)
{
    return a.x==b.x&&a.y==b.y;
}

point::point(){ }

paintWindow::paintWindow(QWidget *parent):
    QWidget(parent)
{
    setLayout(32,32);
}

void paintWindow::setLayout(int x,int y)
{
    XMAX = x;
    YMAX = y;
    margin = 10;
    if(x<50&&y<50)size = 10;
    else if(x<100&&y<100)size =8;
    else if(y<150&&y<150)size = 6;
    map = new QColor**[XMAX];
    for(int i=0;i<XMAX;i++){
        map[i] = new QColor*[YMAX];
        for(int j=0;j<YMAX;j++){
            map[i][j] = new QColor[TIMES];
        }
    }
    for(int i=0;i<XMAX;i++){
        for(int j=0;j<YMAX;j++){
            map[i][j][0] = QColor(0,0,0,0);
        }
    }
    img = new QImage(XMAX,YMAX,QImage::Format_ARGB32);
    img->fill(QColor(0,0,0,0));
    picture = new QLabel;
    picture->setPixmap(QPixmap::fromImage(*img));
    layer = 0;
    front = rear = 0;
    state = DRAWPIXEL;
    isRelease = true;
    isShowGrid = false;
    setMouseTracking(true);
    setMinimumWidth(XMAX*size+2*margin);
    setMinimumHeight(YMAX*size+2*margin);
}

void paintWindow::changeSize(int x,int y)
{
    delete img;
    for(int i=0;i<XMAX;i++){
        for(int j=0;j<YMAX;j++){
            delete map[i][j];
        }
        delete map[i];
    }
    delete map;
    delete picture;
    setLayout(x,y);
    emit(changeImg());
}

void paintWindow::newImage(QImage* image)
{
    delete map;
    delete picture;
    setLayout(image->width(),image->height());
    for(int i=0;i<image->width();i++){
        for(int j=0;j<image->height();j++){
            map[i][j][0] = image->pixelColor(i,j);
        }
    }
    update();
}

paintWindow::~paintWindow()
{

}

void paintWindow::drawOnScreenPixel()
{
    QPainter paint(this);
    paint.setPen(Qt::NoPen);
    if(front!=rear){
        for(int i=0;i<XMAX;i++){
            for(int j=0;j<YMAX;j++){
                if(map[i][j][layer]!=QColor(0,0,0,0)
                        &¤tPoint.find(point(QColor(0,0,0,0),i,j))==currentPoint.end()){
                    paint.setBrush(map[i][j][layer]);
                    paint.drawRect(i*size+margin,j*size+margin,size,size);
                }
            }
        }
    }
}

void paintWindow::drawTmpPixel()
{
    QPainter paint(this);
    paint.setPen(Qt::NoPen);
    std::set<point>::iterator it;
    for(it=currentPoint.begin();it!=currentPoint.end();it++){
        if(it->x>=0&&it->y>=0
                &&it->x<XMAX&&it->y<YMAX) {
            QColor c;
            if(it->c.alpha()!=255&&map[it->x][it->y][layer]!=QColor(0,0,0,0)){
                c = mixColor(map[it->x][it->y][layer],it->c);
            }
            else c = it->c;
            paint.setBrush(c);
            paint.drawRect(it->x*size+margin,it->y*size+margin,size,size);
        }
    }
}

void paintWindow::paintEvent(QPaintEvent *)
{
    QPainter paint(this);
    for(int i=0;i<XMAX;i++){
        for(int j=0;j<YMAX;j++){          
            paint.setPen(Qt::NoPen);
            paint.setBrush(QColor(222,222,222));
            paint.drawRect(size*i+margin, size*j+margin, size/2, size/2);
            paint.drawRect(size*i + size/2+margin, size*j+size/2+margin, size/2, size/2);
            paint.setBrush(QColor(255,255,255));
            paint.drawRect(size*i+size/2+margin, size*j+margin, size/2, size/2);
            paint.drawRect(size*i+margin, size*j+size/2+margin, size/2, size/2);
            if(isShowGrid){
                paint.setPen(QColor(200,200,200));
                paint.setBrush(QColor(0,0,0,0));
                paint.drawRect(size*i+margin, size*j+margin, size, size);
            }
        }
    }
    if(state==ERASE){
        paint.setPen(Qt::NoPen);
        if(front!=rear){
            for(int i=0;i<XMAX;i++){
                for(int j=0;j<YMAX;j++){
                    if(map[i][j][layer]!=QColor(0,0,0,0)&&
                            currentPoint.find(point(QColor(0,0,0,0),i,j))==currentPoint.end()){
                        paint.setBrush(map[i][j][layer]);
                        paint.drawRect(i*size+margin,j*size+margin,size,size);
                    }
                }
            }
        }
        std::set<point>::iterator it;
        for(it=currentPoint.begin();it!=currentPoint.end();it++){
            if(it->x>=0&&it->y>=0
                    &&it->x<XMAX&&it->y<YMAX) {
                paint.setBrush(it->c);
                paint.drawRect(it->x*size+margin,it->y*size+margin,size,size);
            }
        }
    }
    else{
        drawOnScreenPixel();
        drawTmpPixel();
    }


}

void paintWindow::updateImage()
{
    for(int i=0;i<XMAX;i++){
        for(int j=0;j<YMAX;j++){
            img->setPixelColor(i,j,map[i][j][layer]);
        }
    }

    picture->setPixmap(QPixmap::fromImage(*img));
}

void paintWindow::mouseMoveEvent(QMouseEvent *event)
{
    int j = (event->pos().y()-margin)/size;
    int i = (event->pos().x()-margin)/size;
    static int x1, y1;
    static int x2, y2;
    currentPoint.clear();
    if(event->pos().y()-margin<0||event->pos().x()-margin<0){
        update();
        return;
    }
    switch(state){
    case DRAWRECT:
        if(event->buttons()&Qt::LeftButton){
            if(isRelease){
                isRelease = false;
                x1 = i;
                y1 = j;
            }
            x2 = i;
            y2 = j;
            int minX = min(x1,x2);
            int minY = min(y1,y2);
            int maxX = max(x1,x2);
            int maxY = max(y1,y2);
            for(int k=minX;k<=maxX;k++){
                currentPoint.insert(point(color,k,minY));
                currentPoint.insert(point(color,k,maxY));
            }
            for(int k=minY+1;k<=maxY-1;k++){
                currentPoint.insert(point(color,minX,k));
                currentPoint.insert(point(color,maxX,k));
            }
        }
        break;
    case DRAWPIXEL:
        currentPoint.insert(point(color,i,j));
        break;
    case DRAWFULLRECT:
        if(event->buttons()&Qt::LeftButton){
            if(isRelease){
                isRelease = false;
                x1 = i;
                y1 = j;
            }
            x2 = i;
            y2 = j;
            int minX = min(x1,x2);
            int minY = min(y1,y2);
            int maxX = max(x1,x2);
            int maxY = max(y1,y2);
            for(int k=minX;k<=maxX;k++){
                for(int t=minY;t<=maxY;t++){
                    currentPoint.insert(point(color,k,t));
                }
            }
        }
        break;
    case DRAWLINE:
        if(event->buttons()&Qt::LeftButton){
            if(isRelease){
                isRelease = false;
                x1 = i;
                y1 = j;
            }
            x2 = i;
            y2 = j;
            bresenhamLine(x1,y1,x2,y2);
        }
        break;
    case DRAWCIRCLE:
        if(event->buttons()&Qt::LeftButton){
            if(isRelease){
                isRelease = false;
                x1 = i;
                y1 = j;
            }
            x2 = i;
            y2 = j;
            bresenhamCircle(x1,y1,abs(x2-x1));
        }
        break;
    case DRAWFULLCIRCLE:
        if(event->buttons()&Qt::LeftButton){
            if(isRelease){
                isRelease = false;
                x1 = i;
                y1 = j;
            }
            x2 = i;
            y2 = j;
            bresenhamFullCircle(x1,y1,abs(x2-x1));
        }
        break;
    case ERASE:
        QColor tmp(0,0,0,0);
        currentPoint.insert(point(tmp,i,j));
        break;
    };
    update();
}

void paintWindow::mousePressEvent(QMouseEvent *event)
{
    static int count = 0;
    int j = (event->pos().y()-margin)/size;
    int i = (event->pos().x()-margin)/size;
    switch(state){
    case DRAWPIXEL:

        if(i>=0&&i<XMAX&&j>=0&&j<YMAX){
            updateMap();
            map[i][j][layer] = color;
            update();
        }
        break;
    case FILLCOLOR:
        if(i>=0&&i<XMAX&&j>=0&&j<YMAX){
            updateMap();
            seedFilling(i,j);
            update();
        }
        break;
    case GETCOLOR:
        if(i>=0&&i<XMAX&&j>=0&&j<YMAX){
            emit(changeColor(map[i][j][layer]));
        }
    }
}

void paintWindow::mouseReleaseEvent(QMouseEvent *event)
{
    isRelease = true;
    std::set<point>::iterator it;
    switch(state){
    case ERASE:
        updateMap();
        for(it=currentPoint.begin();it!=currentPoint.end();it++){
            if(it->x>=0&&it->y>=0
                    &&it->x<XMAX&&it->y<YMAX) {
                    map[it->x][it->y][layer] = it->c;
            }
        }
        currentPoint.clear();
        update();
        break;
    case DRAWRECT:
    case DRAWFULLRECT:
    case DRAWLINE:
    case DRAWCIRCLE:
    case DRAWFULLCIRCLE:
        updateMap();
        for(it=currentPoint.begin();it!=currentPoint.end();it++){
            if(it->x>=0&&it->y>=0
                    &&it->x<XMAX&&it->y<YMAX) {
                if(it->c.alpha()!=255&&map[it->x][it->y][layer]!=QColor(0,0,0,0)){
                    map[it->x][it->y][layer]
                            = mixColor(map[it->x][it->y][layer],it->c);
                }
                else map[it->x][it->y][layer] = it->c;
            }
        }
        currentPoint.clear();
        update();
        break;
    }
    updateImage();
}

QColor paintWindow::mixColor(const QColor& x,const QColor& y)
{
    float a1 = 1.0f*x.alpha()/255;
    float a2 = 1.0f*y.alpha()/255;
    int r,g,b,a;
    r = x.red()*a1*(1-a2)+y.red()*a2/(a1+a2-a1*a2);
    g = x.green()*a1*(1-a2)+y.green()*a2/(a1+a2-a1*a2);
    b = x.blue()*a1*(1-a2)+y.blue()*a2/(a1+a2-a1*a2);
    a = (1-(1-a1)*(1-a2))*255;
    return QColor(r,g,b,a);
}

void paintWindow::bresenhamLine(int x1,int y1,int x2,int y2)
{
    if(abs(x2-x1)<abs(y2-y1)){
        bresenhamLine(y1,x1,y2,x2,false);
    }
    else{
        bresenhamLine(x1,y1,x2,y2,true);
    }
}

void paintWindow::bresenhamLine(int x1,int y1,int x2,int y2,bool isDxBigger)
{
    int dx = abs(x2-x1);
    int dy = abs(y2-y1);
    int d = 2*dy - dx;
    for(int cx=x1,cy=y1;cx!=x2;cx+=(x2-x1>0?1:-1)){
        if(d<0){
            d += dy*2;
        }
        else{
            cy += (y2-y1)>0?1:-1;
            d += (dy - dx)*2;
        }
        if(isDxBigger)currentPoint.insert(point(color,cx,cy));
        else currentPoint.insert(point(color,cy,cx));
    }
    if(isDxBigger){
        currentPoint.insert(point(color,x1,y1));
        currentPoint.insert(point(color,x2,y2));
    }
    else{
        currentPoint.insert(point(color,y1,x1));
        currentPoint.insert(point(color,y2,x2));
    }
}

void paintWindow::bresenhamCircle(int xc,int yc,int r)
{
    int x = 0,y = r,p = 3 - 2*3;
    while(x<y){
        bresenhamCircle(xc,yc,x,y);
        if(p<0)p = p + 4*x + 6;
        else{
            p = p + 4*(x-y)+10;
            y--;
        }
        x++;
    }
    if(x==y){
        bresenhamCircle(xc,yc,x,y);
    }
}

void paintWindow::bresenhamFullCircle(int xc,int yc,int r)
{
    int x = 0,y = r,p = 3 - 2*3;
    while(x<y){
        for(int i=x;i<=y;i++){
            bresenhamCircle(xc,yc,x,i);
        }
        if(p<0)p = p + 4*x + 6;
        else{
            p = p + 4*(x-y)+10;
            y--;
        }
        x++;
    }
    if(x==y){
        bresenhamCircle(xc,yc,x,y);
    }
}


void paintWindow::bresenhamCircle(int xc,int yc,int x,int y)
{
    if(xc+x<XMAX&&yc+y<YMAX)currentPoint.insert(point(color,xc+x,yc+y));
    if(xc-x>=0&&yc+y<YMAX)currentPoint.insert(point(color,xc-x,yc+y));
    if(xc+x<XMAX&&yc-y>=0)currentPoint.insert(point(color,xc+x,yc-y));
    if(xc-x>=0&&yc-y>=0)currentPoint.insert(point(color,xc-x,yc-y));
    if(xc+y<XMAX&&yc+x<YMAX)currentPoint.insert(point(color,xc+y,yc+x));
    if(xc-y>=0&&yc+x<YMAX)currentPoint.insert(point(color,xc-y,yc+x));
    if(xc+y<XMAX&&yc-x>=0)currentPoint.insert(point(color,xc+y,yc-x));
    if(xc-y>=0&&yc-x>=0)currentPoint.insert(point(color,xc-y,yc-x));
}

void paintWindow::updateMap()
{
    for(int i=0;i<XMAX;i++){
        for(int j=0;j<YMAX;j++){
            map[i][j][(layer+1)%TIMES] = map[i][j][layer];
        }
    }
    layer = (layer+1)%TIMES;
    rear = layer;
    if(rear==front)front = (front+1)%TIMES;
}

void paintWindow::seedFilling(int i,int j)
{
    int dx[] = {0,1,0,-1};
    int dy[] = {1,0,-1,0};

    QColor originalColor = map[i][j][layer];
    if(color==originalColor)return;
    map[i][j][layer] = color;
    for(int k=0;k<4;k++){
        int x = i + dx[k];
        int y = j + dy[k];
        if(x<XMAX&&x>=0&&y<YMAX&&y>=0&&
                map[x][y][layer]== originalColor){
            seedFilling(x,y);
        }
    }
}

void paintWindow::undo()
{
    if(layer!=front){
        layer = (layer+TIMES-1)%TIMES;
        update();
        updateImage();
    }
}

void paintWindow::redo()
{
    if(layer!=rear){
        layer = (layer+1)%TIMES;
        update();
        updateImage();
    }
}

void paintWindow::drawRect()
{
    state = DRAWRECT;
}

void paintWindow::drawPixel()
{
    state = DRAWPIXEL;
}

void paintWindow::fillColor()
{
    state = FILLCOLOR;
}

void paintWindow::drawFullRect()
{
    state = DRAWFULLRECT;
}

void paintWindow::drawLine()
{
    state = DRAWLINE;
}

void paintWindow::drawCircle()
{
    state = DRAWCIRCLE;
}

void paintWindow::drawFullCircle()
{
    state = DRAWFULLCIRCLE;
}

void paintWindow::erase()
{
    state = ERASE;
}

void paintWindow::getColor()
{
    state  = GETCOLOR;
}

void paintWindow::showGrid()
{
    isShowGrid==true?isShowGrid=false:isShowGrid=true;
    update();
}

QLabel* paintWindow::getImage()
{
    return picture;
}

void paintWindow::saveImage(const QString &fileName,int s)
{
    QImage* img1;

    if(s==1){
        updateImage();
        img->save(fileName);
    }
    else if(s==2){
         img1 = new QImage(XMAX*2,YMAX*2,QImage::Format_ARGB32);
         for(int i=0;i<XMAX;i++){
             for(int j=0;j<YMAX;j++){
                 img1->setPixelColor(2*i,2*j,map[i][j][layer]);
                 img1->setPixelColor(2*i+1,2*j,map[i][j][layer]);
                 img1->setPixelColor(2*i,2*j+1,map[i][j][layer]);
                 img1->setPixelColor(2*i+1,2*j+1,map[i][j][layer]);
             }
         }
         img1->save(fileName);
    }
    else if(s==3){
        img1 = new QImage(XMAX*3,YMAX*3,QImage::Format_ARGB32);
        for(int i=0;i<XMAX;i++){
            for(int j=0;j<YMAX;j++){
                img1->setPixelColor(3*i,3*j,map[i][j][layer]);
                img1->setPixelColor(3*i+1,3*j,map[i][j][layer]);
                img1->setPixelColor(3*i,3*j+1,map[i][j][layer]);
                img1->setPixelColor(3*i+1,3*j+1,map[i][j][layer]);

                img1->setPixelColor(3*i+2,3*j,map[i][j][layer]);
                img1->setPixelColor(3*i+2,3*j+1,map[i][j][layer]);
                img1->setPixelColor(3*i+1,3*j+2,map[i][j][layer]);
                img1->setPixelColor(3*i,3*j+2,map[i][j][layer]);

                img1->setPixelColor(3*i+2,3*j+2,map[i][j][layer]);
            }
        }
        img1->save(fileName);
    }

}

pixel.cpp
#include "pixel.h"
#include"newdialog.h"
#include"savedialog.h"
#include<QHBoxLayout>
#include<QVBoxLayout>
#include<QWidget>
#include<QImage>
#include<QLabel>
#include<QMenu>
#include<QMenuBar>
#include<QAction>
#include<QToolBar>
#include<QPixmap>
#include<QString>
#include<QGroupBox>
#include<QGridLayout>
#include<QPicture>
#include<QPushButton>
#include<QFileDialog>
#include<QDockWidget>
#include<QMainWindow>
#include<QMessageBox>
#include<QApplication>
#include"colorbar.h"
pixel::pixel(QObject *parent)
    : QObject(parent)
{
    setLayout();
}

void pixel::setLayout()
{
    window = new QWidget;
    mainWindow = new QMainWindow;
    QVBoxLayout* vlayout = new QVBoxLayout;
    QVBoxLayout* vlayout1 = new QVBoxLayout;
    QVBoxLayout* vlayout2 = new QVBoxLayout;
    QHBoxLayout* hlayout = new QHBoxLayout;
    QHBoxLayout* hlayout1 = new QHBoxLayout;

    QDockWidget* dock = new QDockWidget(QStringLiteral("工具栏"),window);

    //设置paint窗口处于中央
    paint = new paintWindow;

    vlayout2->addStretch();
    vlayout2->addWidget(paint);
    vlayout2->addStretch();

    hlayout1->addStretch();
    hlayout1->addLayout(vlayout2);
    hlayout1->addStretch();

    dock1 = new QDockWidget(QStringLiteral("图像"),window);


    createMenu();
    createTool();
    setLeftTool();
    createColorGroup();
    dock->setWidget(leftWidget);
    dock1->setWidget(paint->getImage());
    vlayout->addWidget(menuBar);
    vlayout->addWidget(toolBar);

    toolBar->setStyleSheet("background-color:rgb(220,220,220);");

    vlayout1->addWidget(color);
    hlayout->addLayout(hlayout1);
    hlayout->addLayout(vlayout1);
    vlayout->addLayout(hlayout);
    mainWindow->addDockWidget(Qt::LeftDockWidgetArea,dock);
    mainWindow->addDockWidget(Qt::RightDockWidgetArea,dock1);

    connect(paint,SIGNAL(changeImg()),this,SLOT(updateImg()));
    connect(paint,SIGNAL(changeColor(QColor)),color,SLOT(changeColor(QColor)));

    window->setLayout(vlayout);
    window->resize(800,700);
    mainWindow->setCentralWidget(window);
    mainWindow->show();
}

void pixel::createMenu()
{
    menuBar = new QMenuBar();
    menuBar->setFixedHeight(28);
    fileMenu = menuBar->addMenu(QStringLiteral("文件"));
    editMenu = menuBar->addMenu(QStringLiteral("编辑"));
    showMenu = menuBar->addMenu(QStringLiteral("显示"));
    actionNew = fileMenu->addAction(QIcon("new.png"),QStringLiteral("&新建"));
    actionOpen = fileMenu->addAction(QIcon("open.png"),QStringLiteral("&打开"));
    actionSave = fileMenu->addAction(QIcon("save.png"),QStringLiteral("&保存"));
    actionUndo = editMenu->addAction(QIcon("undo.png"),QStringLiteral("&撤销"));
    actionRedo = editMenu->addAction(QIcon("redo.png"),QStringLiteral("&重做"));
    actionShowGrid = showMenu->addAction(QIcon("grid.png"),QStringLiteral("&显示网格"));

    actionNew->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
    actionOpen->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O));
    actionSave->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
    actionUndo->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Z));
    actionRedo->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y));

    connect(actionSave, SIGNAL(triggered()),this, SLOT(save()));
    connect(actionUndo,SIGNAL(triggered()),this,SLOT(undo()));
    connect(actionRedo,SIGNAL(triggered()),this,SLOT(redo()));
    connect(actionShowGrid,SIGNAL(triggered()),this,SLOT(showGrid()));
    connect(actionNew,SIGNAL(triggered()),this,SLOT(newFile()));
    connect(actionOpen,SIGNAL(triggered()),this,SLOT(open()));

}

void pixel::open()
{
    QString name = QFileDialog::getOpenFileName(window,
        tr("Choose Image"),
        "",
        tr("*.bmp;; *.png;; *.jpg;; *.tif;; *.GIF")); //选择路径
    if(name.isEmpty())
    {
        return;
    }
    else
    {
        QImage* img = new QImage();
        if(! ( img->load(name) ) ) //加载图像
        {
            QMessageBox msg(QMessageBox::Warning, "error", QStringLiteral("打开图像失败"),
                                 QMessageBox::Yes, NULL);
            msg.exec();
            delete img;
            return;
        }
        else{
            if(img->width()<150&&img->height()<150){
                paint->newImage(img);
                delete img;
                return;
            }
            else{
                QMessageBox msg(QMessageBox::Warning, "error", QStringLiteral("图片过大"),
                                     QMessageBox::Yes, NULL);
                msg.exec();
                delete img;
                return;
            }
        }
    }
}

bool pixel::save()
{
    filename = QFileDialog::getSaveFileName(window,
        tr("Save Image"),
        "",
        tr("*.bmp;; *.png;; *.jpg;; *.tif;; *.GIF")); //选择路径
    if(filename.isEmpty())
    {
        return false;
    }
    else
    {
        saveDialog* dialog = new saveDialog();
        dialog->show();
        connect(dialog,SIGNAL(save(int)),this,SLOT(saveImg(int)));
        return true;
    }
}

void pixel::saveImg(int size)
{
    paint->saveImage(filename,size);
}

void pixel::undo()
{
    paint->undo();
}

void pixel::redo()
{
    paint->redo();
}

void pixel::createTool()
{
    toolBar = new QToolBar(tr("&文件"));
    toolBar->addSeparator();

    toolBar->addAction(actionNew);
    toolBar->addAction(actionOpen);
    toolBar->addAction(actionSave);
    toolBar->addAction(actionUndo);
    toolBar->addAction(actionRedo);
    toolBar->addAction(actionShowGrid);
}

void pixel::setLeftTool()
{
    leftWidget = new QWidget();
    leftWidget->setStyleSheet("background-color:rgb(230,230,230);");
    QString str[] = {
        "rect.png","pixel.png","color.png","fullrect.png",
        "line.png","circle.png","fullcircle.png","erase.png","getcolor.png"
    };
    QString str1[] = {
        "rect1.png","pixel1.png","color1.png","fullrect1.png",
        "line1.png","circle1.png","fullcircle1.png","erase1.png","getcolor1.png"
    };
    drawRectBtn = new Button(str[0],str1[0],str1[0]);
    drawPixelBtn = new Button(str[1],str1[1],str1[1]);
    colorBtn = new Button(str[2],str1[2],str1[2]);
    drawFullRectBtn = new Button(str[3],str1[3],str1[3]);
    drawLineBtn = new Button(str[4],str1[4],str1[4]);
    drawCircleBtn = new Button(str[5],str1[5],str1[5]);
    drawFullCircleBtn = new Button(str[6],str1[6],str1[6]);
    eraseBtn = new Button(str[7],str1[7],str1[7]);
    getColorBtn = new Button(str[8],str1[8],str1[8]);

    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->addWidget(drawRectBtn);
    vlayout->addWidget(drawPixelBtn);
    vlayout->addWidget(colorBtn);
    vlayout->addWidget(drawFullRectBtn);
    vlayout->addWidget(drawLineBtn);
    vlayout->addWidget(drawCircleBtn);
    vlayout->addWidget(drawFullCircleBtn);
    vlayout->addWidget(eraseBtn);
    vlayout->addWidget(getColorBtn);
    vlayout->addStretch();
    leftWidget->setLayout(vlayout);

    drawPixelBtn->setPressImg();

    connect(drawRectBtn, SIGNAL(clicked()),this, SLOT(drawRect()));
    connect(drawPixelBtn, SIGNAL(clicked()),this, SLOT(drawPixel()));
    connect(colorBtn,SIGNAL(clicked()),this,SLOT(fillColor()));
    connect(drawFullRectBtn,SIGNAL(clicked()),this,SLOT(drawFullRect()));
    connect(drawLineBtn,SIGNAL(clicked()),this,SLOT(drawLine()));
    connect(drawCircleBtn,SIGNAL(clicked()),this,SLOT(drawCircle()));
    connect(drawFullCircleBtn,SIGNAL(clicked()),this,SLOT(drawFullCircle()));
    connect(eraseBtn,SIGNAL(clicked()),this,SLOT(erase()));
    connect(getColorBtn,SIGNAL(clicked()),this,SLOT(getColor()));
}

void pixel::newFile()
{
    QMessageBox msg(QMessageBox::Warning, "warning", QStringLiteral("是否保存当前图像?"),
                         QMessageBox::Yes | QMessageBox::No, NULL);
    if(msg.exec()==QMessageBox::Yes){
        if(!save())return;
    }
    newDialog* dialog = new newDialog;
    connect(dialog,SIGNAL(sendIndex(int,int)),paint,SLOT(changeSize(int,int)));
    dialog->show();
}

void pixel::updateIcon(int id)
{
    drawRectBtn->setReleaseImg();
    drawPixelBtn->setReleaseImg();
    colorBtn->setReleaseImg();
    drawFullRectBtn->setReleaseImg();
    drawLineBtn->setReleaseImg();
    drawCircleBtn->setReleaseImg();
    drawFullCircleBtn->setReleaseImg();
    eraseBtn->setReleaseImg();
    getColorBtn->setReleaseImg();

    switch(id){
    case 1:drawRectBtn->setPressImg();break;
    case 2:drawPixelBtn->setPressImg();break;
    case 3:colorBtn->setPressImg();break;
    case 4:drawFullRectBtn->setPressImg();break;
    case 5:drawLineBtn->setPressImg();break;
    case 6:drawCircleBtn->setPressImg();break;
    case 7:drawFullCircleBtn->setPressImg();break;
    case 8:eraseBtn->setPressImg();break;
    case 9:getColorBtn->setPressImg();break;
    default:break;
    }
}

void pixel::drawRect()
{
    paint->drawRect();
    updateIcon(1);
}

void pixel::drawPixel()
{
    paint->drawPixel();
    updateIcon(2);
}

void pixel::fillColor()
{
    paint->fillColor();
    updateIcon(3);
}

void pixel::drawFullRect()
{
    paint->drawFullRect();
    updateIcon(4);
}

void pixel::drawLine()
{
    paint->drawLine();
    updateIcon(5);
}

void pixel::drawCircle()
{
    paint->drawCircle();
    updateIcon(6);
}

void pixel::drawFullCircle()
{
    paint->drawFullCircle();
    updateIcon(7);
}

void pixel::erase()
{
    paint->erase();
    updateIcon(8);
}

void pixel::getColor()
{
    paint->getColor();
    updateIcon(9);
}

void pixel::showGrid()
{
    paint->showGrid();
}

void pixel::createColorGroup()
{
    color = new colorWindow();
}

void pixel::updateImg()
{
    dock1->setWidget(paint->getImage());
}

pixel::~pixel()
{

}

savedialog.cpp
#include"savedialog.h"
#include<QRadioButton>
#include<QGroupBox>
#include<QVBoxLayout>
#include<QHBoxLayout>
#include<QPushButton>
#include<QButtonGroup>
#include<QLineEdit>
#include<QLabel>
#include<QMessageBox>

saveDialog::saveDialog(QWidget* parent):QWidget(parent)
{
    QVBoxLayout* vlayout = new QVBoxLayout;
    QHBoxLayout* hlayout = new QHBoxLayout;

    okBtn = new QPushButton(QStringLiteral("确定"));
    cancelBtn = new QPushButton(QStringLiteral("取消"));

    radioGroup = new QButtonGroup();
    radio1 = new QRadioButton(QStringLiteral("原始大小(1x1)"),this);
    radio2 = new QRadioButton(QStringLiteral("4倍大小(2x2)"),this);
    radio3 = new QRadioButton(QStringLiteral("9倍大小(3x3)"),this);

    radio1->setChecked(true);
    radioGroup->addButton(radio1,1);
    radioGroup->addButton(radio2,2);
    radioGroup->addButton(radio3,3);

    hlayout->addWidget(okBtn);
    hlayout->addWidget(cancelBtn);

    vlayout->addWidget(radio1);
    vlayout->addWidget(radio2);
    vlayout->addWidget(radio3);
    vlayout->addLayout(hlayout);

    connect(okBtn,SIGNAL(clicked()),this,SLOT(saveFile()));
    connect(cancelBtn,SIGNAL(clicked()),this,SLOT(close()));

    setLayout(vlayout);
    setWindowFlags(Qt::WindowStaysOnTopHint);
    setWindowModality(Qt::ApplicationModal);
    setWindowTitle(QStringLiteral("保存设置"));
}

void saveDialog::saveFile()
{
    emit(save(radioGroup->checkedId()));
    close();
}

main.cpp
#include "pixel.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    pixel w;
    a.setWindowIcon(QIcon("box.ico"));
    return a.exec();
}


  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值