【JAVA】简易美颜相机

简易美颜相机

简易美颜相机,是我最初接触JAVA的小项目,通过这个项目,我初步学会了许多JAVA的基础知识,下面就让我们开始吧!

首先让我们理清整个项目的大概逻辑:

1.一张图片和摄像头的显示以及各种不同的处理效果,是在窗体上显示的,所以我们首先需要创建需要一个窗体;

2.处理效果是鼠标点击窗体上的按钮来实现的,所以我们肯定需要添加许多按钮,为了美观也可以添加面板和不同的布局管理器;

3.图像是在窗体上“画”出来的,所以我们肯定需要在窗体上获取画笔,而不同的处理效果则是画笔的不同“画法”来实现的;

4.摄像头方面首先需要导入java额外的webcam包(这里不再赘述,大家可以自行百度解决),然后需要添加线程来控制开启和关闭,其余的跟处理图片的步骤类似。

总体就是这四步骤啦,下面一个个来实现。

/*1.1显示美颜相机界面(功能)

 *1.2监听器:设置界面程序的交互功能

 *1.3在界面上显示图像效果(原图,处理的效果图):获取画笔

 */

public class drawPixel0715 {

public static void main(String[] args){

drawPixel0715 ui=new drawPixel0715();

ui.showUI();

}

//1.1显示操作界面的方法

//swing都有一个paint方法,绘制组件

public void showUI(){

//窗体:默认边框布局

MyFrame jf=new MyFrame();

//像素点

jf.setSize(1300,800);//窗体的特有设置大小方法

jf.setTitle("PC版美颜相机");//窗体的标题

//设置居中显示

jf.setLocationRelativeTo(null);

//设置退出进程

jf.setDefaultCloseOperation(3);

//设置流式布局管理器

BorderLayout border=new BorderLayout();

jf.setLayout(border);

//2.面板:默认是流式布局

JPanel eastPanel=new JPanel();

//设置背景色

eastPanel.setBackground(Color.GRAY);

Dimension dm=new Dimension(140,0);

//处理JFrame,其他组件设置大小都是该方法

eastPanel.setPreferredSize(dm);

jf.add(eastPanel,BorderLayout.EAST);

//2.按钮

PixelMouse mouse=new PixelMouse();

    String[] name={"原图","马赛克","灰度","底片","浮雕","油画","怀旧","黑白","打开图片","保存图片","打开摄像头","关闭摄像头","清屏"};

    for(int i=0;i<name.length;i++){

JButton jbu=new JButton(name[i]);

            jbu.setPreferredSize(new Dimension(200,30));//该dimension不能重复利用

            eastPanel.add(jbu);

jbu.addActionListener(mouse);

    

    }

jf.setVisible(true);

//1(3).获取画笔:图像显示在哪个组件上,画笔就从该组件上获取

//从窗体上获取画笔对象,一定要在窗体显示可见之后

Graphics g=jf.getGraphics();

//1(2).监听器

//给窗体添加鼠标监听器,给监听器绑定处理类

jf.addMouseListener(mouse);

//给按钮添加动作监听器

//a.事件源:当前动作所发生的组件

//b.确定监听器方法:动作监听器

//c.绑定事件处理类

mouse.gr=g;

mouse.getMyFrame(jf);

//把PixelMouse类的数组传递给MyFrame

jf.arrB=mouse.arrB;

}

}

这里需要特别注意,我们需要创建一个类来继承JFrame类,重写paint方法来解决图像的重绘问题(即拖动窗体和暂时隐藏图像效果会消失),代码如下:

//1.4自定义窗体类

