用Java写一个画图工具

一、创建窗体

首先,我们需要建立一个类,并在类里创建窗体,在窗体里添加按钮与监听器等功能

1.设置窗体的基本属性

首先建立一个JFrame类(Java中写好的类)的对象jf,并设置一下窗体的基本属性

 如上图所示,setSize函数用于设置窗体的大小,setTitle函数用于给窗体进行命名,setLocationRelativeTo函数用于给窗体进行居中展示,最后,setDefaultCloseOperation函数是为了让我们按窗体的关闭按钮时,系统能退出运行,而不是保持继续运行的状态。传递的参数3就达到按关闭按钮就退出的效果。我们具体可以按Ctrl进入这个函数,发现JFrame类继承了WindowContants这个接口,按Ctrl查此接口,发现如下:

 所有我们发现3这个常数就代表了EXIT_ON_CLOSE这个量,也就是关闭窗体即退出程序的效果

创建完窗体,我们就要进行窗体的排版布局。因为我们要有一栏是专门存放功能按钮的,剩下来的窗体用于画图。故在这里我们使用边界布局排版,即给窗体设置一个BorderLayout的排版,再建立一个容器,即面板对象,并将面板对象放在jf窗体的最北边(即最上方,宽度默认是窗体长度,无法修改,故传参随意),并设置一些属性,最后将此面板对象添加到窗体上。

 以上代码将面板对象northPanel的背景色设置为蓝色以示区分,并设置其高度(如果不设置高度,高度会很矮)。其中Dimension是一个类(Java自带),其源码如下,用于设置面板对象高度

 到这里我们的窗体就完成的差不多了。

二、添加功能按钮

Java里有个JButton类,我们可以给每个功能创建一个按钮。可以通过以下方法依次创建,并添加到刚刚创建的面板对象,最后注意要设置窗体可见(这很重要,为了后面获取画笔做准备工作)。

 最后我们可以运行一下,能得到以下效果图

三、给窗体添加动作监听器,给按钮添加鼠标监听器

这个部分较为简单,我们只需用addMouseListenr方法给窗体添加动作监听器,再给每个按钮添加动作监听器,同时为了画曲线,给鼠标也要添加一个拖拽监听器。这里也要获取下画笔对象,为了后续画图使用,窗体的画笔要传入Button类中,因为Button类中会涉及图形绘画,所以我们可以通过构造方法将窗体画笔传入。最后一个setShapeArr方法用于图形重绘,后续会说到

四、画直线,矩形,三角形,多边形,曲线,设置画笔颜色

前言:我们在每次画图时,每个图形都有一个对应的列表,即ArrayList类,直线的列表里面存了四个元素,分别为x1,y1,x2,y2,根据这两点的坐标即可复现直线。同理,矩形对应的列表也有四个元素,三角形对应的列表有六个元素(3个坐标),而多边形和曲线就有很多坐标。

以下是一些要设置的量与构造函数。

 接下来我们实现画图功能,我们鼠标监听器的监听按照:按下->松开->点击 这个顺序

直线:在第一次点击时,获得点击坐标,然后移动鼠标松开到终点。获得终点坐标即可将两点相连

矩形:在第一次点击时,获得点击坐标,然后移动鼠标到终点,会画出以起点与终点为对角线的矩形,其中矩形以第一次点击时的坐标为顶点画出

三角形:在第一次点击时,获得点击坐标,然后移动鼠标到终点,画出三角形的一条边,再任意点击一点,该点与前面边的起终点相连,最后得到一个三角形

多边形:在第一次点击时,获得点击坐标,然后移动鼠标到终点,画出多边形的一条边,再任意点一个点,该点会与前面的边的终点相连,双击的点会与起点与上一个点相连,完成作图

曲线:按下的点即为起点,然后拖拽鼠标即可画图,松开为止

在画图中要解决的核心问题是:要将每一个图的坐标能不重复地按顺序依次保存好,于是我们这样处理:

 有了这个if语句,因为点击时,x1,y1,x2,y2都是同一个坐标,故这样能防止同一个坐标入列表两次,从而将点击的点在每个按钮对应的情况下保存处理。

对于矩形有个特殊处理,为了保持矩形为起点贴切,我们要保证它的横坐标是两个点里最小的,纵坐标同理,再利用Math类里的abs方法计算长与宽

 接下来就可以根据坐标来画图了,其中直线与矩形是最好画的,三角形与多边形的需要单独处理,这里创建了一个Shape类,传入列表与图形名,为了解决paint()自动调用重绘覆盖的问题,最后创建完要将列表清空,方便下一次使用。

 因为三角形和多边形是需要通过点击相连的,故再mouseClicked方法里实现。三角形的坐标获得后将其入列表,创建对应Shape类保存起来,再进行连接,记得清空列表就行。多边形的保存与连接同理。只需注意搭配列表长度的用法通过索引获取元素即可。

 曲线我们通过不断更新即可,这里要把每个坐标存到list里进行复现,作者这里忘保存到列表里了,只实现了画的功能,每保存,相信读者也能按照以上思路进行实现。

最后我们测试一下:

 基本实现,但一旦我们改变拉伸窗体或者隐藏再打开,会发现所有的图都没了,因为改变窗体状态,在绘制式会自动调用paint()方法重绘窗体,导致之前画的内容全部消失

五、解决窗体变化导致画的图丢失的问题

所有我们只需要在paint方法里添加重绘的功能即可。首先我们完成下Shape类,可以看到我们在构造函数中传入列表与图形名,我们根据图形名,就可以根据列表有顺序地重绘图形

 复现图形的函数在这,只需要注意搭配索引和循环就可以轻松地实现图形复现

 曲线重绘的功能并不完整,读者可以根据以上思路将曲线图形的列表获得即可。最后我们在paint方法里续写重绘功能即可

因为我们调用的是窗体的画笔,而窗体时JFrame类,故我们写个类继承它,通过方法重载来重写paint方法即可

我们传入存入图形的数组,在paint方法里保留父类的paint方法,再续写即可。我们遍历数组,然后因为我们已经在Shape类中完成了画图功能,故我们只需要给数组里的每个元素调用该方法即可。最后就可以实现重绘。最后要将jf从 JFram类改为MFrame类即可。

我们测试一下: 

 可以明显发现,我们调整了窗体的大小,之前画的图也没有消失,所以我们粗略地实现了此功能。而图形的粗细和颜色也可以实现保存(提示:保存到Shape类中的属性即可),有兴趣的读者可以自己实现。

到这里,一个简单的画图工具就实现了,感谢各位读者的阅读。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值