用Java语言编写一个简易画板

 

    讲了三篇概博客的概念,今天,我们来一点实际的东西。我们来探讨一下如何用Java语言,编写一块简易的画图板。

一、需求分析

    无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目需要满足怎样的需求。

    那么,画板需要满足怎样的需要呢?换句话说,在画板上,我们应该赋予它什么功能呢?从我们熟悉的画板来看,我们需要实现诸如铅笔、橡皮、喷枪、刷子的功能,我们可以画出一些规则的图形,比如直线、矩形、圆。最好我们还能调整画笔的颜色和粗细。以上,我们希望的是,当我们点击一个按钮的时候,我们就能实现相对应的功能。一个简单画板的功能大概就这么多了,一些关于添加文本框、放大镜等的操作在简单画板上就不一一实现了。

二、实现画板

1、基本图形的绘制

    我们先从最基本的画一些基本图形开始。在Java里有一个画笔类Graphics,而我们实现画板功能的关键就在这里。在Graphics这个画笔类里面,有几个方法,比如:画矩形、圆、直线。了解了这一点,我们的思路就来了。接下来,我们将一步一步认识实现基本图形绘制的全过程。

    首先,我们需要实例化一个JFrame容器,并给它设置初始值。其次,我们需要在这个容器上,添加一些按钮。这里以直线、矩形、圆为例。这部分的实现比较简单,需要注意的是,我们可以通过实例化一个字符串类型的数组去存储按钮里的内容,然后通过遍历数组的方式去实现多个按钮的建立,以此减少代码行数。给出代码如下:

 

    其次,因为涉及到关于鼠标点击以及按钮点击的操作,我们需要用到事件监听机制,MouseListener和ActionListener。因为它们都是接口,不能被实例化对象,所以我们需要建立一个事件处理类去实现这两个接口,并重写其中的抽象方法。具体代码如下:

    当然,仅仅这样是不够的。首先,我们需要对事件源,也就是我们的按钮和画板界面通过addXXXListener的方式添加事件处理机制。其次,我们还需要对对应的方法,在其方法体中写上我们需要实现的功能。画笔类是一个抽象类,因此它是不能被实例化的,我们只能通过getGraphics这个方法从JFrame或者是JPanel里去获取画笔。注意,画笔的获取要在让界面可见之后。之后,因为我们在事件处理类里面要用到画笔,所以,我们还需要将画笔从我们的画板界面传到我们的事件处理类当中,我们可以在事件处理类里面定义一个setGraphics的方法,同时定义一个Graphics的引用去接收这个画笔。具体代码如下:

 

 

 

    接下来就是调用画笔里的方法了。举个例子,当我们获取的按钮里的内容是Line的时候,那么,我们需要调用画笔Graphics里的drawLine方法,我们需要给它起始点和终点的x,y坐标。所以,我们在mousePressed方法里,记录下起始点的x,y坐标,在mouseReleased里记录下释放点的xy坐标,然后调用这个drawLine方法。那么,我们就可以在我们按下和释放的地方连成一条直线。代码实现如下:

 

    这样我们就实现了三个基本图形的绘制。其他的, 在Graphics画笔类里面还有关于弧形、多边形、填充矩形等绘制方法,这里就不一一列举了。

2、画笔颜色与粗细的变化

    Java里有一个Color类,它可以用作画笔颜色的设置。除了固定颜色的选取,例如Color.BLACK,我们程序员自己还可以自己去调取颜色。我们知道,每一种颜色,都可以由红、绿、蓝三基色按不同程度调配而成。在Java里有一个关于Color的构造方法,传入三个int类型、范围在0到255之间的数,分别对应红绿蓝三种颜色的程度。我们可以通过Color 颜色名=new Color(int a,int b,int c)的方式去自行定义自己想要的颜色。之后,我们可以通过.setColor的方式,将我们新建的颜色赋给我们的画笔。

    而关于画笔粗细的设置方法,它并不在Graphics类里面,而是在它的子类Graphics2D里面。相较于Graphics,Graphics2D同样是一个抽象类,但是它里面新增了不少方法,比如给画笔设置粗细的方法setStroke。而在setStroke这个方法中,你所需要传递的参数是一个Stroke类型的参数,而Stroke是一个接口,所以不能够实例化,因此我们给它传递的是Stroke的一个封装类BasicStroke,它实现了Stroke这个接口。因此,我们设置粗细的方式为:(Graphics2D)g.setStroke(new BasicStroke(float width))。

    如果我们需要实现这样的情况,在画板界面里有红、绿、蓝等多种颜色的按钮,当点击后画笔变成相应颜色,我们可以通过给按钮设置颜色的方式去处理这样的问题。给按钮或者窗体设置颜色的方式是.setBackground(Color c)。

