Java语言怎么实现一个简单的画图板的功能呢,要支持鼠标的操作并且保存图片

Java语言怎么实现一个简单的画图板的功能呢,要支持鼠标的操作并且保存图片

问题描述:

Java语言怎么实现一个简单的画图板的功能呢,要支持鼠标的操作并且保存图片

一、画图板界面实现

所需用到的主要API类:JFrame,JButton,FlowLayout,Graphics以及一些相关的类;

先创建窗体,设置相关属性,再添加按钮。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JButton;
import javax.swing.JFrame;

public class Draw extends JFrame{

public static void main(String args[]){
    Draw dr = new Draw();
    dr.showdraw();
}
public void showdraw(){
    //继承后JFrame后无需实例化
    this.setTitle("画图板");
    this.setSize(700,500);
    //frame.setResizable(false);
    this.setDefaultCloseOperation(3);
    this.setLocationRelativeTo(null);
    FlowLayout f1 = new FlowLayout();
    this.setLayout(f1);
        //实例化监听器
    DrawListener lis = new DrawListener();
    //创建图形按钮和颜色按钮
    String[] array ={"Line","Pencil","Rect","Oval","RoundRect","fillRect",
            "fillArc","fillOval","Text","Image","Triangle","Polygon"};
    for(int i=0 ; i<array.length ;i++){
        JButton button = new JButton(array[i]);
        this.add(button);
        button.addActionListener(lis);
    }
    Color[] colorArray ={Color.black,Color.blue,
            Color.green,Color.red};
    for(int i=0 ; i<colorArray.length ; i++){
        JButton button = new JButton();
        button.setBackground(colorArray[i]);
        button.setPreferredSize(new Dimension(30,30));//设置按钮大小
        this.add(button);
        button.addActionListener(lis);
    }
    this.setVisible(true);  //setVisible设置窗体可见,放在所有组件后

    Graphics g = this.getGraphics();
    this.addMouseListener(lis);//用this指代frame可能出错
    this.addMouseMotionListener(lis);

    lis.setG(g);

}

二、监听类的实现

所需用到的主要API类:MouseAdapter,BasicStroke,Color,Graphics,JButton以及相关的类。以及ActionListener接口

监听按钮上对应的图形或颜色,并根据得到的内容实现对应的操作,具体的画图在Shape类中实现

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;
import javax.swing.JButton;

//先继承类,后继承接口
public class DrawListener extends MouseAdapter implements ActionListener{

private int x1, y1, x2, y2,x3,y3,sx,sy,ex,ey;
private Graphics2D g2;
private String str = "Line";
private Color color;
private int flag = 1;//用于标记是否是第一次画线

public void setG(Graphics g){
    g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);// 设置画笔开启抗锯齿

}

public void actionPerformed(ActionEvent e){
    JButton button = (JButton) e.getSource();//getSource返回事件源类型,也可以用getActionCommand返回String类型

    if(button.getText() != "")//如果为图形按钮
        str = button.getText();

    else{
        color = button.getBackground();
        System.out.println("color"+color);
    }
}

public void mouseClicked(MouseEvent e){
    System.out.println("点击");//按下和释放要在同一位置才是点击
    x2 = e.getX();

            y2 = e.getY();
   

    //画空心矩形
    if(str.equals("Rect")){
    Shape s = new Shape(x2,y2,80,40,color,
new BasicStroke(1),"Rect");
    s.draw(g2);
    }
    //画填充矩形
    if(str.equals("fillRect")){
    Shape s = new Shape(x2,y2,80,40,color,
new BasicStroke(1),"fillRect");
    s.draw(g2);
    }
    //画圆角矩形
    if(str.equals("RoundRect")){
    Shape s = new Shape(x2,y2,80,40,color,
new BasicStroke(1),"fillRect");
    s.draw(g2);
    }
    //画空心圆
    if(str.equals("Oval")){
    Shape s = new Shape(x2,y2,80,40,color,
new BasicStroke(1),"Oval");
    s.draw(g2);
    }
    //画填充圆
    if(str.equals("fillOval")){
    Shape s = new Shape(x2,y2,80,40,color,
new BasicStroke(1),"fillOval");
    s.draw(g2);
    }
    //画填充弧
    if(str.equals("fillArc")){
    Shape s = new Shape(x2,y2,80,80,color,
new BasicStroke(1),"fillArc");
    s.draw(g2);
    }
    //画图片
    if(str.equals("Image")){
    //先用ImageIcon设置路径,再获取图片(绝对路径)
    ImageIcon icon = new ImageIcon("C:\Users\lenovo\Desktop\background1.jpg");
    Image img = icon.getImage();
    Shape s = new Shape(x2,y2,200,150,
img,"Image");
    s.draw(g2);
    }
    //画文本
    if(str.equals("Text")){
    String text = "Hello World";
    Font font = new Font("华文行楷", Font.BOLD + Font.ITALIC, 26);//字体,粗体,斜体,大小
    g2.setFont(font);
    Shape s = new Shape(x2,y2,text,"Text");
    s.draw(g2);
    }
    //画任意多边形
    if(str.equals("Polygon")){
    if(flag == 2){
    Shape s = new Shape(ex,ey,x2,y2,color,
    new BasicStroke(1),"Line");
    s.draw(g2);
    ex = x2;
    ey = y2;
    }
    //如果与起点较近或鼠标双击,则闭合多边形
    if((Math.abs(sx-x2)<10 && Math.abs(sy-y2)<10)
    ||(e.getClickCount()==2)){
    Shape s = new Shape(sx,sy,x2,y2,color,
    new BasicStroke(1),"Line");
    s.draw(g2);
    flag = 1;
    }
    }
   }

