画图板小结

在蓝杰已经快学习2个月了,在这也学习了java的一些基础知识,如类与对象,继承,多态,接口,监听等,也有了做项目的初步体验。想想自己从一个对java
一无所知到现在能够有一些项目基础,心里还是挺高兴的。
在这段期间有太多的感触!因为之前都是用别人的画图板,而现在终于也有了自己的画图板。尽管自己的功能还不是很全面,还需要一些改善,但是也实现了一些
基本的功能。下面我就谈一下自己做画图板的一些经验与总结。
二、功能介绍
1、画图功能:这个画图板可以实现曲线、直线、矩形、椭圆、填充矩形等各种多边形的画法。
2、颜色选择功能:可以设置画布的背景颜色,也可以设置图形的颜色,颜色是自己从选择器中自行选取的。
3、重绘功能:最小化窗体后,能够使所绘图形重新展现出来;
4.截屏功能:能够截取一个矩形框屏幕;
5.喷漆功能:能够在一个范围类随机的画点;
6.文本框的构建功能:能在画板上随意的加一些文字;
7.菜单栏的功能:做一个菜单界面;
三.对应功能的代码实现及注意点
1.画图功能
直线:g.drawLine(x1,y1,x2,y2);
矩形:g.drawRect(x1, y1,Math.abs(x2-x1),Math.abs(y2-y1));
注意点:x1,y1应该表示矩形的左上角的顶点,通过下面简单的交换实现
                    int x3; 
if (x1 > x2) {
x3 = x1;
x1 = x2;
x2 = x3;
}
if (y1 > y2) {
x3 = y1;
y1 = y2;
y2 = x3;
}

椭圆:g.drawOval(x1, y1, x2, y2);(注意点同上)
圆角矩形: g.drawRoundRect(x1, y1, x2, y2,15,15);(注意点同上)
多边形:
1.代码实现
if (!(x1 == x2 && y1 == y2)) { 
shape =new Drawline(x1,y1,x2,y2,g.getColor(),1);
shape.draw((Graphics2D)g);
list.add(shape);(以上三行代码为画直线,并保存所画直线,一边实现重汇)
k = 1;
} else {
k = 0;
System.out.println("画多边形");
shape =new Drawline(duox,duoy,x2,y2,g.getColor(),1);
shape.draw((Graphics2D)g);
list.add(shape);(以上三行代码为画直线,并保存所画直线,一边实现重汇)
}
x1 = x2;
y1 = y2;}

2.思路:
开始的第一个点为(x1,y1),第二点为(x2,y2),然后由这两个点画多边形的第一条直线,令x1 = x2;y1 = y2;接着当按下下
一点时 ,又由这两点画多边形的一条直线,不断的重复下去;当在某一点双击时将这一点与起始点链接画直线。k是为了方面保存多边形
的第一个点;
2、颜色选择功能
1.颜色按钮的生成:
 for(int i=0;i<20;i++){ 
JButton jb1=new JButton();
jb1.setBackground(color1[i]);
jb1.setLayout(null);
jb1.setBounds(w,b,10,10);
jb1.setBorder(new BevelBorder(0, Color.DARK_GRAY,Color.WHITE));
jp_7.add(jb1);
colorse co= new colorse(jb1);
jb1.addActionListener(co);
colorSelect1 cs1=new colorSelect1(jb1);
jb1.addMouseListener(cs1);
}

注意点:在添加颜色按钮是要将它的布局设为空,然后采用绝对定位setBounds;
内凹及边框的效果实现 :BevelBorder(int bevelType, Color highlight, Color shadow)
创建具有指定类型、高亮显示和阴影颜色的斜面边框。
2.颜色按钮的监听:
class colorSelect1 implements MouseListener{ 
int i=0,j=0;
JButton jb;
public colorSelect1(JButton jb){
this.jb=jb;
i=0;
j=0;
}
public void mouseClicked(MouseEvent e) {
shubiao=e.getButton();
i++;
if(e.getButton()==1)
if(i>1) {
color = javax.swing.JColorChooser.showDialog(null, "颜色选择", jb.getBackground());
Bjtn.setBackground(color);
i=0;
}
j++;
if(e.getButton()==3){
if(j==1){
Fjtn.setBackground(jb.getBackground());
}
if(j>1) {
color = javax.swing.JColorChooser.showDialog(null, "颜色选择", jb.getBackground());
Fjtn.setBackground(color);
j=0;
}
}
}

注意点: e.getButton();表示 : 为1表示右键 为2表示鼠标的滚抽 为3表示左键
3.重绘功能:
思路: a.通过截全屏并用图片保存下来,然后通过构造方法传图片,最后再画图片
b.通过截全屏并用数组保存下来,然后通过构造方法传数组,最后遍历数组画每个像素点
c.队列保存画的每一个图形,然后通过构造方法传队列,最后出队列画每一个图形
代码:

try { 
// 创建一个robot对象
Robot robot = new Robot();
// 获取白色画布(通过事件源)
JPanel jp = (JPanel) e.getSource();
// 获取白色画布的起始点
Point point = jp.getLocationOnScreen();// 查一下与getLocation()的区别
// 获取画布的宽高
Dimension dimen = jp.getPreferredSize();
// 创建一个矩形对象
Rectangle rect = new Rectangle(point, dimen);
// 调用截屏的对象
image = robot.createScreenCapture(rect);
// //将图片保存到二维数组中
// color =new int[image.getHeight()][image.getWidth()];
// for(int i=0;i<image.getHeight();i++){
// for(int j=0;j<image.getWidth();j++){
// color[i][j]=image.getRGB(j, i);
// }
// }

} catch (AWTException e1) {
e1.printStackTrace();
}
}