public class MyFrame extends JFrame{

public BufferedImage[] arrB;

//定义set方法,初始化属性

//super表示当前类的子类对象

//this表示当前类对象

//重写paint方法

public void paint(Graphics g){

//1.绘制组件

super.paint(g);

System.out.println("绘制组件!");

//2.图像效果

for(int i=0;i<arrB.length;i++){

BufferedImage bufferImage=arrB[i];

g.drawImage(bufferImage, 40, 90, 1080,540,null);

}

}

3.图像处理画法

在处理图像效果时,我们要从微观的角度来考虑:图像是由一个个排列紧密的像素点构成的,这些像素点可以看作一个二维数组,每一个像素点具有坐标、颜色和大小,坐标是x、y来确定,颜色以int型(4个字节32位)数字来表示,又是由透明度(这部分暂时不作处理)和红绿蓝三原色组成的,这四个成员占据依次占据int类型的8位,这里的处理效果是对三原色进行不同处理,例如马赛克就是将一部分像素点放大并把其余像素点覆盖,灰度就是创建一个新的color对象,新三原色数值都是原三原色的均值等等,我们百度参考他人设计好的算法。

然后我们注意到,如果图片分辨率较高,这时就会“画”得比较慢,我们可以添加缓冲区来解决,然后获取缓冲区画笔。图片本身是bufferedImage类的对象,上述提到的二维数组也是通过bufferedImage的getWidth和getHeight来获取。

代码如下:

public class PixelMouse implements MouseListener,ActionListener{

//全局变量:属性

public Graphics gr;  //保存传递过来的画笔对象

public String name;

public File file;

public File f2;

public File file2;

public BufferedImage bufferImage;

//定义BufferedImage数组,保存绘制的缓冲图像数据

public BufferedImage[] arrB=new BufferedImage[100];

//操作数组的下标

public int index=0;

public MyFrame jf;

public void getMyFrame(MyFrame jf){this.jf=jf;}

   public void actionPerformed(ActionEvent e){

     //识别点击的按钮对象

     //获取按钮上的内容,局部变量

     name = e.getActionCommand();

     if("打开图片".equals(name)){

     //实现打开电脑中不同图片的功能,需要添加文件选择器

     JFileChooser jfc = new JFileChooser();

     //实现文件的过滤功能,第一个参数是选项,第二个和第三个是筛选的文件后缀,可任意添加筛选类型

     FileNameExtensionFilter filter = new FileNameExtensionFilter(

          "JPG & PNG Images", "jpg", "png");

  jfc.setFileFilter(filter);

  //打开菜单

     jfc.showOpenDialog(null);

     //选择的文件路径

     file =jfc.getSelectedFile();

     System.out.println("file:"+file);

     }

     if("保存图片".equals(name)){

     //代码形式与打开图片的类似

     JFileChooser jfc2 = new JFileChooser();

     jfc2.showSaveDialog(null);

     file2 =jfc2.getSelectedFile();

     System.out.println("已保存");

     save();

     }

     System.out.println("点击按钮  "+name);

    }

//图像效果处理方法

    public void mouseClicked(MouseEvent e){

     System.out.println("点击");  

     //获取当前的坐标值

     int x = e.getX();

     int y = e.getY();

     drawPixel();

    }

     //加载图像数据

        // ImageIcon icon = new ImageIcon("E:\\23.jpg");

        //render是buff父类,作参数时直接使用子类buff参数,相当于自动转型