    public void mousePressed(MouseEvent e){
    x1 = e.getX();
    y1 = e.getY();
    g2.setColor(color);
    if(flag == 1){
    sx = x1;
    sy = y1;
    }
    }

    public void mouseReleased(MouseEvent e){
    x2 = e.getX();
    y2 = e.getY();
   

    //画直线
    if(str.equals("Line")){
    Shape s = new Shape(x1,y1,x2,y2,color,
    new BasicStroke(1),"Line");
    s.draw(g2);
    }
    //画任意多边形
    if(str.equals("Polygon")){
    if(flag == 1){
    Shape s = new Shape(x1,y1,x2,y2,color,
    new BasicStroke(1),"Line");
    s.draw(g2);
    ex = x2;
    ey = y2;
    flag = 2;
    }
    }
    //画等腰三角形
    if(str.equals("Triangle")){
    Shape s = new Shape(x1,y1,x2,y2,color,
new BasicStroke(1),"Triangle");
    s.draw(g2);
    }
    }

    public void mouseDragged(MouseEvent e){
    x3 = e.getX();
    y3 = e.getY();
   

    //画曲线
    if(str.equals("Pencil")){
    Shape s = new Shape(x1, y1, x3, y3, color,
    new BasicStroke(10),"Pencil");
    s.draw(g2);
   
    x1 = x3;
    y1 = y3;
    }
    }
}

三、实现画图形的Shape类

需要定义多个构造方法,传递不同图形需要的参数值,再进行绘制

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Stroke;

public class Shape {
public int x1,x2,y1,y2;
public Stroke stroke;
public Color color;
public String type;
public Image img;
public String text;

public Shape(int x1,int y1,int x2,int y2,Color color,
        Stroke stroke,String type){
    this.x1=x1;
    this.y1=y1;
    this.x2=x2;
    this.y2=y2;
    this.color=color;
    this.stroke=stroke;
    this.type=type;
}

public Shape(int x1,int y1,int x2,int y2,
        Image img,String type){
    this.x1=x1;
    this.y1=y1;
    this.x2=x2;
    this.y2=y2;
    this.img=img;
    this.type=type;
}

public Shape(int x1,int y1,
        String text,String type){
    this.x1=x1;
    this.y1=y1;
    this.text=text;
    this.type=type;
}

public void draw(Graphics2D g){

    if(type.equals("Line") || type.equals("Pencil")){
        g.setColor(color);
        g.setStroke(stroke);
        g.drawLine(x1, y1, x2, y2);
    }
    else if(type.equals("Image")){
        g.drawImage(img,x1,y1,x2,y2,null);
    }
    else if(type.equals("Rect")){
        g.setColor(color);
        g.setStroke(stroke);
        g.drawRect(x1, y1, x2, y2);
    }
    else if(type.equals("Oval")){
        g.setColor(color);
        g.setStroke(stroke);
        g.drawOval(x1, y1, x2, y2);
    }
    else if(type.equals("fillRect")){
        g.setColor(color);
        g.setStroke(stroke);
        g.fillRect(x1, y1, x2, y2);
    }
    else if(type.equals("RoundRect")){
        g.setColor(color);
        g.setStroke(stroke);
        g.drawRoundRect(x1, y1, x2, y2, 10, 10);
    }
    else if(type.equals("fillOval")){
        g.setColor(color);
        g.setStroke(stroke);
        g.fillOval(x1, y1, x2, y2);
    }
    else if(type.equals("fillArc")){
        g.setColor(color);
        g.setStroke(stroke);
        g.fillArc(x1, y1, x2, y2,0,-90);
    }
    else if(type.equals("Text")){
        g.drawString(text, x1, y1);
    }
    else if(type.equals("Triangle")){
        g.setColor(color);
        g.setStroke(stroke);
        g.drawLine(x1,y1,x2,y2);
      g.drawLine(2*x1-x2, y2, x2, y2);
      g.drawLine(x1,y1,2*x1-x2, y2);
    }
}

}

四、画图板的重绘

在实现以上类后,已经可以实现点击对应按钮,画出对应的图形和颜色,但是一旦窗体改变,画的图形就会消失。这是因为图形没有被储存,一旦窗体改变后就生成了一个新窗体,旧的图形不会在新窗体上显示,因此需要保存图形数据,并在新窗体上重绘。

//draw类

        lis.setArray(shapeArray);//增加对图形数组的监听

public Shape[] shapeArray = new Shape[1000];//储存图形的数组
public void paint(Graphics g){
    super.paint(g);//super为父类
    System.out.println("绘制了");
    Graphics2D g2 = (Graphics2D) g;
    for(int i=0 ; i<shapeArray.length ; i++){
        Shape s = shapeArray[i];
        if(s != null)
            s.draw(g2);
    }

}

//drawListener类,增加图形数组,并收集数据

        private Shape[] array;

private int index=0;

        public void setArray(Shape[] array){
this.array = array;
}

        //以画空心矩形为例
    if(str.equals("Rect")){
    Shape s = new Shape(x2,y2,80,40,color,
new BasicStroke(1),"Rect");
    s.draw(g2);
    if(index<1000)
    array[index++] = s;
    }