注意点:以上是通过robot来截屏并用图片保存,或用数组保存,由于队列的实现重汇比较复杂所以就没贴出代码
class MyPanel extends JPanel{ 
class MyPanel extends JPanel{
public void paint(Graphics g){
super.paint(g);
注意点:以下4行使用队列实现重汇
// Graphics2D g1= (Graphics2D) g;
// System.out.println("重绘");
// for(int i=1;i<=list.getSize();i++){
// list.find(i).draw(g1);
// }
注意点:以下2行使用图片实现重汇
if(dl.image!=null)
g.drawImage(dl.image, 0,0 , null);
注意点:以下几行使用数组实现重汇
// int[][] getcolor=dl.color;
// if(getcolor!=null)
// for(int i=0;i<getcolor.length;i++){
// for(int j=0;j<getcolor[i].length;j++){
// Color color=new Color(getcolor[i][j]);
// g.setColor(color);
// g.drawLine(j,i,j,i);
// }
// }

}
}
}

4.截屏功能:
思路:通过robot截屏,然后通过鼠标拖动的方法画图片,当点击图片以外的地方就停止画图;这是我刚开始的想法,
可是当实现的时候却发现了很多问题(如没有将所截的图片的起始位置涂白,没有消除图片在拖动的过程中的痕迹),然后
经过一个漫长的思考,首先用2个点标记图片的所在位置,当第一次拖动的时候将图片涂白,后面用原来图片填充,而这样
就需要我们出始的全屏图像在鼠标拖动的时候不断的画,且必须使它在画截屏图像的之前画;
代码:略(可以参考我的画图板的所有代码)
5.喷漆功能:
思路:首先截取一个全屏对象用数组保存,并用-1标记数组中每一个与所选点颜色相同的点,其余用0来标记,然后有所选点
想四个方向不断地遍历,若遇到颜色不相同的点则停止向这个店遍历,遍历其他的点;所遍历过的点都用1标记,并填充;
问题:如何遍历?
有两种方法:1.盲点扫描法:由其中一点向4个方向遍历并标记,然后扫描数组的每一个点,若被标记则向4个方向遍历并标记,以此类推。
2.数组:首先将所选点放到2个数组中,分别用来存放点的x,y坐标,然后删除一个点,由这一点向4个方个方向并放入数组中,然后再取出一个点,重复操作;
代码:
int go[][] = new int[][] { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; 
int[][] w1 = new int[1000][1000]; //填充数组
int fillx[]=new int [10000000];
int filly[]=new int [10000000];
public void paint0(int a1,int b1){
int len=1;
fillx[0]=a1;
filly[0]=b1;
while(len!=0){
a1=fillx[len-1];
b1=filly[len-1];
len--;
w1[a1][b1]=1;
for(int i=0;i<4;i++){
if((a1+go[i][0]>=0)&&(a1+go[i][0]<image.getHeight())&&(b1+go[i][1]>=0)&&(b1+go[i][1]<image.getWidth()))
if (w1[a1 + go[i][0]][b1 + go[i][1]] == -1) {
fillx[len]=a1 + go[i][0];
filly[len]=b1 + go[i][1];
len++;
}
}
}
}


6.文本框的构建功能 :
 // 取出文本域 
if (db.value.equals("10") && textflags == 1) {
textx = e.getX();
texty = e.getY();
if (!(textx >= textx1 && textx <= textx2 && texty >= texty1 && texty <= texty2)) {
s = jt.getText();
System.out.println(s);
jp_1.remove(jt);
jt.setText(null);
w = s.toCharArray();
int j = -1;
texty1 -= 50;
for (int i = 0; i < s.length(); i++) {
if (w[i] == '\n') {
g.drawChars(w, j + 1, i - j - 1, textx1, texty1);
texty1 += 17;
j = i;
}
}
}
}

7.菜单栏的功能:
//给菜单选项添加监听器 
MenuBar jmb = new JMenuBar();
this.setJMenuBar(jmb);
JMenu savemenu= new JMenu("保存");
jmb.add(savemenu);
savemenu.addMenuListener(ml);
JMenu openmenu= new JMenu("打开");
jmb.add(openmenu);
openmenu.addMenuListener(ml);

//********************************************************************************//


/**
* 创建菜单栏的方法,并且把菜单栏添加到窗体上
*/
public void createMenuBar() {
// 创建菜单条对象
JMenuBar bar = new JMenuBar();
String[] menus = { "文件", "颜色", "帮助" };
String[][] menuItems = { { "新建", "打开", "保存", "退出" }, { "编辑颜色" },
{ "帮助主题", "关于画图" } };
for (int i = 0; i < menus.length; i++) {
JMenu menu = new JMenu(menus[i]);
for (int j = 0; j < menuItems[i].length; j++) {
JMenuItem menuItem = new JMenuItem(menuItems[i][j]);
menu.add(menuItem);//将下拉菜单添加到菜单上
menuItem.setActionCommand(menuItems[i][j]);//获取点击下拉菜单上对象的命令
}
bar.add(menu);//将菜单添加到菜单条上
}
this.setJMenuBar(bar);// 把菜单条添加到窗体
}

五、技术点分析
在画图板的开发当中,用到的技术点有:构造器、类的继承、自动转型、多态、接口及抽线类、事件监听器、JAVA.SWING组件及布局管理器、GRAPHICS对象及方法的调用、数组和队列的运用。主要技术点:
1.构造器和类的继承,自动转型及多态及匿名内部类的灵活运用。
a.构造器的使用
// 重载构造器传入相关参数(创建工具面板对象和画布对象)
public DrawListener(ToolPanel tp, Graphics g, ColorPanel cp, DrawPanel dp, 
ListImp<Shape> shapes) {
this.tp = tp;
this.cp = cp;
this.dp = dp;
this.shapes = shapes;
g.setColor(color);
color = cp.getBackgroundColor();
}

b.匿名内部类的使用
// 实例化一个画图面板,并定义重绘画布对象的方法; final DrawPanel dp = new DrawPanel() { //使用匿名内部类 public void paint(Graphics g) { super.paint(g); // 遍历 drawShape(g); } } 

2.类参数及全局变量和局部变量的传入与使用。特别是graphics 类变量的传入与导出的处理。
 // 鼠标按下的时的监听方法 
public void mousePressed(MouseEvent e)
{
g = dp.getGraphics();
x1 = e.getX();
y1 = e.getY(); // 在画图之前取得选中的color color = cp.getBackgroundColor(); // 设为画布上的color g.setColor(color);
}

3. 数组的灵活运用。
//创建工具图形名称数组 String[] toolname={"any","select","brush","curve","eraser","line", "loupe","oval","paint","text","pencil","painting","polygon","rect","round_rect", 
//调用循环语句将数组中语素实例化对象及调用
for(int i=0;i<toolname.length;i++){
ImageIcon toolpic = new ImageIcon("images/"+toolname[i]+".gif");
javax.swing.JButton jbt = new javax.swing.JButton(toolpic);
jbt.setPreferredSize(new Dimension(25,25));
jbt.setActionCommand(toolname[i]);
jtbar.add(jbt);
jbt.addActionListener(btnlistener);}

4.重汇的队列实现:
思路: 通过创建一个类作为所有的画图方法类的父类,这样父类的方法能够有多种实现,然后创建一个父类队列,将每一个画图的操作都保存在个父类队列中,
然后在遍历队列的每一个元素重画;
代码:
1.父类代码:
/* 
* 画图形的父类
*/
public abstract class Shape {
int x1,y1,x2,y2,b;
Color color;
int w1[][]=new int [1000][1000];
BufferedImage image=null;

public Shape(int x1,int y1,int x2,int y2,Color color,int b){
this.x1=x1;
this.x2=x2;
this.y1=y1;
this.y2=y2;
this.color=color;
this.b=b;
}
public Shape(int w1[][],Color color,int b,BufferedImage image){
this.w1=w1;
this.color=color;
this.b=b;
this.image=image;
}
//定义画的方法
public abstract void draw(Graphics2D g);

}

2.往队列中加入元素的代码:
shape =new Drawline(j,i,j,i,g.getColor(),1); 
shape.draw((Graphics2D)g);
list.add(shape);
//这里子类会自动转型为父类

3.队列元素的重画:
public void paint(Graphics g){ 
super.paint(g);
Graphics2D g1= (Graphics2D) g;
System.out.println("重绘");
for(int i=1;i<=list.getSize();i++){
list.find(i).draw(g1);
}

六、开发过程中遇到的错误。
1.在画布对象的传入与导出时出现错误导致不能改变颜色。
2.添加菜单条时出错,添加菜单条到窗体时一定要使用set方法,否则导致画笔坐标出现误差。 // 设置窗体的菜单栏 this.setJMenuBar(menubar);
3.在最后画图方法继承shape类后,调用画图方法,在传入参数时出错。
没有与构造器参数顺序一致(方法参数顺序)
在做这个项目的过程中,我学到了很多。尽管有时候可能会用大量的时间来向怎么解决一个问题,但是与此同时我也收获了不少的经验,而且对所学的知识点也会有更进一步
的理解,我一定会继续努力下去的!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值