3、铅笔、刷子、橡皮以及喷枪的实现

    现在,我们知道了如何画一个圆,画一条直线。在实现铅笔等功能钱,我想先问个问题,如何去画一个点?我有两个想法,一个是,你可以通过画实心圆的方式来画一个点,给它半径指定为一个像素,那么所画出的实心圆就成了一个点。第二种,可以通过画直线的方式,指定起始位置和释放位置相同,那么画出的也是一个点。

    接下来,我们要讲讲如何实现铅笔的功能。这里需要介绍一个新的事件监听方法,MouseMotionListener。在这个接口里,有一个鼠标拖动的监听方法。我们可以用它来实现铅笔的实现。它的工作机制是每隔一段时间,就获取一次你鼠标所在的位置。当然,这个时间非常短。事实上,我们可以观察在画图板上的直线。我们会发现每一条不规则曲线,都是由若干条直线构造而成的。那么,在这个拖动过程当中,我们可以在开始的地方记录下它的xy坐标,然后每运行一次拖动获取,就改变一次起始的xy坐标,那么,我们就实现了所谓的铅笔绘图功能。因为我们的事件处理类同时也继承了MouseListener,在拖动进行的开始,事实上我们已经进行了一次点击操作,所以,最开始的坐标我们不需要记录。注意,因为是不同的监听方法,所以一定要记得给画板界面添加MouseMotionListener的监听方法。铅笔的具体代码实现如下:

 

    实现了铅笔,刷子其实也就那么回事,我们只需要将铅笔实现这部分的代码复制下来,并在之前添加一行给画笔加粗的代码即可,加粗了的铅笔,不就是我们的刷子吗?至于橡皮,我们也可以这么理解,只要找到与画板界面底色相类似的颜色,给画笔赋这样的颜色,不就能覆盖掉原有的部分了吗?

    接下来是关于喷枪的实现。我们可以将喷枪理解成,在铅笔的基础上(去掉铅笔所绘的轨迹),对于一个点,在一定范围内,随机画若干个点。类似的变换,我们可以对一个点的xy坐标加减一定范围内不等的值,画出来的效果,就类似于喷枪效果了。生成随机数的方法在Random这个类里面,所以我们首先需要实例化一个Random类,然后通过nextInt(int a)的方式去获取一个0到a-1的随机数。这样,我们就能实现喷枪了。具体代码如下:

4、重绘

    在这个实验过程当中,我们很容易发现一个问题,当我们最小化或者说调整窗体大小的时候,我们所绘制的图形消失了,然而按钮还在。这是为什么呢?事实上,每当我们进行一次最小化或者调整窗体大小的时候,我们原先的那个窗体都被关闭了,接着计算机又重新绘制了一个全新的窗体。所以,我们自行绘制的图形都没有了。那么,为什么我们的按钮还在?事实上,不仅仅是按钮,swing包内其他我们熟悉的组件,账号输入框、密码输入框等元素,也还是存在。事实上,每一个元素、每一个窗体,它都有一个重绘方法。当窗体改变大小的时候,生成新窗体后,计算机会调用这个重绘方法,所以你看到按钮等元素在改变界面后仍然在界面上。那么,如何让我们自行绘制的图形也像按钮一样,不会随着改变窗体而消失呢?

    事实上,我们只需要重写一下画图界面上的重绘方法。这也就是为什么我要继承JFrame这个类的原因。因为继承了JFrame,所以,我们可以重写它继承的paint方法,在其中加上我们所绘制的内容,那么在窗体重绘的过程当中,我们所绘制的内容也就重新绘制上去了。

    这只不过是重绘的第一步。因为我们绘制的内容有可能过于复杂,那么我们在主类里面如何去得知我们绘制了什么呢?我们可以定义一个shape类,然后在事件处理类里面定义一个shape类型的数组,每画一个图,那么,我们就用数组将它存储下来,然后让index++。为了简化paint方法里的内容,我们可以定义一个shape抽象类,里面定义一个抽象方法draw,然后申明不同图形,让它们都继承shape类,并且重写draw方法。这样,在paint方法里,我们就可以直接调用draw方法,而不用去写各种判断语句。这样做简化了我们的代码。

