整体思路的分析:1,首先要有一个得到窗体的类,即包含主函数的类2,当点击鼠标时,要发生鼠标事件,所以要写一个监听类。3,当画不同的图形时,要写成不同的类,来实现画图形的方法。4,当我们前三步做好时,每当我们点击鼠标时,能够画图形了,但当我们把窗体移动时,原来画的图形就不见了,这样,我们就必须要实现图形的重绘,我们定义一个队列用来保存图形,所以就必须要有一个队列类5,虽然能够实现画板的重绘,但有时我们希望把图形保存到硬盘里。所以就必须要有一个打开和保存文件的类。
具体步骤:
1,得到窗体的类,由于这个类比较简单,我就不完全把代码写下来了。
javax.swing.JRadioButton line = new javax.swing.JRadioButton("Line");
line.setActionCommand("Line");
line.setSelected(true);// 默认选中
javax.swing.JRadioButton rect = new javax.swing.JRadioButton("Rect");
rect.setActionCommand("Rect");
javax.swing.JRadioButton oval = new javax.swing.JRadioButton("Oval");
oval.setActionCommand("Oval");
javax.swing.JRadioButton filloval = new javax.swing.JRadioButton("FillOval");
filloval.setActionCommand("Filloval");
javax.swing.JRadioButton trangle = new javax.swing.JRadioButton("Trangle");
trangle.setActionCommand("Trangle");
javax.swing.JButton bu_color=new javax.swing.JButton("ChooseColor");
final javax.swing.JButton b=new javax.swing.JButton("Save");
final javax.swing.JButton c=new javax.swing.JButton("Open");
这是窗体的组件。"ChooseColor"按钮是选择颜色按钮,"Save"是图形保存到文件的按钮,"Open"是将文件的图形显示出来的按钮。为了窗体的美观,我还定义了两个面板。
//给窗体加面板
Panel panel=new Panel();
Panel panel2=new Panel();
//将按钮添加到面板中去
panel.add(bu_color);
panel.add(line);
panel.add(rect);
panel.add(oval);
panel.add(filloval);
panel.add(trangle);
panel2.add(b);
panel2.add(c);
//将面板添加到窗体中去
this.add(panel,BorderLayout.NORTH);
panel.setBackground(Color.LIGHT_GRAY);
this.add(panel2,BorderLayout.SOUTH);
panel2.setBackground(Color.LIGHT_GRAY);
简单的界面已经完成了。效果如下:
![](http://dl.iteye.com/upload/attachment/465350/eca85664-ff8e-3c20-a085-4b52628d326f.jpg)
2.然后我们需要写画不同形状的类,由于我的画图板是写了六种不同形状,我在这里主要写一下画矩形和画三角形的类。画矩形的方法:
public class Rect extends Shape{
public int x1,y1,x2,y2;
public Rect(int x1,int y1,int x2,int y2 ){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public void draw(Graphics g){
type=2;//标记类型的变量
g.setColor(this.getColor());
if(x1<x2&&y1<y2)
g.drawRect( x1, y1, Math.abs(x1-x2), Math.abs(y1-y2));
else if(x1>x2&&y1>y2)
g.drawRect(x2, y2, Math.abs(x1-x2), Math.abs(y1-y2));
else if(x1>x2&&y1<y2)
g.drawRect(x2, y1, Math.abs(x1-x2), Math.abs(y1-y2));
else
g.drawRect(x1, y2, Math.abs(x1-y1), Math.abs(y1-y2));
}
}
画三角形的类:
public class Trangle extends Shape {
public int x1,y1,x2,y2;
Random random=new Random();
//随机生成一点的坐标
int x3=random.nextInt(250)+50;
int y3=random.nextInt(250)+50;
public Trangle (int x1,int y1,int x2,int y2){
this.x1=x1;
this.y1=y1;
this.x2=x2;
this.y2=y2;
}
public void draw(Graphics g){
type=5;
g.setColor(this.getColor());
int d1=(int)Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
int d2=(int)Math.sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));
int d3=(int)Math.sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3));
if((d1+d2)>d3&&(d1+d3)>d2&&(d2+d3)>d1){
g.drawLine(x1,y1,x2,y2);
g.drawLine(x1,y1,x3,y3);
g.drawLine(x2, y2, x3, y3);
}
}
}
这样画图形的类就已经完成了。然后我们就应当要画图形了,画图形首先必须要有监听器,能够监听事件源
3.监听类
public class DrawListener implements java.awt.event.MouseListener {
private int x1,y1,x2,y2;
private Graphics g;
private javax.swing.ButtonGroup group;
private Color color = Color.BLACK;
Shape sh=null;
//传参过来
public DrawListener(Graphics g,javax.swing.ButtonGroup group){
this.g = g;
this.group = group;
}
public void setColor(Color color) {
this.color = color;
}
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
public void mouseReleased(MouseEvent e) {
x2 = e.getX();
y2 = e.getY();
//得到选中的形状
String str = group.getSelection().getActionCommand();
Shape sh=null;
//设置形状的颜色
if("Line".equals(str)){
sh = new Line(x1,y1,x2,y2);
}
if("Rect".equals(str)){
sh = new Rect(x1,y1,x2,y2);
}
if("Oval".equals(str)){
sh=new Oval(x1,y1,x2,y2);
}
if("Filloval".equals(str)){
sh=new fillOval(x1,y1,x2,y2);
}
这只是监听图形选择按钮,还有颜色选择按钮和打开,保存按钮也要添加监听器,只不过这三种按钮加的不是鼠标监听器,而是事件监听器。我首先只写下颜色选择按钮监听器,保存和打开按钮到后面再写,应为牵涉到文件的读写。
颜色选择按钮添加事件监听器:
bu_color.addActionListener(new java.awt.event.ActionListener(){
public void actionPerformed(ActionEvent e){
showColorSelecter();
}
});
public void showColorSelecter(){
this.color=JColorChooser.showDialog(null, "请选择颜色", java.awt.Color.black);
//System.out.println(color);
//DrawListener l=new DrawListener(color);
lis.setColor(color);
}
当我们到这一步时,我们已经可以选择不同的颜色来画不同的形状了,但我们又发现,当我们移动窗体时,我们画过的图形又不见了,所以我们必须要实现画板的重绘。所以必须再写一个类,然后在定义一个泛型的队列,将画过的图形保存到队列中。而且写的这个类是用来保存不同形状的类,所以不同形状的类必须要继承该类。
画图行时的效果如下:
![](http://dl.iteye.com/upload/attachment/465358/2563c53c-3db5-3739-ba73-52c688612b2f.jpg)
4.形状(用来保存不同图形)类
public abstract class Shape {
public Color c;//颜色
public int type;
public void setColor(Color c){
this.c = c;
}
public Color getColor(){
return c;
}
/**
* 绘制的方法
* @param g
*/
public abstract void draw(Graphics g);
}
现在我们已经能够实现画图板的重绘了,但我们有时还想把它保存到硬盘里,所以我们必须再写一个类,这个类是用来把图形保存到文件中,而且在把文件中的图形显示出来
5.文件读写类:
public class FileReadAndWrite {
/**
* 将画图板写到文件中去
*
* @param path写入的路径
* @param shape待写的数据
*/
public static void WriteFile(String path, NJListImp<Shape> shapes) {
File file = new File(path);// 先创建一个文件
try {
// 定义一个输出流
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
// 得到总的数据
int t = shapes.size();
// 写入文件头
dos.writeInt(t);
// 遍历队列
for (int i = 0; i < shapes.size(); i++) {
Shape shape = shapes.get(i);// 根据下标取对象
// 得到对象的颜色
// System.out.println(shape);
// System.out.println(shape.getColor());
Color color = shape.getColor();
int c = color.getRGB();
// 将颜色写入到文件中
dos.writeInt(c);
dos.writeByte(shape.type);// 将对象的类型写入到文件中去
if (shape.type == 1) {// 如果是直线
// 强制转化
Line line = (Line) shape;
// 将4个点写到文件中去
dos.writeInt(line.x1);
dos.writeInt(line.y1);
dos.writeInt(line.x2);
dos.writeInt(line.y2);
}
if (shape.type == 2) {// 如果是矩形
// 强制转化
Rect rect = (Rect) shape;
// 将4个点写到文件中去
dos.writeInt(rect.x1);
dos.writeInt(rect.y1);
dos.writeInt(rect.x2);
dos.writeInt(rect.y2);
}
if (shape.type == 3) {// 如果是圆形
// 强制转化
Oval oval = (Oval) shape;
// 将4个点写到文件中去
dos.writeInt(oval.x1);
dos.writeInt(oval.y1);
dos.writeInt(oval.x2);
dos.writeInt(oval.y2);
}
if (shape.type == 4) {// 如果是圆形
// 强制转化
fillOval filloval = (fillOval) shape;
// 将4个点写到文件中去
dos.writeInt(filloval.x1);
dos.writeInt(filloval.y1);
dos.writeInt(filloval.x2);
dos.writeInt(filloval.y2);
}
if (shape.type == 5) {// 如果是三角形
// 强制转化
Trangle trangle = (Trangle) shape;
// 将4个点写到文件中去
dos.writeInt(trangle.x1);
dos.writeInt(trangle.y1);
dos.writeInt(trangle.x2);
dos.writeInt(trangle.y2);
dos.writeInt(trangle.x3);
dos.writeInt(trangle.y3);
}
}
dos.flush();
dos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 将文件中的数据读出来
*
* @param path待读的路径
* @return:返回读出队列
*/
public static NJListImp<Shape> ReadFile(String path) {
NJListImp<Shape> shape = new NJListImp<Shape>();
try {
// 定义输入流
FileInputStream fis = new FileInputStream(path);
DataInputStream dis = new DataInputStream(fis);
// 得到队列中数据的总长度
int len = dis.readInt();
// 根据队列的长度依次读出数据
for (int i = 0; i < len; i++) {
int c = dis.readInt();
Color color = new Color(c);// 读出颜色
Byte b = dis.readByte();// 读出类型
if (b == 1) {
// 读出两个点的坐标
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
// 将数据加到shape中
Line line = new Line(x1, y1, x2, y2);
line.setColor(color);
line.type = b;
shape.add(line);
}
if (b == 2) {
// 读出两个点的坐标
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
// 将数据加到shape中
Rect rect = new Rect(x1, y1, x2, y2);
rect.setColor(color);
rect.type = b;
shape.add(rect);
}
if (b == 3) {
// 读出两个点的坐标
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
// 将数据加到shape中
Oval oval = new Oval(x1, y1, x2, y2);
oval.setColor(color);
oval.type = b;
shape.add(oval);
}
if (b == 4) {
// 读出两个点的坐标
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
// 将数据加到shape中
fillOval filloval = new fillOval(x1, y1, x2, y2);
filloval.setColor(color);
filloval.type = b;
shape.add(filloval);
}
if (b == 5) {
// 读出三个点的坐标
int x1 = dis.readInt();
int y1 = dis.readInt();
int x2 = dis.readInt();
int y2 = dis.readInt();
int x3=dis.readInt();
int y3=dis.readInt();
// 将数据加到shape中
Trangle trangle = new Trangle(x1, y1, x2, y2);
trangle.setColor(color);
trangle.type = b;
trangle.x3=x3;
trangle.y3=y3;
shape.add(trangle);
}
}
dis.close();
fis.close();
return shape;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
当写到这来时,我们在给"Save"和"Open"按钮添加监听器:
由于我这步操作是基于已经写好的程序后添加的功能,故我们写个事件匿名类,就不需修改前面的代码
//给保存和打开按钮添加事件监听器
ActionListener ac=new ActionListener (){
public void actionPerformed(ActionEvent e){
if(e.getSource()==b)
FileReadAndWrite.WriteFile(path, shapes);
else if(e.getSource()==c){
shapes=FileReadAndWrite.ReadFile(path);
repaint();
}
}
};
b.addActionListener(ac);
c.addActionListener(ac);
//设置按钮的事件监听器
如果我重新选择窗体的颜色,或是撤销上次画过的图形运行效果如下:
![](http://dl.iteye.com/upload/attachment/465361/01fba7d9-2c52-3122-8a34-ab9315d18785.png)
这个简单的画图板就已经完成了
在这个基础上,我又添加了一些功能,比如说背景颜色的选择,清除最后一次画的图形,和清除所有的图形
我在这个程序中的给画布设置颜色选择器时,做了很久,当点击画布颜色选择按钮时,不知道怎么把颜色传到画布中去,后来想了个笨方法,用构造器传参。后来由于老师指导,直接在监听器中写个setcolor方法就可以在选择颜色的那个方法直接通过类名去调用了,以前学的基础内容,我就不知道用在这里了。还有我在写清除最后一次画过图形的方法时,没有想到调用队列中的remove方法,直接通过移除最后的对象就可以了。我是自己把最后的对象中的数据全部设为0的,我觉得我以后思维要开拓点,应充分使用API文档中的方法,最后还有个问题就是,在往窗体中加组件时,必须把加组件的程序代码写在this.setVisible(true)前面,不然,有时运行程序时,添加的组件将不会出现在窗体中。而this.setVisible(true)必须写在得多画布代码的前面,否则将会出现空指针异常。
但我背景颜色选择中还有个问题:当把画过的图形及窗体颜色及画布颜色保存到文件中,然后在点击打开按钮时,画过的图形不见了,只有窗体的颜色,然后最小化窗体,然后在打开,窗体上的图形又出现了。我觉得很奇怪,弄了很久都没弄出来,哪个高手指点一下啊
![点击查看原始大小图片](http://dl2.iteye.com/upload/attachment/0046/5117/46e0c95a-97c4-37f7-b0b7-b1a429d1572f-thumb.jpg)
- 大小: 122.7 KB
![点击查看原始大小图片](http://dl2.iteye.com/upload/attachment/0046/5350/eca85664-ff8e-3c20-a085-4b52628d326f-thumb.jpg)
- 大小: 33.7 KB
![点击查看原始大小图片](http://dl2.iteye.com/upload/attachment/0046/5358/2563c53c-3db5-3739-ba73-52c688612b2f-thumb.jpg)
- 大小: 48.4 KB
![点击查看原始大小图片](http://dl2.iteye.com/upload/attachment/0046/5361/01fba7d9-2c52-3122-8a34-ab9315d18785-thumb.png)
- 大小: 17.1 KB
分享到:
相关推荐
【JAVA简易画图板】是一个基于Java编程语言开发的简单绘图应用程序,它为用户提供了一个基本的图形界面,用户可以通过这个界面进行简单的绘画操作。这个程序包含了一些基本的绘图功能,如绘制形状、使用铅笔工具以及...
"简单画图板的设计"是一个关于创建一个基本图形编辑器的话题,主要涉及到计算机图形学、用户界面设计以及可能的编程实现。在这个项目中,我们可能会遇到以下关键知识点: 1. **计算机图形学基础**:画图板应用的...
《Flash简易画图板:选中工具作图与互动功能详解》 在数字艺术和教育领域,Flash作为一种曾经广泛使用的交互式矢量图形和多媒体平台,曾为许多开发者提供了丰富的创作空间。本篇文章将深入探讨一个基于Flash开发的...
在本文中,我们将深入...通过以上步骤,我们可以构建一个功能完备的MFC简易画图板应用。这个过程涉及到Windows编程基础、MFC类库的使用、图形绘制以及用户交互等多个方面,是学习MFC和Windows编程的一个良好实践项目。
### 基于VC++MFC程序设计——简易画图板 #### 概述 本文档将详细介绍如何利用VC++中的MFC(Microsoft Foundation Classes)框架来开发一款简易的画图板应用程序。该画图板的主要功能包括但不限于图形的绘制、线型...
C# 开发的简单画图板 含源代码 C# 开发的简单画图板 含源代码 C# 开发的简单画图板 含源代码
【简易画图板程序java】是一个基于Java编程语言实现的简单图形绘制软件,它涵盖了图形学的基本概念和技术,为用户提供了一个交互式的平台,可以进行基本的图形绘制操作。这个程序的核心功能包括画直线、绘制圆以及对...
【Java简易画图板】是一个基于Java编程语言开发的简单图形绘制工具,它为用户提供了一个基本的画布,用户可以通过各种绘图工具进行创作。这个程序包含了一系列基础的图形元素和编辑功能,如直线、铅笔、圆形和矩形,...
"MFC简单画图板"是一个基于Microsoft Foundation Class (MFC)库开发的简易绘图应用程序。MFC是微软提供的一套面向对象的C++类库,它为Windows应用程序开发提供了便利,封装了Windows API,使得开发者能更高效地构建...
本项目“virtual c++6.0 mfc简易画图板”正是基于VC++ 6.0的MFC库,实现了类似Windows自带画图板的功能,让用户能够进行简单的图形绘制,如直线、圆、矩形和椭圆,并且可以调整线条的颜色和类型。 一、MFC库介绍 ...
通过以上步骤,我们可以构建一个功能齐全的Java简易画图板。这个项目不仅可以帮助学习者掌握Java GUI编程,还能加深对图形绘制和事件处理的理解。在实际开发过程中,还可以进一步增加撤销/重做功能、图层管理、...
《VC++简易画图板详解》 在计算机编程领域,C++是一种强大的、面向对象的编程语言,广泛应用于系统软件、应用软件、游戏开发、驱动程序等各个领域。本项目以VC++为工具,利用MFC(Microsoft Foundation Classes)...
【标题】"仿照win的简易画图板"是一个基于计算机图形学原理和技术,模仿Windows操作系统内置的“画图”程序开发的简单图形编辑软件。这个应用提供了基本的绘图工具,让用户能够进行简单的图形创作和编辑。 【描述】...
【VB语言编写的简易画图板程序】 VB(Visual Basic)是Microsoft开发的一种可视化的、面向对象的编程语言,尤其适合初学者入门。这个“简易画图板程序”利用VB的强大功能,创建了一个用户友好的图形界面,允许用户...
这个“VB简易画图板 鼠标响应”项目主要涉及以下几个核心知识点: 1. **窗体控件**:首先,我们需要一个主窗体(Form)作为画图板的基础,它将承载所有的绘图操作。可以设置窗体的背景色为白色或其他颜色,以模拟...
在这个简易画图板项目中,我们可能需要使用`JFrame`作为应用程序的主窗口,`JPanel`作为画布,以及`Graphics2D`对象进行绘图。 1. **JFrame**: 是Swing中的顶级容器,相当于窗口。在这里,我们将用它来创建我们的...
【简易画图板】是一个基础的图形绘制工具,它的核心目标是提供一个简单易用的平台,让用户可以进行基本的绘图操作。虽然功能相对有限,但该项目在开发过程中运用了两种重要的技术——橡皮筋技术和双缓存技术,这在...
本项目“C#简易画图板”就是利用C#语言在Visual Studio 2010环境下构建的一个简单绘画应用程序。该程序旨在提供基本的绘图功能,让初学者了解图形用户界面(GUI)编程和事件处理的基础知识。 首先,我们来了解一下...
在这个简易画图板项目中,我们将主要关注框架窗口和视图这两个组件。 **框架窗口与视图** - **框架窗口 (CFrameWnd)**:这是MFC中的顶级窗口类,通常作为应用程序的主窗口。它包含了菜单、工具栏和状态栏等元素。在...