Simplifying Graphics With Java and Threads

原创 2001年10月22日 16:25:00

Simplifying Graphics With Java and Threads

By Alex Chaffee and John Papageorge
July 1997

<!-- Begin Main Body Text -->

Here's some code that EarthWeb's Alex Chaffee likes to use as an example of how Java can be used to simplify algorithms by combining graphics with threading to render complex graphics.

Basically there are three threads: a Renderer, which performs a complex calculation; an Animator, which wakes up periodically and draws the current image to the screen; and of course the default User Interface thread, which responds to user events and changes the display as appropriate.

The Renderer runs at a low priority—just grinding away forever, or at least until it's done; it shouldn't interfere with the other two threads. The Animator only comes to life every 500 msec or so, to avoid the expense of drawing each pixel.

To perform a specific calculation, subclass the Renderer to make a Mandelbrot function. Note the object-oriented design: this way, the Mandelbrot subclass only needs to override the Run method and doesn't have to worry about the threading implementation, which is handled by its superclass. Of course, in this example, the threading implementation is trivial, but this is a teaching exercise.

Other items of note are the use of an offscreen Graphics buffer, and the use of progressive rendering. The code makes several rough passes over the image, calculating the value in each quadrant, then gradually refines the view. Unlike Netscape's rendering of progressive gifs, this program treats a calculated pixel as the "center" of a square of color, not as the top corner or a pixel-wide stripe, and so avoids that odd venetian-blind scrolling-up effect. With a laugh, Chaffee says, "But maybe I'm the only one in the world who thought Netscape's gif-rendering algorithm looked funny." now , see Chaffee's source code

/* man.java a test to do threaded animation Copyright (c) 1996 Alex Chaffee, all rights reserved Permission is granted to use this source code for instructional purposes as long as copyright information remains intact. @Author: Alex Chaffee */ import java.awt.*; import java.util.*; import java.applet.*; import java.lang.Math; /** * Animator * This class implements the thread that draws the image to the screen * every 500 msec. * @author Alex Chaffee **/ class Animator implements Runnable { static int delay = 500; private Applet applet; private Vector images; private Thread thread = null; private int frame; public Animator(Applet appletIn, Vector imagesIn) { applet = appletIn; images = imagesIn; } public void start() { if (thread == null) { thread = new Thread(this); thread.start(); } } public void stop() { System.out.println("Animator stopped"); thread.stop(); thread = null; } public void run() { thread.setPriority(Thread.MAX_PRIORITY-1); while (thread != null) { applet.repaint(); try { thread.sleep(delay); } catch (InterruptedException e) {}; // Increment frame // Must use synchronized on the off chance that update gets called // between the frame++ and the frame=0 synchronized (this) { frame++; if (frame > images.size()) { frame = 0; } } } } public void paint(Graphics g) { if (frame < images.size()) { Image image = (Image)images.elementAt(frame); if (image != null) { g.drawImage(image, 0, 0, null); // try it without an ImageObserver } } } } /** * Renderer * This class progressively renders the image **/ class Renderer implements Runnable { protected Image image; protected Thread thread = null; protected int delay = 50; static int count = 0; public Renderer(Image imageIn) { image = imageIn; } public void start() { if (thread == null) { thread = new Thread(this, "Renderer " + count++); thread.setPriority(Thread.MIN_PRIORITY+1); thread.start(); } } public void stop() { System.out.println("Renderer stopped"); thread.stop(); thread = null; } public void setDelay(int delay) { this.delay = delay; } public void run() {} } /** Subclasses Renderer in order to implement a Mandelbrot function **/ class Mandelbrot extends Renderer { /** * zoom constant */ protected static float kZoom = (float)1.3; /** * Magnification of the image -- mag 0 = full span of 4 (-2 to +2) * span = 4 / (K^mag) * @see kZoom */ int mag; /** * point in virtual space around which we're drawing the thing * (i.e. where in virtual space is (0,0) in the window */ float originX = 0; float originY = 0; public Mandelbrot(Image image, int mag, float originX, float originY) { super(image); this.mag = mag; this.originX = originX; this.originY = originY; } static float MagToSpan(int mag) { return 4 / (float)(java.lang.Math.pow(kZoom, mag)); } /** * Render this image progressively. */ public void run() { /** * The graphics port of the image we're drawing to */ Graphics g; g = image.getGraphics(); int width, height; width = image.getWidth(null); height = image.getHeight(null); /** * The width of the window on the virtual space * @see mag */ float span = MagToSpan(mag); /** * current resolution (how big each pixel is) */ int resolution; /** * how far in do we go before we're rendering by pixel */ int resolutionMax = 10; // should calculate based on image size /** * current increment (based on resolution) */ float inc; resolution = 1; int widthPixel, heightPixel; do { // the resolution determines which power of two we're dividing // the span by -- so it fills in by squares float scale = 1 / (float)(java.lang.Math.pow(2, resolution)); inc = span * scale; // pre-calculate the width and height of each "pixel" in the image widthPixel = (int)(scale * width) + 1; heightPixel = (int)(scale * height) + 1; spew("resolution " + resolution + " pixel=(" + widthPixel + ", " + heightPixel + ")"); // Mandelbrot function Color c; int maxiterations = 100; int i; float temp, r, x, y; float minX = originX + inc/2; float maxX = originX + span; float minY = originY + inc/2; float maxY = originY + span; for (float c1= minX; c1 < maxX; c1 += inc) { for (float c2 = minY; c2 < maxY; c2 += inc) { // Nitty gritty, merci Benoit r = 0; x = 0; y = 0; i = 0; while ((i 1 || heightPixel > 1); spew("stopped"); } // method run void spew(String str) { System.out.println("(" + originX + "," + originY + ")x" + mag + ":" + str); } public static int iterate(float c1, float c2) { int maxiterations = 100; // Nitty gritty, merci Benoit float r, x, y, temp; int i; r = 0; x = 0; y = 0; i = 0; while ((i0) zoom(mag-1); return true; default: return false; } // switch } // keyDown void zoom(int magNew) { float spanOld = Mandelbrot.MagToSpan(mag); float centerX = originX + spanOld/2; float centerY = originY + spanOld/2; mag = magNew; float spanNew = Mandelbrot.MagToSpan(mag); originX = centerX - spanNew/2; originY = centerY - spanNew/2; stopThreads(); startThreads(); } public boolean mouseDown(Event evt, int x, int y) { System.out.println(evt.toString()); stopThreads(); animator = null; float span = Mandelbrot.MagToSpan(mag); originX = x * span / size().width + originX - span/2; originY = y * span / size().height + originY - span/2; System.out.println("New origin: " + x + (new Dimension(x,y)).toString() + " -> " + originX + "," + originY ); start(); return true; } static float convert(int x, int width, int mag, float origin) { float span = Mandelbrot.MagToSpan(mag); float z = x * span/width + origin; return z; } public boolean mouseMove(Event evt, int x, int y) { float vx = convert(x, size().width, mag, originX); float vy = convert(y, size().height, mag, originY); int i = Mandelbrot.iterate(vx, vy); String str = "i=" + (new Integer(i)).toString(); str = str + " (" + vx + ", " + vy + ")"; getAppletContext().showStatus(str); // System.out.println((new Integer(i)).toString()); return true; } }

Java Graphics类的绘图方法

Graphics类提供基本绘图方法,Graphics类提供基本的几何图形绘制方法,主要有:画线段、画矩形、画圆、画带颜色的图形、画椭圆、画圆弧、画多边形、画字符串等。画线段在窗口中画一条线段,可以使用...
  • zhliro
  • zhliro
  • 2015年05月07日 17:40
  • 4781

使用Java的Graphics类进行绘图的方法详解

Graphics类提供基本绘图方法,Graphics2D类提供更强大的绘图能力。本节讲解Graphics类,下节讲解Graphics2D。 Graphics类提供基本的几何图形绘制方法,主要有:画线...
  • Vision_Tung
  • Vision_Tung
  • 2016年10月17日 20:46
  • 505

java画图总结之二(常用类Graphics,JFrame,JPanel)

二,常用类 Graphics,JFrame,JPanel     理清一下,画图要用的类,和之间的关系。...
  • tanjun592
  • tanjun592
  • 2017年02月08日 13:21
  • 1323

java Graphics2D 使线条更平滑

java使Graphics2D绘制的线条更加平滑好看
  • bbzz9394
  • bbzz9394
  • 2017年03月28日 15:12
  • 572

java图形界面基础之画图(使用Graphics类从画图形到图片到gif)

前几天,使用Graphics类画笔时,发现了许多有趣的现象,用for循环实现颜色和形状的渐变;此外,还发现了在JFrame中画动态图的方法。 下面是画图的效果:     用for循环画的gif图...
  • u010376380
  • u010376380
  • 2015年06月14日 22:33
  • 2289

如何实例化Graphics对象

一、创建Graphics对象 要绘制图像,首先要创建Graphics对象,然后才可以使用GDI+绘制线条和形状,呈现文本或显示与操作图像。Graphics对象是GDI+的绘图表面,是用于创建图形图像...
  • yulongguiziyao
  • yulongguiziyao
  • 2013年08月29日 09:47
  • 2272

Java Graphics类的绘图方法

Graphics类提供基本的几何图形绘制方法,主要有:画线段、画矩形、画圆、画带颜色的图形、画椭圆、画圆弧、画多边形等。 1. 画线 在窗口画一条线段,可以使用Graphics类的drawLi...
  • risingsuncsdn
  • risingsuncsdn
  • 2017年03月24日 09:35
  • 333

Threads 的基本使用方法

POSIX Threads 1.1      Thread基本要素 ž   线程操作包括创、终止、同步(joins,blocking)、调度、数据管理、过程交互。 ž   一个线程不维持一个已创建线...
  • xiaoding133
  • xiaoding133
  • 2013年11月27日 20:32
  • 1587

Java Graphics2D绘制背景透明的图形过程

package com.jhy.time; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt....
  • gingerredjade
  • gingerredjade
  • 2016年11月16日 23:14
  • 4676

通过Graphics对象来实现动画效果

通过Graphics对象来实现动画效果
  • yaerfeng
  • yaerfeng
  • 2014年02月23日 10:43
  • 1537
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Simplifying Graphics With Java and Threads
举报原因:
原因补充:

(最多只允许输入30个字)