<一> 画图板的简介
画图板是一种很实用的画图工具。它的界面如下:
-------------------------------------------- 1 --------------------------------------------------------------------------------------------------------
<二> java语言实现它
画图板大致可以分为三个部分:左侧工具面板、中间面板和底部颜色面板。
在构架画图板时,就必须得构建一个窗体,3个面板。考虑到程序的可维护
性和职责分离,以及提高效率,在实现画图板时将其抽象为5个类。
在构建窗体和面板时,直接通过继承相应的类,如JFrame、JPanel。在
具体的类中,可以用 this.属性或方法 来替代直接new一个对象.属性或方法。
接下来,具体讲每个类的实现。
第一部分 DrawBoard.java 类
package cn.huaxin.ui2.layer;
import java.awt.BorderLayout;
import java.awt.Graphics2D;
import javax.swing.JFrame;
public class DrawBoard {
JFrame jfDrawFrame = null;// 全局变量
// ------------------------------------------------------------------------------
// 构造方法
public DrawBoard() {
/** 第一步:设置窗体属性:大小、位置、标题、可见(必须要最后(add后)设置)、释放 **/
setFrameParams();// 调用了自己的方法
/** 第二步: add 控件 **/
// 左边面板
PanelLeft panelLeft = new PanelLeft(null);
jfDrawFrame.add(panelLeft, BorderLayout.WEST);
// 中间面板
PanelCenter panelCenter = new PanelCenter(panelLeft, null);
jfDrawFrame.add(panelCenter, BorderLayout.CENTER);
// 设置底部的面板
PanelBottom panelBottom = new PanelBottom(panelLeft, null);
jfDrawFrame.add(panelBottom, BorderLayout.SOUTH);
/** 第三步: 事件 **/
jfDrawFrame.setAlwaysOnTop(true);
jfDrawFrame.setVisible(true);
// 必须在获得画笔:
Graphics2D graphics2 = (Graphics2D) panelCenter.getGraphics();// 获得画笔
// TODO 要给左边面板的g赋值
panelLeft.graphics = graphics2;
panelCenter.graphics = graphics2;
panelBottom.graphics = graphics2;
}
/** 第一步:设置窗体属性:大小、位置、标题、可见(必须要最后(add后)设置)、释放 **/
public void setFrameParams() {
jfDrawFrame = new JFrame();
jfDrawFrame.setSize(500, 500);
jfDrawFrame.setLocationRelativeTo(null);
jfDrawFrame.setTitle("画图板");
jfDrawFrame.setDefaultCloseOperation(3);
jfDrawFrame.setLayout(new BorderLayout());// 布局
// null 空布局直接:给x,y坐标(屏幕适配有问题,做桌面程序没什么影响)
}
}
在DrawBoard类中,分为属性和方法。构造函数中,主要是建立窗体和面板,以及获得画笔。大致分为三步:
(1)为窗体设置属性
(2)为窗体添加面板
(3)事件
在构建窗体时,一定要注意一个“先”和一个“后”。标准就是窗体的可见性。
先: 设置窗体其他属性要先于可见性(this.setVisible());
(this.setVisible());
后: 获得画笔和为面板添加画笔要后于可见性(this.setVisible());
画笔
Graphics2D继承自抽象类
Graphics。它的用法在下面面板的应用中讲解
package cn.huaxin.DrawBoard;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
public class PanelLeft extends JPanel {
public int pressedCount;// 按下的次数 int pressedCount=0
public String currentComman = "line"; // 默认一开始就是直线
public Color currentColor = Color.black;
public Graphics2D graphics = null;
public PanelLeft(Graphics2D g) {
graphics = g;
// 左边
Dimension dSizie = new Dimension(70, 100); // 尺寸
this.setPreferredSize(dSizie);// 设置大小
this.setBackground(Color.black);// 设置背景颜色
// 添加jbutton 添加图片
String[] images = { "airbrush", "brush", "color_picker", "curve",
"dot_rect", "eraser", "fill", "line", "magnifier", "oval",
"pencil", "polygon", "rect", "round_rect", "star", "word" };
// 1.先要有监听器 :一个类implements ActionListener ;;
// 接口不能new,有一个普通类,没有类名-》匿名类 =>匿名内部类
ActionListener actionListener = new ActionListener() {
// 重写了接口的抽象方法
// 事件触发
public void actionPerformed(ActionEvent e) {
System.out.println("监听到了~~~");
pressedCount = 0;
// 区分是哪个按钮?
currentComman = e.getActionCommand();// 获得当前触发按钮的命令
if ("eraser".equals(currentComman)) {
// 设置橡皮的颜色:白色
graphics.setColor(Color.WHITE);
// 接口 s = 子类; 子类 s = 接口;
Stroke s = new BasicStroke(10);
// BasicStroke ss = (BasicStroke) s; // 接口 赋值给 子类
graphics.setStroke(s);
} else if ("brush".equals(currentComman)) {
// 设置刷子的颜色
graphics.setColor(currentColor);
// 接口 s = 子类; 子类 s = 接口;
Stroke s = new BasicStroke(10);
// BasicStroke ss = (BasicStroke) s; // 接口 赋值给 子类
graphics.setStroke(s);
} else if ("line".equals(currentComman)) {
// 设置直线的颜色
graphics.setColor(currentColor);// ???不能写死
// 接口 s = 子类; 子类 s = 接口;
Stroke s = new BasicStroke(1);
graphics.setStroke(s);
} else {
// 设置白色
graphics.setColor(currentColor);// ???不能写死
// 接口 s = 子类; 子类 s = 接口;
Stroke s = new BasicStroke(1);
graphics.setStroke(s);
}
}
};
for (int i = 0; i < images.length; i++) {
ImageIcon imageIcon = new ImageIcon("images/" + images[i] + ".jpg");
JButton btnIcon = new JButton(imageIcon);
Dimension preferredSize = new Dimension(25, 25);
btnIcon.setPreferredSize(preferredSize);
this.add(btnIcon);
// 2.给按钮添加监听
btnIcon.addActionListener(actionListener);//
// 3.给触发按钮设置一个命令
btnIcon.setActionCommand(images[i]);//
}
}
}
Dimension dSizie = new Dimension(70, 100);
this.setPreferredSize(dSizie);
实现左侧面板的大致思想是:
(1)建立左侧面板是,设置属性
(2)为面板添加按钮
(3)位每个按钮添加事件(得先建一个监听器才能添加监听器)
添加事件需要设置监听器和命令。由于ActionListener是接口,不能继承,在此用了一个懒办法:匿名内部类。它要求实现ActionListener里的抽象方法。BasicStroke()为Graphics2D里的设置画笔宽度的方法。
package cn.huaxin.DrawBoard;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JPanel;
public class PanelCenter extends JPanel {
public PanelLeft panelLeft;
public Graphics2D graphics;
int polygonMiddleX;
int polygonMiddleY;
// 坐标
int xStart = 0;
int yStart = 0;
int xEnd = 0;
int yEnd = 0;
// 多边形
int polygonStartX; // 起点 收尾相连的时候用
int polygonStartY;
Random random = new Random();// 随机数生成器
public PanelCenter(PanelLeft pl, Graphics2D g) {
this.panelLeft = pl;
graphics = g;
// 1.1有个一个监听器;匿名内部类
MouseListener mouseListener = new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
int clickCount = e.getClickCount();
System.out.println("点击了" + clickCount);
if ("polygon".equals(panelLeft.currentComman)) {
if (clickCount == 1) {
// 画直线
graphics.drawLine(polygonMiddleX, polygonMiddleY,
e.getX(), e.getY());
// 交换中间点
polygonMiddleX = e.getX();
polygonMiddleY = e.getY();
} else if (clickCount == 2) {
// 收尾相连
graphics.drawLine(polygonStartX, polygonStartY,
polygonMiddleX, polygonMiddleY);
// 还原点击次数
panelLeft.pressedCount = 0;
}
}
}
@Override
public void mousePressed(MouseEvent e) {
System.out.println("按下了");
// 起始点
xStart = e.getX();
yStart = e.getY();
if ("polygon".equals(panelLeft.currentComman)) {// 多边形
// 第一次
if (panelLeft.pressedCount == 0) {
polygonStartX = xStart;
polygonStartY = yStart;
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
System.out.println("释放了");
xEnd = e.getX();
yEnd = e.getY();
// 画
if ("line".equals(panelLeft.currentComman)) // 区分 直线 还是椭圆???
// 通过命令区分
{
// 当前是画直线
graphics.drawLine(xStart, yStart, xEnd, yEnd);
} else if ("oval".equals(panelLeft.currentComman)) {
// 反着画 : xStart>xEnd width<0
// TODO x较小的 y较小的 :绝对值:xEnd - xStart
graphics.drawOval(xStart, yStart, xEnd - xStart, yEnd
- yStart);
} else if ("rect".equals(panelLeft.currentComman)) {
// 反着画 : xStart>xEnd width<0
// TODO x较小的 y较小的 :绝对值:xEnd - xStart
graphics.drawRect(xStart, yStart, xEnd - xStart, yEnd
- yStart);
} else if ("round_rect".equals(panelLeft.currentComman)) {
graphics.drawRoundRect(xStart, yStart, xEnd - xStart, yEnd
- yStart, 100, 100);
} else if ("polygon".equals(panelLeft.currentComman)) {// 多边形
// 画第一条线
if (panelLeft.pressedCount == 0) {
graphics.drawLine(xStart, yStart, xEnd, yEnd);
polygonMiddleX = xEnd;
polygonMiddleY = yEnd;
panelLeft.pressedCount++;
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("进入了");
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("退出了");
}
};
// 1.2鼠标拖动的事件监听器
MouseMotionListener mouseMotionListener = new MouseMotionListener() {
//
public void mouseDragged(MouseEvent e) {
// System.out.println("鼠标拖动~~");
int x1 = e.getX();
int y1 = e.getY();
if ("pencil".equals(panelLeft.currentComman)) {
// graphics.drawLine(x1, y1, x1, y1);// 不能画圆点
graphics.drawLine(xStart, yStart, x1, y1);
xStart = x1;
yStart = y1;
} else if ("eraser".equals(panelLeft.currentComman)) {
// System.out.println("~~~~");
graphics.drawLine(xStart, yStart, x1, y1);
xStart = x1;
yStart = y1;
} else if ("brush".equals(panelLeft.currentComman)) {
// System.out.println("~~~~");
graphics.drawLine(xStart, yStart, x1, y1);
xStart = x1;
yStart = y1;
} else if ("airbrush".equals(panelLeft.currentComman))// 喷枪
{
for (int i = 0; i < 30; i++) {
// 生成的随机数
int nextInt = random.nextInt(8) - 4;// [0,9]->[-5,4]
int nextInt2 = random.nextInt(8) - 4;// [0,9]->[-5,4]
System.out.println(nextInt);
graphics.drawLine(x1 + nextInt, y1 + nextInt2, x1
+ nextInt, y1 + nextInt2);// 画点
}
}
}
public void mouseMoved(MouseEvent e) {
// System.out.println("鼠标移动");
}
};
this.setBackground(Color.WHITE);
// 2.给panel添加监听器
this.addMouseListener(mouseListener);
this.addMouseMotionListener(mouseMotionListener);
}
}
中间面板,主要就是通过鼠标在面板上操作。所以,这里涉及到鼠标事件。
鼠标事件有:进入,按下,点击,释放,退出,拖动,移动。
监听器分为两种:MouseListener 和 MouseMotionListener
具体的每个按钮对应的事件如图所示。
第四部分 PanelBotton.java 类
package cn.huaxin.DrawBoard;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class PanelBottom extends JPanel {
// 1 默认颜色的数组
Color[] colors = { Color.red, Color.black, Color.blue, Color.yellow };
PanelLeft panelLeft;
public Graphics2D graphics;
public PanelBottom(PanelLeft p, Graphics2D g) {
panelLeft = p;
graphics = g;
Dimension d = new Dimension(100, 70);
this.setPreferredSize(d);
/** 创建按钮的点击事件 **/
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("颜色选择了~~");
String actionCommand = e.getActionCommand();
int i = Integer.valueOf(actionCommand);// String -> int
// :Integer整数
System.out.println(i);
Color color = colors[i];
graphics.setColor(color);// 改了颜色
panelLeft.currentColor = color;
if ("eraser".equals(panelLeft.currentComman))// 橡皮檫的时候颜色还原
{
graphics.setColor(Color.WHITE);
}
}
};
/** 面板上面添加默认颜色的Button **/
// 1 默认颜色的数组
for (int i = 0; i < colors.length; i++) {
// 2创建Button
JButton button = new JButton();
button.setBackground(colors[i]);
Dimension dd = new Dimension(25, 25);
button.setPreferredSize(dd);
button.addActionListener(listener);
button.setActionCommand(i + "");
// 3.添加
this.add(button);
}
}
}