Java小项目——画板
一、项目设计
1、界面设计JFrame
上面为控制栏JPanel
下面为绘制面板JPanel
2、基本思路
鼠标事件监听器:展示一个JPanel界面,添加鼠标事件监听器,记录鼠标点击事件的坐标;
getGraphics()方法:可以得到java.awt.Graphics对象gr,gr作为“画笔”,调用draw方法并传入坐标,可以绘制相应图像。
3、具体功能
3.1、绘制方式:
画直线:
g.drawLine(x1,y1,x2,y2);
画矩形:
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
画多边形:
若为第一次单击,保存该坐标;非第一次单击,绘制两个单击之间的直线;双击后,绘制第一次单击和本次双击坐标之间的直线,再清空所有坐标。
拖动绘制:
拖动鼠标中,不断绘制两个时间段之间两点之间的直线。
3.2、颜色选取
可以选取对应颜色进行绘制
3.3、重绘
改变窗体大小时,会调用paint()函数,重绘。
需要在这个函数中,写重绘已经绘制的图形的代码,用于保存代码。
二、初步实现:界面实现+绘制直线
1、主函数部分:SampleDraw类
package Draw;
import javax.swing.*;
import java.awt.*;
public class SampleDraw {
public static void main(String args[]){
SampleDraw draw = new SampleDraw();
draw.showUI();
}
public void showUI(){
//主界面JFrame jf
JFrame jf = new JFrame();
jf.setTitle("画图1.0");
jf.setSize(800,800);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
//控制台JPanel jp1+绘制界面JPanel jp2
JPanel jp1 = new JPanel();
JPanel jp2 = new JPanel();
jp1.setBackground(java.awt.Color.white);
jf.add(jp1,BorderLayout.NORTH);
jf.add(jp2,BorderLayout.CENTER);
//按钮:前四个为绘制功能;后两个为颜色选择
JButton jb1 = new JButton("线条");
JButton jb2 = new JButton("矩形");
JButton jb3 = new JButton("多边形");
JButton jb4 = new JButton("绘制");
JButton jbc1 = new JButton("蓝色");
JButton jbc2 = new JButton("绿色");
jbc1.setForeground(Color.blue);
jbc2.setForeground(Color.green);
//jbc2.setBackground(Color.BLACK);
jp1.add(jb1);
jp1.add(jb2);
jp1.add(jb3);
jp1.add(jb4);
jp1.add(jbc1);
jp1.add(jbc2);
//可见放在add之后,获取之前
jf.setVisible(true);
//创建画笔对象gr,添加至jpanel2
Graphics gr = jp2.getGraphics();
//鼠标监听器对象mouse
//构造函数初始化:使得鼠标中的位置,获取画布类:鼠标在画布上画线、多边形
addMouseListener mouse = new addMouseListener(gr);
//在各个事件源(组件)上添加鼠标监听器
jp2.addMouseListener(mouse);
jp2.addMouseMotionListener(mouse);
jb1.addActionListener(mouse);
jb2.addActionListener(mouse);
jb3.addActionListener(mouse);
jb4.addActionListener(mouse);
jbc1.addActionListener(mouse);
jbc2.addActionListener(mouse);
}
}
2、事件监听器部分:addMouseListener类,继承了多个动作监听器接口
2.1 首先在actionPerformed获取目前状态:画什么,用什么颜色
2.2 在按下去 mousePressed 、释放 mouseReleased 中分别获取当时坐标,用绘制函数绘制直线和矩形
if(name.equals("线条")||name.equals("")){
g.drawLine(x1,y1,x2,y2);
}
if(name.equals("矩形")){
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
}
2.3 在点击mouseClicked中,用函数绘制多边形
第一次按压记录x0;第二次之后,绘制上一次点击位置和本次点击位置的直线;双击之后,绘制上一次点击位置和本次点击位置+x0与本次双击点的两条直线
g.drawLine(x01,y01,x02,y02); //第二次以后
g.drawLine(x0,y0,x01,y01); //双击后
2.4 在拖拽mouseDragged中,绘制两次时间段之间的直线,时间段片小,则显示出来像曲线
g.drawLine(x,y,xt,yt);
package Draw;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
//MouseListener:绘制直线、矩形、多边形
//ActionListener:动作监听,获取button的text,来判断目前处于何种工作状态
//MouseMotionListener:拖动画线
public class addMouseListener implements MouseListener ,ActionListener , MouseMotionListener{
//变量如下,分别对应直线、矩形x1,x2;多边形x01,x02,x0;
private int x1=0,y1=0,x2=0,y2=0;
private int x=0,y=0,xt=0,yt=0;
private int x01,y01,x02,y02,x0,y0;
private Graphics g ;
private String name = "线条";
private Color jbcolor = Color.BLACK;
//构造方法,将画笔传入监听器,在监听器中动作执行时,绘制相应图形
public addMouseListener(Graphics gr){
this.g = gr;
}
@Override
public void mouseClicked(MouseEvent e) {
//3-多边形绘制,最后双击,在第一个点和最后一个点的位置之间画线
if(e.getClickCount()==2){
System.out.println("双击!!");
g.drawLine(x0,y0,x01,y01);
x0=0;y0=0;x01=0;y01=0;x02=0;y02=0;
}
System.out.println("点击");
if(name.equals("多边形")) {
//当第一次按压,x01=0时候,则将第一次按压坐标存入x0,y0
if(x01==0){
x0 = e.getX();
y0 = e.getY();
}
x01 = e.getX();
y01 = e.getY();
//第二次按压以后画线
if (x02!=0){
g.drawLine(x01,y01,x02,y02);
}
//将本次x01按压存入x02,用于下一次绘制直线
x02 = x01;
y02 = y01;
}
}
@Override
public void mousePressed(MouseEvent e) {
//1线条-2矩形-按压时为绘制起点x1,y1
System.out.println("按压");
x1 = e.getX();
y1 = e.getY();
}
@Override
public void mouseReleased(MouseEvent e) {
//1线条-2矩形-释放时为绘制终点x2,y2
System.out.println("释放");
x=0;y=0;xt=0;yt=0;
x2 = e.getX();
y2 = e.getY();
//
if(name.equals("线条")||name.equals("")){
g.drawLine(x1,y1,x2,y2);
}
if(name.equals("矩形")){
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
}
}
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("进入");
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("离开");
}
@Override
public void mouseDragged(MouseEvent e) {
//拖动绘制
if(name.equals("绘制")){
x = e.getX();
y = e.getY();
if(xt!=0){
g.drawLine(x,y,xt,yt);
}
xt = x;
yt = y;
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("蓝色")){
//定义新的jb按钮对象,来接受e.getSource()的object对象,强制转型为JButton
JButton jb = (JButton)e.getSource();
jbcolor = jb.getForeground();
g.setColor(jbcolor);
}else if(e.getActionCommand().equals("绿色")){
JButton jb = (JButton)e.getSource();
jbcolor = jb.getForeground();
g.setColor(jbcolor);
}else{
name = e.getActionCommand();
}
System.out.println("button:"+name);
}
}
结果:如下
三、重绘 ❤️【本章节三个类组成最终代码】❤️
1、需要重绘,则需要数组存储下绘制过的线条
定义Shape类
属性:包括初始坐标、终止坐标、绘制形状、颜色
方法:重新画方法,调用该方法,将shape中的对象重新绘制出来
package com.java7.DrawRedraw0710;
import java.awt.*;
public class Shape {
private int x1,y1,x2,y2;
private String name;
private Color color;
public Shape(int x1,int y1,int x2,int y2,String name,Color color){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.name = name;
this.color = color;
}
//重绘中,调用Redraw,则绘制shape对象
public void Redraw(Graphics g){
System.out.println("Graphics name = "+name);
g.setColor(color);
switch (name){
case "线条":
g.drawLine(x1,y1,x2,y2);
break;
case "矩形":
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
break;
}
}
}
2、定义好shape类后,我们需要在在监听器类,绘制的时候,将坐标、颜色、绘制种类存入Shape,再将Shape存入ShapeArray[]数组。
//1.把线条坐标、名称存入Shape Shape shape = new Shape(x1,y1,x2,y2,name,jbcolor); shapeArray[index++] = shape;
//3.1.单击后,把多边形的初始坐标、名称存入Shape Shape shape = new Shape(x01,y01,x02,y02,"线条",jbcolor); shapeArray[index++] = shape; //3.2.双击后,把多边形的初次按下坐标+最后按压的坐标、名称存入Shape;清空所有坐标,用于下一次判断是否为第一次按压 Shape shape = new Shape(x0,y0,x01,y01,"线条",jbcolor); shapeArray[index++] = shape; x0=0;y0=0;x01=0;y01=0;x02=0;y02=0;
源码:addMouseListener类
package com.java7.DrawRedraw0710;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class addMouseListener implements MouseListener ,ActionListener , MouseMotionListener{
private int x1=0,y1=0,x2=0,y2=0;
private int x=0,y=0,xt=0,yt=0;
private int x01,y01,x02,y02,x0,y0;
private Graphics g ;
private String name = "线条";
private Color jbcolor=Color.BLACK;
//重绘:
private Shape shapeArray[];
private int index = 0;
//set函数,使用后,初始化画笔gr,shapeArray[]数组,用于将其传入addMouseListener
public void setGr(Graphics gr){
this.g = gr;
}
public void setSa(Shape shapeArray[]){
this.shapeArray = shapeArray;
}
@Override
public void mouseClicked(MouseEvent e) {
if(e.getClickCount()==2){
g.drawLine(x0,y0,x01,y01);
//3.2.双击后,把多边形的初次按下坐标+最后按压的坐标、名称存入Shape
Shape shape = new Shape(x0,y0,x01,y01,"线条",jbcolor);
shapeArray[index++] = shape;
x0=0;y0=0;x01=0;y01=0;x02=0;y02=0;
}
}
public void mousePressed(MouseEvent e) {
//System.out.println("按压");
x1 = e.getX();
y1 = e.getY();
}
public void mouseReleased(MouseEvent e) {
x=0;y=0;xt=0;yt=0;
x2 = e.getX();
y2 = e.getY();
System.out.println("name="+name);
if(name.equals("线条")||name.equals("")){
g.drawLine(x1,y1,x2,y2);
//1.把线条坐标、名称存入Shape
Shape shape = new Shape(x1,y1,x2,y2,name,jbcolor);
shapeArray[index++] = shape;
}
if(name.equals("矩形")){
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x2-x1),Math.abs(y2-y1));
//2.把矩形坐标、名称存入Shape
Shape shape = new Shape(x1,y1,x2,y2,name,jbcolor);
shapeArray[index++] = shape;
}
if(name.equals("多边形")) {
System.out.println("多边形");
if(x01==0){//第一次按下,记录地刺次按下的位置,用于双击后,多边形闭合
x0 = e.getX();
y0 = e.getY();
}
x01 = e.getX();
y01 = e.getY();
if (x02!=0){//第二次按压
g.drawLine(x01,y01,x02,y02);
//3.1.单击后,把多边形的初始坐标、名称存入Shape
Shape shape = new Shape(x01,y01,x02,y02,"线条",jbcolor);
shapeArray[index++] = shape;
}
x02 = x01;
y02 = y01;
}
}
public void mouseEntered(MouseEvent e) {
///System.out.println("进入");
}
public void mouseExited(MouseEvent e) {
//System.out.println("离开");
}
public void mouseDragged(MouseEvent e) {
if(name.equals("绘制")){
System.out.println("DRAGE —— 拖动绘制曲线:");
x = e.getX();
y = e.getY();
if(xt!=0){
g.drawLine(x,y,xt,yt);
//把坐标、名称存入Shape
Shape shape = new Shape(x,y,xt,yt,"线条",jbcolor);
shapeArray[index++] = shape;
}
xt = x;
yt = y;
}
}
public void mouseMoved(MouseEvent e) {
}
public void actionPerformed(ActionEvent e) {
//首先获取jb对象(JButton)e.getSource();再对象的颜色jb.getBackground()
if("".equals(e.getActionCommand())){
JButton jb = (JButton)e.getSource();
jbcolor = jb.getBackground();
g.setColor(jbcolor);
}
//获取动作:直线、矩形、多边形、拖动绘制线条
else{
name = e.getActionCommand();
System.out.println("button:"+name);
}
}
}
3、 主函数,继承JPanel,在重写panit()函数时,写入:绘制shapeArray[]数组中所有的Shape对象。
@Override public void paint(Graphics g) { //调用重绘 super.paint(g); for(int i=0;i<shapeArray.length;i++){ if(shapeArray[i]!=null){ shapeArray[i].Redraw(g); } else break; } System.out.println("重绘"); }
源码:SampleDraw
package com.java7.DrawRedraw0710;
import javax.swing.*;
import java.awt.*;
public class SampleDraw extends JPanel{
public static void main(String args[]){
SampleDraw draw = new SampleDraw();
draw.showUI();
}
private Shape shapeArray[]=new Shape[1000];
@Override
public void paint(Graphics g) {
//调用重绘
super.paint(g);
for(int i=0;i<shapeArray.length;i++){
if(shapeArray[i]!=null){
shapeArray[i].Redraw(g);
}
else
break;
}
System.out.println("重绘");
}
public void showUI(){
//界面
JFrame jf = new JFrame();
jf.setTitle("画图1.0");
jf.setSize(800,800);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
//JPanel
JPanel jp1 = new JPanel();
jp1.setBackground(Color.white);
jf.add(jp1,BorderLayout.NORTH);
jf.add(this,BorderLayout.CENTER);
//按钮
JButton jb1 = new JButton("线条");
JButton jb2 = new JButton("矩形");
JButton jb3 = new JButton("多边形");
JButton jb4 = new JButton("绘制");
jp1.add(jb1);
jp1.add(jb2);
jp1.add(jb3);
jp1.add(jb4);
//鼠标监听器,初始化设置shapeArray
addMouseListener mouse = new addMouseListener();
//颜色数组,循环添加颜色按钮
Color colorArray[] = {Color.GREEN,Color.BLUE,Color.CYAN};
for(int i=0;i<colorArray.length;i++){
JButton jb = new JButton();
jb.setBackground(colorArray[i]);
jb.setForeground(colorArray[i]);
jp1.add(jb);
jb.addActionListener(mouse);
}
//可见放在add之后,获取之前
jf.setVisible(true);
//画布,添加至jpanel2
Graphics gr = this.getGraphics();
System.out.println("graphics = " + gr);
//添加鼠标监听器
this.addMouseListener(mouse);
this.addMouseMotionListener(mouse);
jb1.addActionListener(mouse);
jb2.addActionListener(mouse);
jb3.addActionListener(mouse);
jb4.addActionListener(mouse);
mouse.setGr(gr);//使得鼠标中的位置,获取画布类:鼠标在画布上画线、多边形
mouse.setSa(shapeArray);//获得shapeArray,用于paint中重绘
}
}
结果: