[Qt C++] 开发一个像素画工具
来源:互联网 发布:免费云计算平台创业 编辑:程序博客网 时间:2024/04/28 03:32
代码:http://download.csdn.net/detail/zju_fish1996/9608840
像素画,是以像素为基本单位进行绘制的画。同时,它也是一种设计风格,常用于图标(ICon)设计、logo设计、表情设计以及经典像素风游戏设计。像素画的绘制上手比较容易,对创作者最基本的要求是对色彩的把握,如明度对比、纯度对比。因为在像素画中,具体的线条概念可以是不明确的,而更多是由色彩来表达形体的。
开发这款工具的初衷,就是为了方便以后的设计。当然市面上也有类似的产品了,但是很多都不是免费的(当然本来也没有多少设计软件是免费的),我感觉它本身的实现并不难,所以就花了一点时间来自己动手写它。
现在的功能还不那么完善,但是最基本的功能已经实现了,包括这款工具的所有图标都是用它自身绘制出来的。
代码框架
继承自QToolButton, 在其基础上添加了一些函数。主要用于改变按钮样式。
colorbar.h:
实现渐变的颜色条,继承自QWidget, 颜色改变后,可向画板、颜色面板发出信号通知它们修改颜色。
功能介绍
同样,可以加载一般的图片,但是大小也限制在150X150以下。
详细设计
(一)画板
为了实时显示鼠标移动过程中的绘制状态,需要在一开始启动鼠标轨迹追踪(setMouseTracing(true))。
缓存
此外,因为鼠标移动时也会实时绘制,所以我们另外使用一个集合容器(currentPoint)来维护这些点,每次使用后就及时清空。
除了当前画板的显示,我们在右侧还提供了实际图像的显示,这个图像由QImage暂存,因为QImage提供了像素点的底层操作。我们显示的时候,是将map数组的所有像素颜色直接调用setPixelColor复制过去的。又因为图像的显示是由主窗口控制的,所以我们提供了一个函数来返回包含这个QImage的QLabel的指针。由于新建的时候这个QImage将不再指向原来的内容,我们会发射一个信号通知主窗口更新图像指针。
撤回与重做
颜色填充使用的算法是种子填充法,也就是不断地向四周递归搜索,如果颜色相同的话。我们知道点的邻域有四邻域和八邻域,计算机图形学相关的书籍指出:在填充算法中,我们一般选择四邻域。八邻域往往会导致“过分”填充,而四邻域往往会导致填充“不足”,但是,相比之下,不足是可以弥补的,而过分填充却是难以弥补的,所以我们更倾向于四邻域填充算法。
(二)颜色条
图片资源(均有该像素画工具绘制)
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
代码
#ifndef BUTTON#define BUTTON#include<QToolButton>class Button : public QToolButton{ Q_OBJECTprivate: 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
#ifndef COLORBAR_H#define COLORBAR_H#include<QWidget>class colorBarLight : public QWidget{ Q_OBJECTpublic: static QColor color; colorBarLight(QWidget* parent = 0);signals: void selectColor(QColor);protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *);};class colorBarAlpha : public QWidget{ Q_OBJECTpublic: 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_OBJECTprivate: 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_OBJECTprivate: 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_OBJECTprivate: 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_OBJECTprivate: 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_OBJECTprivate: 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
#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();}
#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); }}
#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();}
- [Qt C++] 开发一个像素画工具
- 开发了一个小工具
- Qt开发小工具之gif转换器
- 我开发的一个端口映射小工具
- 实用小工具:像素尺子
- 解决一个问题,发布一个自己开发的小工具
- Qt小工具
- 我开发的一个信息管理小工具——PersonalInfo
- OSGi开发中方便查找的一个小工具
- 开发一个小工具重温C#经典问题
- 一个Symfony2开发必备的调试小工具 LadybugBundle
- iOS- 快速开发一个app(一些包工具等)
- Qt 5.3 下OpenCV 2.4.11 开发(4)Mat 像素引用
- Qt 5.3 下OpenCV 2.4.11 开发(5)最高效的像素引用
- Qt QImage像素格式小结
- IOS 平铺一个像素
- 一个像素的activity
- 一个像素的Activity
- 图片相似算法(1)
- N皇后问题
- 自定义switch
- UVA 1632 Alibaba
- 深入理解TAILQ队列
- [Qt C++] 开发一个像素画工具
- linux虚拟机 pxe
- Webx日志系统初始化
- poj 3281 Dining(最大流)
- libuv的学习(一)
- 图解css3之box-sizing
- 程序员批注《语言学教程》——第四章 从词语到篇章
- 机器人移动问题
- Sqlite数据库基础