     public void drawPixel(){

     File path = file;

     int[][] arrPixel = getImagePixel(path);//  20  30

     //1.创建缓冲区

      bufferImage=new BufferedImage(arrPixel.length,arrPixel[0].length

     ,BufferedImage.TYPE_INT_RGB);

     //2.获取缓冲区画笔

     Graphics g2=bufferImage.getGraphics();

        if("打开图片".equals(name)){

         for(int i=0;i<arrPixel.length;i++){

          for(int j=0;j<arrPixel[i].length;j++){

          int pixel = arrPixel[i][j];   //取出像素值

          Color color3 = new Color(pixel);  //转成color对象,设置给画笔

          g2.setColor(color3);

          //绘制像素点

          g2.fillRect(i, j, 1, 1);

          }

          }

            }

       if("马赛克".equals(name)) {

       for(int i=0;i<arrPixel.length;i++){

     for(int j=0;j<arrPixel[i].length;j+=8){

     int pixel = arrPixel[i][j];   //取出像素值

     //右移提取 三原色:pixel>>0&0xFF

     Color color = new Color(pixel);  //转成color对象,设置给画笔

//     color.getRed()

//     color.getGreen();

     g2.setColor(color);

     //绘制像素点

     g2.fillRect(i, j, 8, 8);

    

     }

     }

       }

       if("原图".equals(name)){

    for(int i=0;i<arrPixel.length;i++){

     for(int j=0;j<arrPixel[i].length;j++){

     int pixel = arrPixel[i][j];   //取出像素值

     Color color3 = new Color(pixel);  //转成color对象,设置给画笔

     g2.setColor(color3);

     //绘制像素点

     g2.fillRect(i, j, 1, 1);

     }

     }

       }

       if("灰度".equals(name)){

    for(int i=0;i<arrPixel.length;i++){

     for(int j=0;j<arrPixel[i].length;j++){

     int pixel2 = arrPixel[i][j];

     Color color2=new Color(pixel2);

     int r=color2.getRed();

     int g=color2.getGreen();

     int b=color2.getBlue();

     int gray=(r+g+b)/3;

     Color newcolor=new Color(gray,gray,gray);

     g2.setColor(newcolor);

     //绘制像素点

     g2.fillRect(i, j, 1, 1);

       }

     }

       }

       if("底片".equals(name)){

    for(int i=0;i<arrPixel.length;i++){

     for(int j=0;j<arrPixel[i].length;j++){

     int pixel3 = arrPixel[i][j];

     Color color3=new Color(pixel3);

     int r=255-color3.getRed();

     int g=255-color3.getGreen();

     int b=255-color3.getBlue();

     Color newcolor2=new Color(r,g,b);

     g2.setColor(newcolor2);

     //绘制像素点

     g2.fillRect(i, j, 1, 1);

    

     }

     }

       }

       if("浮雕".equals(name)){

    for(int i=0;i<arrPixel.length-1;i++){

     for(int j=0;j<arrPixel[i].length-1;j++){

     int pixel4 = arrPixel[i][j];

     int pixel5 = arrPixel[i+1][j+1];

     Color dd=new Color(pixel5);

     Color cc=new Color(pixel4);

     int r=128+cc.getRed()-dd.getRed();

     int g=128+cc.getGreen()-dd.getGreen();

     int b=128+cc.getBlue()-dd.getBlue();

      if (r > 255)

                     r = 255;

                 if (r < 0)

                     r = 0;

                 if (g > 255)

                     g = 255;

                 if (g < 0)

                     g = 0;

                 if (b > 255)

                     b = 255;

                 if (b < 0)

                     b = 0;

     Color newcolor3=new Color(r,g,b);

     g2.setColor(newcolor3);

     //绘制像素点

     g2.fillRect(i, j, 1, 1);

      }

     }

       }

       if("油画".equals(name)){

    for(int i=0;i<arrPixel.length;i=i+4){

     for(int j=0;j<arrPixel[i].length;j=j+4){

     int pixel6 = arrPixel[i][j];   //取出像素值

     Color color6 = new Color(pixel6);  //转成color对象,设置给画笔

     g2.setColor(color6);

     //绘制像素点

     g2.fillRect(i, j, 5, 5);

     }

     }

       }

     if("怀旧".equals(name)){

     for(int i=0;i<arrPixel.length;i++){

      for(int j=0;j<arrPixel[i].length;j++){

      int pixel7 = arrPixel[i][j];   //取出像素值

      Color color7 = new Color(pixel7);  //转成color对象,设置给画笔

      int[] rgb=new int[3];

rgb[0] = (int) (0.393*color7.getRed()+0.769*color7.getGreen()+0.189*color7.getBlue());

rgb[1] = (int) (0.349*color7.getRed()+0.686*color7.getGreen()+0.168*color7.getBlue());

rgb[2] = (int) (0.272*color7.getRed()+0.534*color7.getGreen()+0.131*color7.getBlue());

for(int m=0;m<3;m++) {

if(rgb[m]<0)

rgb[m]=0;

else if(rgb[m]>255)

rgb[m]=255;

}

Color newcolor7 = new Color(rgb[0],rgb[1],rgb[2]);

g2.setColor(newcolor7);

      //绘制像素点

      g2.fillRect(i, j, 1, 1);

      }

      }

        }

     if("黑白".equals(name)){

     for(int i=0;i<arrPixel.length;i++){

      for(int j=0;j<arrPixel[i].length;j++){

      int pixel2 = arrPixel[i][j];

      Color color2=new Color(pixel2);

      int r=color2.getRed();

      int g=color2.getGreen();

      int b=color2.getBlue();

      int gray=(r+g+b)/3;

      if(gray>=128){

      r=g=b=255;

      }

      else { r=g=b=0;}

      Color newcolor=new Color(r,g,b);

      g2.setColor(newcolor);

      //绘制像素点

      g2.fillRect(i, j, 1, 1);

        }

      }

        }

     if("清屏".equals(name)){

     jf.repaint();

     for(int i=0;i<arrB.length;i++){

    arrB[i]=null;

     }

     }

   

     gr.drawImage(bufferImage, 40, 90,1080,540, null);

     System.out.println("name:"+name);

     //把图像效果保存在数组中

     arrB[index++] = bufferImage;

     }

