java画图板之平面山水画(一):https://blog.csdn.net/qq_43348021/article/details/104346805
上次的博客中已经将山脉的轮廓画出来了,这次我们对它进行修饰。

填充

刚开始,我以为将区域填充需要将其中每个点都画到,其实不然。我们知道画出的山脉轮廓其实是有若干个点连线组成的,我们只需要从这些点开始,垂直向下划线即可,当点的数量足够多的时候,显示的就是全部被填充的情况。

    public void showmt(double startx, double starty, double endx, double endy, Color mtcolor, double range, double timescounter) {double midx, midy;//计算中点坐标midx = (startx + endx) / 2;midy = (starty + endy) / 2 + (Math.random() * 2 - 1) * range;if (timescounter++ == times) {//画山脉轮廓g.drawLine((int) startx, (int) starty, (int) midx, (int) midy);g.drawLine((int) midx, (int) midy, (int) endx, (int) endy);//填充山脉g.setColor(mtcolor);g.drawLine((int) midx, (int) midy, (int) midx, (int) 600/*画布底部*/);} else {//随着相邻两个点的横坐标距离减少,纵坐标随机起伏范围也要减小range *= rate;//递归showmt(startx, starty, midx, midy, mtcolor, range, timescounter);showmt(midx, midy, endx, endy, mtcolor, range, timescounter);}}
  • 这是递归次数(times)为10时画出的效果:

  • 这是递归次数(times)为11时画出的效果:

群山

只有一座山肯定是不够的,我们用循环来画多做山脉,同时对远近山脉的高低、颜色进行调整,这部分放在监听器中。

   for (int i = 0; i < 4; i++) {int distance = 100;// 每座山脉间距离mountain mountain = new mountain();mountain.setGraphics(bufferg);// 先在缓存中绘制Color mtcolor = new Color(i * 50, i * 50, i * 50);// 设置每座山脉颜色mountain.showmt(0, 50 + i * distance, 800, 50 + i * distance, mtcolor, 100, 1);// showmt(double startx, double starty, double endx, double endy, Color mtcolor, double range, double timescounter)}

提速

实际运行过上面的代码就会知道,递归11次会使得画出图像需要1秒左右的过程,有没有什么办法能使图像在运行的瞬间就显示出来呢?这就需要用到计算机的缓存了,我们可以事先在缓存中画出图形并保存,然后将缓存中的图像显示出来(CPU与缓存间传输信息的速度要大于CPU与输入输出设备的)。
    这样做还有一个好处,由于我们的图像绘制时使用了随机函数,导致我们每次调用函数都会改变图像,当其他构件发生变化时,山脉的图像也在跟着变化。运用缓存后,当其他构件发生变化影响到山脉的图像时,我们只需要将缓存中保存的图片重新显示出来就行了,而不需要重新绘制。
    java提供了BufferedImage类供我们使用。

    //绘制山脉// 设置缓存BufferedImage buffer = new BufferedImage(800, 400, BufferedImage.TYPE_INT_RGB);// 设置缓存画布Graphics bufferg = buffer.getGraphics();// 设置画布背景颜色Color bufferbgcolor = new Color(255,255,255);bufferg.setColor(bufferbgcolor);bufferg.fillRect(0, 0, 800, 400);// 在缓存中绘制山脉for (int i = 0; i < 4; i++) {int distance = 100;// 每座山脉间距离mountain mountain = new mountain();mountain.setGraphics(bufferg);// 先在缓存中绘制Color mtcolor = new Color(i * 50, i * 50, i * 50);// 设置每座山脉颜色mountain.showmt(0, 50 + i * distance, 800, 50 + i * distance, mtcolor, 100, 1);// showmt(double startx, double starty, double endx, double endy, Color mtcolor, double range, double timescounter)}

太阳

有了山脉,我总觉得还少了点什么,为了让图片更加有意境,我加入了太阳这个元素。但是仅仅是画一个太阳很死板,我想让它动起来。

  • 首先,先确定太阳的画法,使用fillOval()函数,需要注意的是里面的参数是圆外接矩形左上角的点的坐标。在画下一个太阳前,需要将前一个太阳擦除,准确的说是覆盖:用与背景相同的颜色,在前一个太阳处画圆。
  • 然后,就是太阳的轨迹:

    我们将轨迹设置为以O为圆心,OA为半径的圆弧,A点的位置可以修改。接着我们设定太阳移动的移动速度sunspeed = 0.5 弧度/次,运动开始相对时间starttime = 35(因为从0开始可能会被挡住,每次运行完+1),我们可以通过三角函数,算出在t时刻P点的坐标(OB - OA* Math.cos(Math.asin(AB/OA) + starttime * sunspeed * PI / 180),600 - 500 * Math.sin(Math.asin(AB/OA) + starttime * sunspeed * PI / 180))
public void showsun() {// 绘制太阳// 清除上一个太阳Color bgcolor = new Color(255, 128, 0);g.setColor(bgcolor);g.fillOval((int) (sunx - sunr), (int) (suny - sunr), (int) sunr, (int) sunr);// 计数starttime++;// 计算新太阳的位置sunx = 400 - 500 * Math.cos(Math.asin(0.6) + starttime * sunspeed * PI / 180);suny = 600 - 500 * Math.sin(Math.asin(0.6) + starttime * sunspeed * PI / 180);// 画出太阳Color suncolor = new Color(255, 0, 0);g.setColor(suncolor);g.fillOval((int) (sunx - sunr), (int) (suny - sunr), (int) sunr, (int) sunr);// 在主画布上画出缓存画布g.drawImage(buffer, 0, 200, null);}
  • 最后,我们加入线程休眠,让这段程序每100ms运行一次
    while (sun.sunx <= 700) {// 设置截止条件// 计时try {Thread.sleep(100); // 设置精度} catch (InterruptedException ex) {Logger.getLogger(sun.class.getName()).log(Level.SEVERE, null, ex);}// 画出太阳和山脉sun.showsun();}

但是,这里面还有一个问题,就是太阳没有运行完,程序就不能执行其他的任务,这需要用到多线程和高并发的相关知识了,我会将这一部分放到聊天室搭建的博客中。

运行结果

结果是一个动图,但是我不知道怎么做gif。虽然可能没有想象中的美观但是关键是技术与思想的掌握和今后的运用。

附录(源代码)

background类

package plain;import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;public class background {public void showbg() {JFrame bg = new JFrame();// 设置窗体基本属性bg.setTitle("地球平原");bg.setSize(800, 600);bg.setLocationRelativeTo(null);// 窗体关闭时结束程序bg.setDefaultCloseOperation(bg.EXIT_ON_CLOSE);// 设置背景颜色,直接设置没有用,需要用Panel组件Color bgcolor = new Color(255, 128, 0);//Color bgcolor = new Color(255, 255, 255);bg.getContentPane().setBackground(bgcolor);// 设置布局,放在可见前才显示FlowLayout flow = new FlowLayout();bg.setLayout(flow);// 设置可见,并获取画布对象bg.setVisible(true);Graphics g = bg.getGraphics();// 设置鼠标监听器MouseListener mouselistener = new MouseListener();bg.addMouseListener(mouselistener);mouselistener.setGraphics(g);}public static void main(String args[]) {background bg = new background();bg.showbg();}
}

MouseListener类

package plain;import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;import javax.swing.JFrame;import three_dimention.Pad;public class MouseListener implements java.awt.event.MouseListener, ActionListener {Graphics g;public void setGraphics(Graphics g) {this.g = g;}public void mouseClicked(MouseEvent e) {//绘制山脉// 设置缓存BufferedImage buffer = new BufferedImage(800, 400, BufferedImage.TYPE_INT_RGB);// 设置缓存画布Graphics bufferg = buffer.getGraphics();// 设置画布背景颜色Color bufferbgcolor = new Color(255, 128, 0);bufferg.setColor(bufferbgcolor);bufferg.fillRect(0, 0, 800, 400);// 在缓存中绘制山脉for (int i = 0; i < 4; i++) {int distance = 100;// 每座山脉间距离mountain mountain = new mountain();mountain.setGraphics(bufferg);// 先在缓存中绘制Color mtcolor = new Color(i * 50, i * 50, i * 50);// 设置每座山脉颜色mountain.showmt(0, 50 + i * distance, 800, 50 + i * distance, mtcolor, 100, 1);// showmt(double startx, double starty, double endx, double endy, Color mtcolor, double range, double timescounter)}//绘制太阳sun sun = new sun();sun.setGraphics(g);sun.setBuffer(buffer);while (sun.sunx <= 700) {// 设置截止条件// 计时try {Thread.sleep(100); // 设置精度} catch (InterruptedException ex) {Logger.getLogger(sun.class.getName()).log(Level.SEVERE, null, ex);}// 画出太阳和山脉sun.showsun();}}public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e) {}public void mouseExited(MouseEvent e) {}public void actionPerformed(ActionEvent e) {}}

mountain类

package plain;import java.awt.Color;
import java.awt.Graphics;public class mountain {double rate = 0.5, times = 11;//times>10Boolean whe_left = true;Graphics g;public void setGraphics(Graphics bufferg) {this.g = bufferg;}public void showmt(double startx, double starty, double endx, double endy, Color mtcolor, double range, double timescounter) {double midx, midy;//计算中点坐标midx = (startx + endx) / 2;midy = (starty + endy) / 2 + (Math.random() * 2 - 1) * range;if (timescounter++ == times) {//画山脉轮廓g.drawLine((int) startx, (int) starty, (int) midx, (int) midy);g.drawLine((int) midx, (int) midy, (int) endx, (int) endy);//填充山脉g.setColor(mtcolor);g.drawLine((int) midx, (int) midy, (int) midx, (int) 600/*画布底部*/);} else {//随着相邻两个点的横坐标距离减少,纵坐标随机起伏范围也要减小range *= rate;//递归showmt(startx, starty, midx, midy, mtcolor, range, timescounter);showmt(midx, midy, endx, endy, mtcolor, range, timescounter);}}
}

sun类

package plain;import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;import javax.swing.JFrame;public class sun {Graphics g;// 主画布double sunspeed = 0.5;// 太阳移动速度double PI = 3.14;// πdouble sunx = 0, suny = 300, sunr = 80;// 起始位置、太阳直径double starttime = 35;// 运动开始的时间BufferedImage buffer;public void setGraphics(Graphics g) {this.g = g;}public void setBuffer(BufferedImage buffer) {this.buffer = buffer;}public void showsun() {// 绘制太阳// 清除上一个太阳Color bgcolor = new Color(255, 128, 0);g.setColor(bgcolor);g.fillOval((int) (sunx - sunr), (int) (suny - sunr), (int) sunr, (int) sunr);// 计数starttime++;// 计算新太阳的位置sunx = 400 - 500 * Math.cos(Math.asin(0.6) + starttime * sunspeed * PI / 180);suny = 600 - 500 * Math.sin(Math.asin(0.6) + starttime * sunspeed * PI / 180);// 画出太阳Color suncolor = new Color(255, 0, 0);g.setColor(suncolor);g.fillOval((int) (sunx - sunr), (int) (suny - sunr), (int) sunr, (int) sunr);// 在主画布上画出缓存画布g.drawImage(buffer, 0, 200, null);}
}

java画图板之平面山水画(二)相关推荐

  1. java画图板之平面山水画(一)

    前期准备 在上次的博客中,我们已经用java了解并制作了画图板,可以在上面添加绘制椭圆.曲线.填充.改变颜色等功能,在之后的版本中会进行修改.     今天要做的是通过递归的方式绘制山脉. 具体步骤 ...

  2. JAVA画图板01 —— 窗体的实现

    画图板 界面开发: 创建窗体对象 完善界面 个人将自制的JAVA画图板分为了三个模块,分别是界面.监听器以及画笔,这一章来介绍界面的相关代码. 界面开发: 创建窗体对象 首先需要创建一个窗体对象.JF ...

  3. 一个Java画图板程序的设计

    本文讲述一个画图板应用程序的设计,屏幕抓图如下.这篇文章带有三个附件,其中两个jar文件都是j2sdk1.4.2_08编译打包,包含源代码,可执行,如下表: 附件名称及链接 详情 jDraw_basi ...

  4. java画图板代码_java学习小总结——画图板制做(附代码)

    学习java这门编程语言也有一个多月了.~若是能用本身学的编程语言去开发一些小程序软件能够说是本身一直求之不得吧!.模仿XP的画图板的开发则是学java来最先作的一个小软件.也是把以前学到的不少知识得 ...

  5. Java 画图板用随机数搞“混沌游戏”

    今晚做了这样的一个任务:用随机数在画图板里面生成四个点,然后选出其中的三个点组成一个三角形,把三角形的三个顶点标为1.2.3,另一个点标为4,把4点随机与1.2.3三个点中一个点进行连接,取连线的中点 ...

  6. Java画图板界面上的添加

    步骤 1.创建类来实现接口(动作监听器和鼠标监听器) 2.在按钮上添加动作监听器,通过e.getActioncommand(),来得到按钮上的字,通过button =(JButton)e.getAct ...

  7. Java画图板的简单实现。(重绘,多边形,曲线画笔,画图片)

    思路: ①画图板的界面 ②创建监听器类 ③给按钮加上鼠标监听 ③画图版的重绘 第一部分:界面类 ①画图板的界面 ③给按钮加上鼠标监听 public class SampleDraw extends J ...

  8. java 画图板源代码_非常值得学习的java 绘图板源代码

    package minidrawpad; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; impor ...

  9. java 画图板 锯齿_java绘画中的锯齿问题

    java给图中的锯齿问题也称作呈现兼容性问题 JDK(tm)1.1呈现模型是基于像素给的模型,该模型的坐标无限细分,且位于像素之间.使用一个一像素宽的画笔执行绘制操作,填充路径锚点向下和向右的像素.J ...

最新文章

  1. Nimbus/Supervisor本地目录结构
  2. big sur卡第二阶段无限重启_2019百大球员第67:克林特卡佩拉,一张饼一辈子
  3. 数据库基础知识——DDL语言
  4. Java 语言 ArrayList 和 JSONArray 相互转换
  5. Flex 中使用 FileReference 的 download 方法下载文件时的缓存刷新问题
  6. Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用
  7. 1.2.1 Milking Cows 挤牛奶
  8. 令人困惑的strtotime
  9. Tomcat运行原理
  10. 08服务器端口映射,windows_Server_2008_R2_NAT服务器_端口映射.pdf
  11. 安卓基于图像识别和CNN做出一个通用的斗地主记牌器(一)
  12. SharedPreferences牛刀小试
  13. 李维看 .net 和 DELPHI 6 (含李维照片) (转)
  14. 分水岭 matlab代码,分水岭算法MATLAB编程代码解析
  15. 如何将华氏转换为摄氏
  16. 降本提效!注册中心在蚂蚁集团的蜕变之路
  17. 【20保研】暨南大学关于举办2019年优秀大学生暑期学术夏令营活动的公告
  18. 联发科6758_联发科MT6758
  19. java实现从url路径中下载pdf文档到本地
  20. U盘出现RAW问题时的数据恢复

热门文章

  1. Hey 朋友们好久不见。
  2. Quartz配置资源介绍
  3. 如何卸载Visio秘钥
  4. NoSQL数据库简单学习
  5. 区块链技术运用在票据领域-票据链
  6. 分享20个无版权的高清无 码图库站
  7. c语言猜单词游戏实验报告,猜单词游戏c语言源程序.doc
  8. 机器学习(19)之支持向量回归机
  9. 凯迪拉克5月软文-V设计
  10. Markdown写接口文档,自动添加TOC