1、搭建基本窗口框架
此部分是关于和用户交互之间的窗口,及一些参数的配置
public class DrawTest02 extends JFrame{
public void DrawTest02(){
JFrame jframe = new JFrame("画板");//创建JFrame对象 并对画板窗口进行命名
JFrame jFrame = this;
jframe.setSize(1000,800);//设定窗口大小
jframe.setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭窗口会结束当前运行状态
jframe.setLocationRelativeTo(null);//设定画板页面中间
jframe.setLayout(new FlowLayout());//创建流布局,自动根据窗口大小排列
jframe.setVisible(true);//设定数据可视化开关
jframe.addMouseListener(drawListenerA);//添加监听的对象
}
创建工具类(颜色,坐标点等...)
class UtilityColor
{
Color color;
int x,x1,y,y1;
String TypeName;
public UtilityColor(Color color, int x, int x1, int y, int y1, String typeName) {
this.color = color;
this.x = x;
this.x1 = x1;
this.y = y;
this.y1 = y1;
TypeName = typeName;
}
public void drawShape(Graphics graphics)
{
graphics.setColor(color);
}
}
2、封装图形实现过程
此处是对于图像绘制的过程进行封装,方便重复调用
class Line extends UtilityColor{
//继承UtilityColor中的属性,并重写其中的实例方法
//这是因为子类之间的实现功能需求不同
public Line(Color color, int x, int x1, int y, int y1, String typeName) {
super(color, x, x1, y, y1, typeName);
}
public void drawShape(Graphics graphics){
super.drawShape(graphics);
graphics.drawLine(x,y,x1,y1);
}
}
class Rect extends UtilityColor{
//继承UtilityColor中的属性,并重写其中的实例方法
//这是因为子类之间的实现功能需求不同
//由于此处我们有两个选项一个是实心矩形,一个不是
//此处采用对于drawShpe方法重写中进行判断
//注意:判断的内容要是什么,由于过程当中若是判断的是非实心矩形,
//会造成实际画板上的内容,画一个非实心矩形,在使用实心矩形画不出来的情况
//实心圆同理
public Rect(Color color, int x, int x1, int y, int y1, String typeName) {
super(color, x, x1, y, y1, typeName);
}
public void drawShape(Graphics graphics){
super.drawShape(graphics);
if(TypeName.equals("实心矩形")){
graphics.fillRect(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
}else {
graphics.drawRect(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
}
}
}
class Oval extends UtilityColor{
//继承UtilityColor中的属性,并重写其中的实例方法
//这是因为子类之间的实现功能需求不同
public Oval(Color color, int x, int x1, int y, int y1, String typeName) {
super(color, x, x1, y, y1, typeName);
}
@Override
public void drawShape(Graphics graphics) {
super.drawShape(graphics);
if(TypeName.equals("实心圆")){
graphics.fillOval(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
}else {
graphics.drawOval(Math.min(x,y),Math.min(x1,y1),Math.abs(x - x1),Math.abs(y - y1));
}
}
}
class ABC extends UtilityColor{//等腰三角
//继承UtilityColor中的属性,并重写其中的实例方法
//这是因为子类之间的实现功能需求不同
public ABC(Color color, int x, int x1, int y, int y1, String typeName) {
super(color, x, x1, y, y1, typeName);
}
@Override
public void drawShape(Graphics graphics) {
super.drawShape(graphics);
int ix = (x + x1) /2;//顶点
int ymin = Math.min(y,y1);
int xmax = Math.max(x,x1);
int xmin = Math.min(x,x1);
int ymax = Math.max(y,y1);
graphics.drawLine(ix,ymin,xmin,ymax);
graphics.drawLine(xmin,ymax,xmax,ymax);
graphics.drawLine(xmax,ymax,ix,ymin);
}
}
3、窗口按键上色板块、图像名字,运用ArrayList数组进行存储,并由监听器进行监听
此处是关于鼠标、用户操作的监听器,和部分基本属性部分
class DrawListenerB implements MouseListener, ActionListener {
/*
ActionListener 接收操作事件的侦听器
MouseListener 鼠标监听器
*/
int x,x1,y,y1;//设定两个点 矩形 圆都是两点决定的
int x2,y2,x3,y3,x4,y4;
String Shape = "";
Color color;
Graphics graphics = null;//调入Graphics图形上下文的抽象基类 也可以叫做绘图的画笔
ArrayList<UtilityColor> arrayList = new ArrayList<>();//存储数组
public void setGraphics(Graphics graphics) {
this.graphics = graphics;
}
int count = 0;//计数器
@Override
public void mouseClicked(MouseEvent e) {//鼠标点击时调用
x = e.getX(); //返回事件相对于源组件的水平 x 坐标。
y = e.getY(); // 返回事件相对于源组件的水平 y坐标。
//尝试一下子点击的时候
if(Shape.equals("三角形")){
if(count == 0){
x2 = x;
y2 = y;
count++;
} else if(count == 1)
{
x3 = x;
y3 = y;
graphics.drawLine(x2,y2,x3,x3);
count++;
} else if(count == 2){
x4 = x;
y4 = y;
graphics.drawLine(x3,y3,x4,y4);
graphics.drawLine(x4,y4,x2,y2);
count=0;
}
}
int button = e.getButton (); //返回更改了状态的鼠标按键
}
@Override
public void mousePressed(MouseEvent e) {//鼠标按下时调用
x = e.getX(); //返回事件相对于源组件的水平 x 坐标。
y = e.getY(); // 返回事件相对于源组件的水平 y坐标。
}
@Override
public void mouseReleased(MouseEvent e) {//鼠标释放的时候调用
x1 = e.getX(); //返回事件相对于源组件的水平 x 坐标。
y1 = e.getY(); // 返回事件相对于源组件的水平 y坐标。
switch (Shape){
case "直线":
Line line = new Line(color,x,y,x1,y1,Shape);
line.drawShape(graphics);
arrayList.add(line);//添加到数组当中
break;
case "矩形":
Rect rect = new Rect(color,x,y,x1,y1,Shape);
rect.drawShape(graphics);
arrayList.add(rect);
break;
case "圆" :
Oval oval = new Oval(color,x,y,x1,y1,Shape);
oval.drawShape(graphics);
arrayList.add(oval);
break;
case "实心矩形" :
Rect fillRect = new Rect(color,x,y,x1,y1,Shape);
fillRect.drawShape(graphics);
arrayList.add(fillRect);
break;
case "实心圆":
Oval fillOvel = new Oval(color,x,y,x1,y1,Shape);
fillOvel.drawShape(graphics);
arrayList.add(fillOvel);
break;
//上述四种情况都相同,两个点确定一个图像,所以可以使用过相同的参数
case "等腰三角形" :
ABC abc = new ABC(color,x,y,x1,y1,Shape);
abc.drawShape(graphics);
arrayList.add(abc);
break;
//思路:以矩形为参照物,矩形中点为顶点,之后两个点就是Math.min(x,x1) Math.max(y,y1)
//另一个点 Math.max(x,x1),Math.max(y,y1)
default:
break;
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
MyButton myButton = (MyButton) e.getSource(); //get最初发生 Event 的对象
int buttonId = myButton.getButtonId();//在接收事物监听器中判断接收的是颜色还是图像
if(buttonId == MyButton.TYPE_SHAPE)
{
Shape = myButton.getText();
System.out.println(Shape);
}
else if(buttonId == MyButton.TYPE_COLOR) {
System.out.println("颜色点击按钮");
color = myButton.getBackground();
graphics.setColor(color);
}
}
}
class MyButton extends JButton{
//设定识别是否为颜色/图形设定相关变量
private int ButtonId;
public void setButtonId(int buttonId) {
ButtonId = buttonId;
}
public static final int TYPE_SHAPE=1;//若为1就是图像
public static final int TYPE_COLOR=0;//为0就是颜色
public MyButton() {
super("");
}
public MyButton(String text) {
super(text);
}
上面这个是关于上面代码块的判断图像和颜色的部分
4、重写paint()方法
public void paint(Graphics graphics){
super.paint(graphics);//重写paint方法重绘,这里会把画的图像地址保存到数组当中
for (UtilityColor utilityColor : drawListenerA.arrayList) {
utilityColor.drawShape(graphics);
}
}
5、把这写方法写到添加到主函数的无参方法中(方便调用)
public class DrawTest02 extends JFrame{
DrawListenerB drawListenerA = new DrawListenerB();
public void DrawTest02(){
JFrame jframe = new JFrame("画板");
JFrame jFrame = this;
jframe.setSize(1000,800);
jframe.setDefaultCloseOperation(EXIT_ON_CLOSE);
jframe.setLocationRelativeTo(null);//设定画板页面中间
jframe.setLayout(new FlowLayout());//创建流布局,自动根据窗口大小排列
//设定按钮
String [] str = {"直线","矩形","圆","实心矩形","实心圆","等腰三角形","三角形","多边形"};
for (int i = 0; i < str.length; i++) {
MyButton myButton = new MyButton(str[i]);
myButton.setButtonId(MyButton.TYPE_SHAPE);
myButton.addActionListener(drawListenerA);//将监听器局部变量放到按钮中
jframe.add(myButton);//把String数组中的东西呈现在窗口上
}
Color [] color = new Color[]{//添加颜色板块
Color.BLACK,Color.BLUE,Color.GREEN,Color.LIGHT_GRAY,Color.ORANGE,Color.RED
, Color.CYAN,Color.MAGENTA
};
//添加按钮功能
for (int i = 0; i < color.length; i++) {
MyButton myButton = new MyButton();
myButton.setBackground(color[i]);
myButton.setButtonId(MyButton.TYPE_COLOR);//此行由于没写其构造方法,所以运行前写不到面板上
myButton.addActionListener(drawListenerA);
myButton.setPreferredSize(new Dimension(50,50));//设定颜色板块大小
jframe.add(myButton);
}
jframe.setVisible(true);//设定数据可视化开关
jframe.addMouseListener(drawListenerA);//添加监听的对象
drawListenerA.setGraphics(jframe.getGraphics());
// 为组件创建一个图形上下文。
}
6、最后调用主函数
public static void main(String[] args) {
new DrawTest02().DrawTest02();
}
图像展示