画图板界面如下:
截取后的图片: 截图.png
实现的功能有:
1、左边工具栏中功能:截图并保存,橡皮擦,取色笔,铅笔,刷子,喷枪,文本框,直线,矩形,椭圆,圆角矩形等功能
2、颜色选择功能(2处):底部颜色选择(第一个大的方形显示画笔当前的颜色)、菜单栏中“颜色”选择器
3、鼠标形状的切换:如:选择喷枪工具后,进入绘图区,鼠标变为喷枪形状
4、菜单栏中:“新建” 画图的功能,”打开“ 图片,”保存“ 修改后的图片的功能
由于内容太多,以 下叙述可能不是很详细
资源已打包(附详细注释)可以直接下载或者联系我,还可以互相交流一下下,嘿嘿
下载链接:http://download.youkuaiyun.com/detail/u010622887/6009271
总体分为九个类:
MainFrame.java: 主界面 MyMenuBar.java: 菜单栏 ColorPane.javal: 底部颜色面板 ToolPanel.java: 工具面板 PaintPanel.java: 画图面板
MyMouseListener.java: 鼠标监听类 MyList.java: 保存数组类 ImageCut.java: 截图功能类 Test.java: 测试类
Test.java: 测试类
public static void main(String[] args){
MainFrame frame=new MainFrame();
frame.showFrame();
}
一、MainFrame:
功能:创建菜单栏、底部颜色面板、工具面板、画图面板对象,并添加到主界面上;为画图面板添加监听
1、 布局方式:不用设置,为默认布局方式:BorderLayou
this.add(toolPanel,BorderLayout.WEST);
this.add(colorPanel,BorderLayout.SOUTH);
this.add(paintPanel,BorderLayout.CENTER);
2、为画图区创建鼠标监听时,可以只用MouseAdapter ; 但添加监听必须为两个:MouseListener ; MouseMotionListener
// 创建建鼠标监听,将三个面板传递给鼠标监听MyMouseAdapter mouse_listener=new MyMouseAdapter(toolPanel,colorPanel,paintPanel);
/*为画图区添加鼠标监听(按下、释放、单击、进入或离开)*/
paintPanel.addMouseListener(mouse_listener);
//另外还得添加鼠标移动的监听器(光标移动、拖拽等 )否则无法画出铅笔等
paintPanel.addMouseMotionListener(mouse_listener);
二、MyMenuBar:
功能:实现菜单子项目等的添加,并为之添加监听
1、创建菜单条后,将菜单选项添加至菜单条,再将子选项添加至菜单目录下 (JMenuBar;JMenu;JMenuItem)
//例:添加菜单子选项“新建”
menu_file=new JMenu("文件");
this.add(menu_file);
item_new=new JMenuItem("新建");
menu_file.add(item_new);
其子项目他同上
2、内部类形式创建ActionListener();获取选项命令menu_command:判断后,做出相应的反映:
JFileChooser默认的路径为桌面的TEST
(1.)新建功能: 重新加载一个新窗体
MainFrame frame=new MainFrame();
frame.showFrame();
(2.)打开对话框,选择要打开的图片
想在面板中显示图像:Graphics2D中有drawImage();【 g.drawImage(image, 5, 5, image.getWidth(), image.getHeight(), null);】
必须得到面板的画布:g 、所需显示的图形对象 image、显示图像的位置
(3.)保存修改后的图片(详见后文,截图功能后)
(4.)全部清除的功能:
(5.)打开颜色选择器
保存用户所选择的颜色:color=JColorChooser.showDialog(fileChooser, "选择颜色", Color.black);
选择颜色后改变ColorPanel:中大按钮的背景色为当前选择的颜色,故需要得到颜色面板中的大按钮
创建完监听器后,给子选项添加监听器
三、ColorPanel:
功能:改变画布的颜色,并显示在颜色面板的第一个大矩形区域内
1、流式布局,向左靠齐:setLayout(new FlowLayout(FlowLayout.LEFT));
2、用一数组装颜色,以遍历数组的方式,给每个按钮添加背景颜色,创建监听,添加监听
3、监听具体内容:当鼠标点击时,获得所选按钮的背景颜色,将第一个JPanel中的大按钮的背景色改成当前所选的颜色
四:ToolPanel:
功能:添加工具到工具面板上,并为之添加监听
流式布局:String[] 装图形的名称,for循环顺序为每个按钮添加图形
创建ActionListener监听,按下按钮后,获取tool_command;
提供getCommand(),传递给鼠标监听类
五:MyMouseListener:
功能:处理鼠标发生相应变化时发生的事件
在MainFrame 中创建此类;获得来自MainFrame 中的toolPanel, colorPanel,paintPanel
1、改变光标:
进入画图区时:mouseEntered();
cursor=Toolkit.getDefaultToolkit().
createCustomCursor(new ImageIcon("images/"+name+".jpg").getImage(),new Point(10,10), name);
cursor=new Cursor(Cursor.CROSSHAIR_CURSOR);
paint_panel.setCursor(cursor);
2、画简单几何图形:
按下时:获得点的坐标:(X1,Y1);
释放时:获得点的坐标(X2,Y2);
g.drawLine(X1, Y1, X2, Y2);
g.drawRect(Math.min(X1,X2),Math.min(Y1, Y2) , Math.abs(X1-X2), Math.abs(Y1-Y2));
g.drawOval(Math.min(X1,X2),Math.min(Y1, Y2) , Math.abs(X1-X2), Math.abs(Y1-Y2)); g.drawRoundRect(Math.min(X1,X2),Math.min(Y1, Y2) , Math.abs(X1-X2), Math.abs(Y1-Y2), (Math.abs(X1-X2))/3, (Math.abs(Y1-Y2))/3);
多边形:
设置画的第一条边的起始点为第一坐标点,用第一条边的结束点作为第二条边的起始点,
直到有一条边的结束点为第一条边的起始点,结束画图,count清零
所画直线分为两种,第一条边为g.drawLine(X1,Y1,X2,Y2);此后的直线,可以用
g.drawLine(next_x,next_y,X2,Y2);
next_x=X2;
next_y=Y2;
3、简单类似工具:铅笔,橡皮擦,刷子(类似的画法)
在拖动mouseDragged()中:(X2,Y2)是动态变化的点
类似于画多边形
g.drawLine(X1, Y1, X2, Y2);
X1=X2;
Y1=Y2;
橡皮擦,刷子=多个铅笔并排一起画
for(int x=X2;x<X2+8;x++){
for(int y=Y2;y<Y2+8;y++){
g.drawLine(x, y,X2, Y2);
}
}
4、喷枪:
mousePressed()中,
//画10个点,在距离鼠标10个单位内
for(int i=0;i<10;i++){
int x,y;
x=X1+new Random().nextInt(10);
y=Y1+new Random().nextInt(10);
}
mouseDragged()中,取随机数
x=X2+new Random().nextInt(10);
y=Y2+new Random().nextInt(10);
g.fillRect(x,y, 1, 1);
5、取色笔 (详见MyMouseAdapter.java)
color = new Robot.getPixelColor(mousepoint.x, mousepoint.y);
6、文本框:
思路:显示一个文本框,输入字符串。单击文本框以外的地方,将字符串显示在面板上,文本框移除
mouseReleased()中,
(1、)创建文本框前提:
if("word".equals(tool_command)&&(textArea_show==false)&&(Math.abs(X1-X2)>20&& Math.abs(Y1-Y2)>20)
(2、)释放鼠标,得到坐标,设置矩形文本框的大小
(3、)给文本框创建监听器,添加监听,保存文本框的字符串
text=textArea.getText();
(4、)面板被单击时,将文本框的字符串画到画图面板上
g.drawString(text, text_x, text_y);
注意:此处画字符串的起始点在文本框左上角点的下方一些
(5、)移除文本框,重绘画板区(必须)
paint_panel.remove(textArea);
paint_panel.repaint();
文本框功能重点:给文本框添加监听的类型:
JTextField:创建的是单行文本框;JTextArea:多行文本框
(1、JTextField,能添加ActionListener();TextListener();
ActionListener():必须按下回车键才触发事件,获取文本字符串,繁琐
TextListener():文本框发生改变时,触发事件,从而方便的获取文本内容
// 内部类形式
TextListener text_listener=new TextListener(){
public void textValueChanged(TextEvent e) {
text=textArea.getText();
}
};
textArea.addTextListener(text_listener);
(2、JTextArea,不能添加上面两种监听;能添加KeyListener;
/**
* 单击画板后,文本框才会失去焦点,即要画板被点击后才能获取文本
* 内容,矛盾。造成text 为空,报错
*/
FocusListener text_focusListener=new FocusListener(){
public void focusGained(FocusEvent e) { }
public void focusLost(FocusEvent e) {
text=textArea.getText();
}
};
textArea.addFocusListener(text_focusListener);
//在文本框区域外单击,文本框消失,字符显示
if(textField.getComponentAt(e.getPoint())==null){
paint_panel.setTextList(textList.saveValue(text, text_x, text_y,
textArea.getLineCount(),textArea.getColumns(),color));//保存行,列数值到数组里面
}
6、截图:
思路:鼠标释放后,抓图得到截图的矩形区域(类似画矩形),传给ImageCut.java ,由ImageCut.对象将其保存为图片
//得到鼠标释放点的坐标,创建一个相对屏幕的矩形
Rectangle rectangle=new Rectangle(mousepoint.x, mousepoint.y, Math.abs(X1-X2), Math.abs(Y1-Y2));
new ImageCut(rectangle).cutImage();//创建截图对象,调用截图方法
六、PaintPanel
功能:接收从MyMouseAdapter传入的所需自定义数组队列显示画图面板,实现重绘画图面板区的功能
//提供设置数组的方法,从MyMouseAdapter传入所需数组队列
public void setTextList(Object[] my_list){
this.textList=my_list;
}
/**
* 重绘画板区
*/
public void paint(Graphics g){
super.paint(g);
//重绘图片
if(!(bufferedImage==null)){
System.out.println("重绘图片。。。。");
g.drawImage(bufferedImage, 5, 5, bufferedImage.getWidth(), bufferedImage.getHeight(), null);
};
//非拖曳区重绘,第一个数组,每次取出六个数,赋值后画出(画矩形为例)
for(int i=0;i<myList_1.length;i=i+6){
X1=(Integer)myList_1[i];
Y1=(Integer)myList_1[i+1];
X2=(Integer)myList_1[i+2];
Y2=(Integer)myList_1[i+3];
tool_command=(String)myList_1[i+4];
color=(Color)myList_1[i+5];
g.setColor(color);
if("rect".equals(tool_command)){
g.drawRect(Math.min(X1,X2),Math.min(Y1, Y2) , Math.abs(X1-X2), Math.abs(Y1-Y2));
}
}
//拖曳区,每次取出六个数,赋值后画出(铅笔为例)
for(int i=0;i<myList_2.length;i=i+6){
X1=(Integer)myList_2[i];
Y1=(Integer)myList_2[i+1];
X2=(Integer)myList_2[i+2];
Y2=(Integer)myList_2[i+3];
tool_command=(String)myList_2[i+4];
color=(Color)myList_2[i+5];
g.setColor(color);
if("pencil".equals(tool_command)){
g.drawLine(X1, Y1, X2, Y2);
X1=X2;
Y1=Y2;
}
}
}
七、Mylist
功能:实现单个或多个数据添加到自定义队列中(例:每次添加六个值);
保存画图面板中的图形数据(坐标等),等待重绘时使用
//定义两个数组:目标数组长度是原始数组+6;将原始数组数据顺序复制到目标数组,再将六个需要保存的数据添加到目标数组尾部
private Object[] my_list = new Object[0];
private Object[] destArray = new Object[my_list.length+6];
/**
* 用数组保存基本图形坐标值,六个值为Object类
*/
public Object[] saveValue(int x1,int y1,int x2,int y2,String tool_command,Color color){
//清空目标数组,设置长度为源数组+6
destArray = new Object[my_list.length+6];
for(int i=0;i<my_list.length;i++){
destArray[i] = my_list[i];
};
destArray[my_list.length] = x1;
destArray[my_list.length+1] = y1;
destArray[my_list.length+2] = x2;
destArray[my_list.length+3] = y2;
destArray[my_list.length+4]=tool_command;
destArray[my_list.length+5]=color;
my_list = destArray;
return my_list;
}
八、ImageCut:
功能:实现画图板指定区域的截图,并将图片命名后保存至选择的文件中
单独创建一个截图类:ImageCut.java 需要获得所要截取图形的区域rectangle
1、获取截图对象:image = new Robot().createScreenCapture(Rectangle r);
2、显示保存对话框【用户选择完保存的路径,输入命名文件的字符串】
fileChooser.showSaveDialog(fileChooser)
3、若用户选择确定保存按钮:获得当前路径,使用拼接路径(当前路径+用户输入的文件名)创建一个新文件
String fileName=fileChooser.getSelectedFile().getName();
String savePath=fileChooser.getCurrentDirectory()+"\\"+fileName+".png";//拼接存储路径
File destFile=new File(savePath);
4、将图片写入新的空文件中
ImageIO.write(image, "png", destFile);
详见
7、保存修改后的图片的功能
跟截图功能一样,只是截图的大小为原始的大小
Point point_screen=paint_panel.getLocationOnScreen();
Rectangle rectangle=new Rectangle(point_screen.x+5, point_screen.y+5, image.getWidth(), image.getHeight());
源代码下载链接:http://download.youkuaiyun.com/detail/u010622887/6009271