    public void save(){

     try{

if(!file2.exists()){

file2.createNewFile();

}

ImageIO.write(bufferImage, "png", file2);

System.out.println("xxxx");

     }

     catch(IOException e) {

e.printStackTrace();

}

    

    }

    //获取图片的像素值

    public int[][] getImagePixel(File path){

     //创建文件对象(图片)

        

     //读取图片文件数据,返回缓冲图片对象

     BufferedImage bufferImage = null;

//这里添加处理异常语句,避免程序在出错时直接中断

     try {

bufferImage = ImageIO.read(file);

} catch (IOException e) {

e.printStackTrace();

}

     //根据缓冲图片的大小确定二维数组

     int w = bufferImage.getWidth();

     int h = bufferImage.getHeight();

     int[][] arrPixel = new int[w][h];

    

     for(int i=0;i<w;i++){

     for(int j=0;j<h;j++){

     //获取每个位置的像素值

     int pixel = bufferImage.getRGB(i, j);

     arrPixel[i][j] = pixel;

     }

     }

     return arrPixel;

    }

      

    public void mousePressed(MouseEvent e){

    

    }

    public void mouseReleased(MouseEvent e){

    

    }

    public void mouseEntered(MouseEvent e){

    

    }

    public void mouseExited(MouseEvent e){

    

    }

}

4.摄像头

摄像头处理实际上就是一直从摄像头获取实时图片来处理,就是说这里需要创建一个类来继承Thread线程类。但是,这里我不知道如何将图片处理的算法和摄像头的算法共享使用,所以我就创建了一个Pixel类复制图片算法,代码如下:

public class Pixel {

    public void drawPixel1(BufferedImage buffImage,Graphics gr) {

     int[][] arrPixel = getImagePixel(buffImage);

       

       for(int i=0;i<arrPixel.length;i++){

     for(int j=0;j<arrPixel[i].length;j+=8){

     int pixel = arrPixel[i][j];   //取出像素值

     //右移提取 三原色:pixel>>0&0xFF

     Color color = new Color(pixel);  //转成color对象,设置给画笔

          //      color.getRed()

         //      color.getGreen();

     gr.setColor(color);

     //绘制像素点

     gr.fillRect(i+300, j+200, 8, 8);

    

     }

     }

    //gr.drawImage(buffImage, 300, 150, 540, 540, null);

       //jf.repaint();

    }

    public void drawPixel2(BufferedImage buffImage,Graphics gr) {

     int[][] arrPixel = getImagePixel(buffImage);

       

    for(int i=0;i<arrPixel.length;i++){

     for(int j=0;j<arrPixel[i].length;j++){

     int pixel2 = arrPixel[i][j];

     Color color2=new Color(pixel2);

     int r=color2.getRed();

     int g=color2.getGreen();

     int b=color2.getBlue();

     int gray=(r+g+b)/3;

     Color newcolor=new Color(gray,gray,gray);

     gr.setColor(newcolor);

     //绘制像素点

     gr.fillRect(i+300, j+200, 1, 1);

       }

     }

    //gr.drawImage(buffImage, 300, 150, 540, 540, null);

    //jf.repaint();

    }

    public void drawPixel3(BufferedImage buffImage,Graphics gr) {

     int[][] arrPixel = getImagePixel(buffImage);

       

     for(int i=0;i<arrPixel.length;i++){

     for(int j=0;j<arrPixel[i].length;j++){

     int pixel3 = arrPixel[i][j];

     Color color3=new Color(pixel3);

     int r=255-color3.getRed();

     int g=255-color3.getGreen();

     int b=255-color3.getBlue();

     Color newcolor2=new Color(r,g,b);

     gr.setColor(newcolor2);

     //绘制像素点

     gr.fillRect(i+300, j+200, 1, 1);

    

        }

         }

    //gr.drawImage(buffImage, 300, 150, 540, 540, null);

        System.out.println("已调用底片处理方法");

     //jf.repaint();

    }