代码具体实现如下:

 

 

 

这里只给出shapeLine这个类的定义,关于其他类型的图案的定义就没有一一给出了,让看客自行发散。

5、进行界面的美化

    假设我们把所有的按钮都如此加上,那么,我们会发现,画图界面会非常的不美观。为了增强界面的美观程度,我们可以通过引进panel的方法。我们可以将画基本图形的按钮放在一块面板内,颜色按钮放在一块面板里,而铅笔等功能又放到一块面板里。同时为了区分每个界面,我们还可以在重绘方法里,编写这样的语句g.drawLine来给界面加上边框。

    完成程序,具备想要的功能只是第一步。之后我们需要做的就是去尽量让我们的界面美观,并且,一些能进行缩减的代码尽量缩减,使我们的代码看起来更加的精简干练。

 

三、总结

    一个画板,说简单也简单,说复杂也复杂。以后我们打的程序肯定会越来越复杂,我们需要更加严谨,最好是加上一定的注释(当然我个人写代码是不喜欢写注释的,可能也是因为写的少的原因)。画板谈的比较粗糙,欢迎各位大神指正。

 

 

 

    

 

转载于:https://www.cnblogs.com/PHBlog/p/6021511.html

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 画板UI设计(总体布局) (1)创建窗体并设置相关属性; (2)给整个窗体添加一个中间容器用来覆盖整个窗体; (3)设置边框布局,因为整个画板大致为左边部分,中间部分,菜单栏三个部分,用边框布局比较合适; (4)给窗体添加左面板,中间面板; (5)给左面板添加按钮,并设置按钮图片和效果; (6)给左面板添加左子面板,用来存放颜色按钮; 2.画板功能设计 (1)给左画板中的按钮组中的每个按钮添加鼠标监听器; (2)点击不同按钮,绘制不同的图形; (3)给左子面板中的每个颜色按钮添加鼠标监听器; (4)根据下面板中选中的颜色按钮,来获取按钮的背景颜色,并将该颜色设置成画笔的颜色; (5)铅笔功能 1、铅笔是鼠标拖动时画的线,所需要实现鼠标移动监听器,我们采用一个类来实现多个接口; 2、添加新的鼠标监听器类; 3、在鼠标移动时间中实现画笔的逻辑(其实就是绘制直线,鼠标每移动一个像素,就会触发移动事件,通过移动事件获取鼠标的坐标,与上一次移动的坐标连线就可以了; (6)刷子功能 刷子其实就是加粗的画笔,画出来的直线更粗,这里需要用到Graphic2D画笔来设置画笔的粗细。 (7)橡皮擦功能 橡皮擦就是把画笔颜色设置成相同的背景颜色就可以了,拖动鼠标时进行擦除,所以在鼠标拖动事件中编写。 (8)喷桶功能 1、定位方法:鼠标拖动事件实现; 2、随机数生成:Random; 3、实现原理,在鼠标拖动附近绘制很多的原点; 3. 画板的保存和重绘的设计 (1)给我们的画板添加菜单条、菜单以及菜单项 (2)给每个菜单项添加监听器 (3)点击不同的菜单项实现相应的功能 (4)图形保存功能:利用对象输出流,将容器对象写入文件; (5)打开图形功能:利用对象输入流,将容器对象读入,然后将容器里面的图形对象在画板上绘制出来 (6)新建文件功能:新建文件,将画板上绘制的内容清空(清空之前可以确认是否需要进行保存)清屏(重绘)功能依次方法; (7)文件保存格式为BMP格式; (8)文字功能:读取文本框中的文本并打印到屏幕鼠标的相应的响应位置,传入输入的文字大小的参数,以此来改变文字的大小; 4.弹泡泡功能的设计 根据Java多线程来实现弹泡泡功能;泡泡的位置颜色随机出现,并且做到碰到边框会变色;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值