    public void drawPixel4(BufferedImage buffImage,Graphics gr) {

     int[][] arrPixel = getImagePixel(buffImage);

       

    for(int i=0;i<arrPixel.length-1;i++){

     for(int j=0;j<arrPixel[i].length-1;j++){

     int pixel4 = arrPixel[i][j];

     int pixel5 = arrPixel[i+1][j+1];

     Color dd=new Color(pixel5);

     Color cc=new Color(pixel4);

     int r=128+cc.getRed()-dd.getRed();

     int g=128+cc.getGreen()-dd.getGreen();

     int b=128+cc.getBlue()-dd.getBlue();

      if (r > 255)

                     r = 255;

                 if (r < 0)

                     r = 0;

                 if (g > 255)

                     g = 255;

                 if (g < 0)

                     g = 0;

                 if (b > 255)

                     b = 255;

                 if (b < 0)

                     b = 0;

     Color newcolor3=new Color(r,g,b);

     gr.setColor(newcolor3);

     //绘制像素点

     gr.fillRect(i+300, j+200, 1, 1);

      }

     }

    //gr.drawImage(buffImage, 300, 150, 540, 540, null);

    //jf.repaint();

    }

    public void drawPixel5(BufferedImage buffImage,Graphics gr) {

     int[][] arrPixel = getImagePixel(buffImage);

       

    for(int i=0;i<arrPixel.length;i=i+4){

     for(int j=0;j<arrPixel[i].length;j=j+4){

     int pixel6 = arrPixel[i][j];   //取出像素值

     Color color6 = new Color(pixel6);  //转成color对象,设置给画笔

     gr.setColor(color6);

     //绘制像素点

     gr.fillRect(i+300, j+200, 5, 5);

     }

     }

   // gr.drawImage(buffImage, 300, 150, 540, 540, null);

    //jf.repaint();

       }

    public void drawPixel6(BufferedImage buffImage,Graphics gr) {

     int[][] arrPixel = getImagePixel(buffImage);

   

     for(int i=0;i<arrPixel.length;i++){

      for(int j=0;j<arrPixel[i].length;j++){

      int pixel7 = arrPixel[i][j];   //取出像素值

      Color color7 = new Color(pixel7);  //转成color对象,设置给画笔

      int[] rgb=new int[3];

rgb[0] = (int) (0.393*color7.getRed()+0.769*color7.getGreen()+0.189*color7.getBlue());

rgb[1] = (int) (0.349*color7.getRed()+0.686*color7.getGreen()+0.168*color7.getBlue());

rgb[2] = (int) (0.272*color7.getRed()+0.534*color7.getGreen()+0.131*color7.getBlue());

for(int m=0;m<3;m++) {

if(rgb[m]<0)

rgb[m]=0;

else if(rgb[m]>255)

rgb[m]=255;

}

Color newcolor7 = new Color(rgb[0],rgb[1],rgb[2]);

gr.setColor(newcolor7);

      //绘制像素点

gr.fillRect(i+300, j+200, 1, 1);

         

      }

      }

         //gr.drawImage(buffImage, 300, 150, 540, 540, null);

     //jf.repaint();

        }

    public void drawPixel7(BufferedImage buffImage,Graphics gr) {

     int[][] arrPixel = getImagePixel(buffImage);

     for(int i=0;i<arrPixel.length;i++){

      for(int j=0;j<arrPixel[i].length;j++){

      int pixel2 = arrPixel[i][j];

      Color color2=new Color(pixel2);

      int r=color2.getRed();

      int g=color2.getGreen();

      int b=color2.getBlue();

      int gray=(r+g+b)/3;

      if(gray>=128){

      r=g=b=255;

      }

      else { r=g=b=0;}

      Color newcolor=new Color(r,g,b);

      gr.setColor(newcolor);

      //绘制像素点

      gr.fillRect(i+300, j+200, 1, 1);

     

        }

      }

         //gr.drawImage(buffImage, 300, 150, 540, 540, null);

     //jf.repaint();

        }

  

public int[][] getImagePixel(BufferedImage buffImage) {

     //创建图片文件

    

     //根据图片大小设置数组

     int w = buffImage.getWidth();

     int h = buffImage.getHeight();

     int[][] arrPixel = new int[w][h];

    

     for(int i=0;i<w;i++) {

     for(int j=0;j<h;j++) {

     //获取每个像素点的值

     int pixel = buffImage.getRGB(i, j);

     arrPixel[i][j] = pixel;

     }

     }

     return arrPixel;

    }

}

public class Threadop extends Thread{

public Graphics gr;

public int op;

public BufferedImage bufferImage;

public Pixel pixel = new Pixel();

public String name; //区分不同处理效果

public void setop(int op){

this.op=op;

}

public void setPixelName(String n) {

name = n;

}

public void run(){

Webcam webcam = Webcam.getDefault();

    webcam.open();

while(true){

     bufferImage=webcam.getImage();

     if("马赛克".equals(name)) {

     pixel.drawPixel1(bufferImage, gr);

     }

     else if("黑白".equals(name)) {

     pixel.drawPixel7(bufferImage, gr);

     }

     else if("底片".equals(name)) {

     pixel.drawPixel3(bufferImage, gr);

     //System.out.println("方法调用了");

     }

     else if("灰度".equals(name)) {

     pixel.drawPixel2(bufferImage, gr);

     }

     else if("浮雕".equals(name)) {

     pixel.drawPixel4(bufferImage, gr);

     }

     else if("怀旧".equals(name)) {

     pixel.drawPixel6(bufferImage, gr);

     }

     else if("油画".equals(name)) {

     pixel.drawPixel5(bufferImage, gr);

     }

     else{

     gr.drawImage(bufferImage, 300, 200, 640, 480, null);

     }

     if(op==1){break;}

}

}

}

然后,我们也要在窗体里添加相应的摄像头按钮,在监听器类的全局属性中创建Threadop对象,在actionPerformed方法里添加相应方法,代码如下:

public Webcam webcam;

public Threadop tr=new Threadop();

public void getwebcam(Webcam webcam){

        this.webcam=webcam;

}

 public void actionPerformed(ActionEvent e){

     //识别点击的按钮对象

     //获取按钮上的内容,局部变量

     tr.gr=gr;//将监听器中已保存的画笔传给线程中的画笔

     name = e.getActionCommand();

     if("打开图片".equals(name)){

     //实现打开电脑中不同图片的功能,需要添加文件选择器

     JFileChooser jfc = new JFileChooser();

     //实现文件的过滤功能,第一个参数是选项,第二个和第三个是筛选的文件后缀,可任意添加筛选类型

     FileNameExtensionFilter filter = new FileNameExtensionFilter(

          "JPG & PNG Images", "jpg", "png");

  jfc.setFileFilter(filter);

  //打开菜单

     jfc.showOpenDialog(null);

     //选择的文件路径

     file =jfc.getSelectedFile();

     System.out.println("file:"+file);

     }

     if("保存图片".equals(name)){

     //代码形式与打开图片的类似

     JFileChooser jfc2 = new JFileChooser();

     jfc2.showSaveDialog(null);

     file2 =jfc2.getSelectedFile();

     System.out.println("已保存");

     save();

     }

     if("打开摄像头".equals(name)){

     tr.start();

     System.out.println(tr+"  op  "+tr.op);

     }

     if("关闭摄像头".equals(name)){

tr.setop(1);

System.out.println(tr+"  op  "+tr.op);

System.out.println("关闭");

jf.repaint();

     }

       if("马赛克".equals(name)) {

  tr.setPixelName(name);

  }

  if("黑白".equals(name)) {

  tr.setPixelName(name);

  }

  if("灰度".equals(name)) {

  tr.setPixelName(name);

  }

  if("怀旧".equals(name)) {

  tr.setPixelName(name);

  }

  if("油画".equals(name)) {

  tr.setPixelName(name);

  }

  if("底片".equals(name)) {

  tr.setPixelName(name);

  }

  if("浮雕".equals(name)) {

  tr.setPixelName(name);

  }

    

     System.out.println("点击按钮  "+name);

    }

这样,我们的项目就基本完成了。

实现效果如下:

基本界面:

图像处理效果:

(打开摄像头)

 

 (灰度效果)

总结:

这个小项目在老师的指导下,历经千辛万苦才完成,从只能显示图片、不同效果处理一张图片、处理多张图片、使用摄像头、不同效果处理摄像头,一步步走来,在写这篇教程的过程中,我真实地感觉自己的动手写代码能力提高了不少,许多基础知识都灵活地运用其中,作品完成时我内心有说不尽的非常开心与激动。学无止境,我会一直走下去的。最后,感谢您的阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值