现在的位置: 首页 > 综合 > 正文

JAVA2D Shape 高级

2018年03月23日 ⁄ 综合 ⁄ 共 7665字 ⁄ 字号 评论关闭

除了内置的形状类的能力之外,Java 2D 还具有通过组合 Shape 对象来构造复杂形状的能力。这一功能称为构造型区域几何 或 CAG。

Shape 接口的特殊实现,即 java.awt.geom.Area 类,在 Shape 类上执行各种二进制操作。

有四种组合操作:

  • add():组合两个形状。它不必有任何共同区域。
  • subtract():除去指定区域。
  • intersect():创建一个只含有源区域和目标区域共有空间的新的形状。
  • exclusiveOr():从两个形状中除去重叠区域。

上述操作创建一个新 Area,它是源对象和指定的目标对象组合的结果。源对象可以在 Area 对象的构造器中指定。因为 Area 本身就是 Shape,所以可以组合任意复杂的形状。

 

 

 

 

请记住,渲染引擎必须处理的段的数目随形状的复杂而上升,从而会降低性能。

 

缓冲的图像 第 2 页(共5 页)

 

类似于 Graphics2D 继承 Graphics 的方式,java.awt.image.BufferedImage 通过在 Java 2D API 中提供一组强大的功能替换了 AWT Image 类。BufferedImageImage 的继承,因此它同 Java 2D 以前的代码完全兼容。JDK 1.2 的实现规定:图形系统返回的任何 Image 对象都是 BufferedImage,这与所有的图形环境实际上都是 Graphics2D 实例很相象。

Image 只可通过获取图形环境然后在其上着色来进行修改,而 BufferedImageImage 不同,它提供对底层图像数据的直接访问。BufferedImage 还提供通过称为过滤的过程来进行修改,这一过程在图像上提供了类似于高级图像编辑软件中找到的那些操作。

BufferedImage 进行了特殊设计以支持 Java 高级图像 API,它支持多色模式和光栅格式。

 

从图像创建缓冲图像 第 3 页(共5 页)

 

 

变换是一组操作,它们基于对图形元素执行各种修改的矩阵算术。要使用这些能力并不一定要理解线性代数;java.awt.geom.AffineTransform 类封装了所有可用操作。可以将变换应用于 ShapeFontBufferedImage,也可以将它直接应用于图形环境。

变换可以提供几种操作,这些操作可以结合起来使用。

  • 平移:改变图形的原点或 (x,y) 坐标。图形在 2D 坐标空间内移动,但外观不改变。
  • 旋转:在坐标空间内以通过原点(缺省)或任何指定坐标的轴为轴线转动图形。
  • 缩放:按照维护图像的需要添加或减弱像素,从而改变图形的大小。缩放可以是成比例的也可以是不成比例的,如果为 X 轴和 Y 轴分别给予不同的缩放值,那就是不成比例的。如果缩放值大于 1,那么缩放会增加每个轴的大小,如果缩放值小于 1,那么缩放会收缩每个轴的大小。负缩放值会沿对应的轴翻转图形。
  • 扭曲:滑动线的像素使它们不再沿一个轴排列。斜体字符可以被认为是扭曲了的正常字符。

正如您能想象到的那样,变换是不可交换的。也就是,如果以不同顺序应用一组变换操作,那么它们可能会产生不同的结果。很显然,如果您按照某人的吩咐“转九十度再向北走三步”与您“向北走三步再转九十度”所到达的地方将不一样。

 

下面的代码获取一个 Image 类型的对象并将其转换为一个 BufferedImage 实例:


public static BufferedImage createBufferedImage(Image image) 
{
    // Create the buffered image.
    BufferedImage bufferedImage = 
                  new BufferedImage(image.getWidth(null), 
                  image.getHeight(null), BufferedImage.TYPE_INT_RGB);                    
    
	// The fill operation will expand the buffer to accommodate
	// the copy of the image
    Graphics g = bufferedImage.createGraphics();
    g.setColor(Color.white);
    g.fillRect(0, 0, image.getWidth(null), 
    		           image.getHeight(null)); 

    // Copy image to buffered image and return        
    g.drawImage(image, 0, 0, null);
    g.dispose();
    return bufferedImage;
}

构造型区域几何 第 1 页(共5 页)

 

 

 

 

示例:模拟时钟 第 5 页(共5 页)

下面是一个使用 GeneralPathAffineTransform 类来创建实时模拟时钟的示例类。

 

 

 

package com.zelator.clock2d;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.Calendar;
import javax.swing.*;

public class Clock2DPanel extends JPanel implements ActionListener
{
    // Create a shape for the face of the clock
    protected static Ellipse2D face = new Ellipse2D.Float(3, 3, 94, 94);

    // Create a path that represents a tick mark
    protected static GeneralPath tick = new GeneralPath();
    static
    {
        tick.moveTo(100, 100);
        tick.moveTo(49, 0);
        tick.lineTo(51, 0);
        tick.lineTo(51, 6);
        tick.lineTo(49, 6);
        tick.lineTo(49, 0);
    }

    // Create a cool hour hand
    protected static GeneralPath hourHand = new GeneralPath();
    static
    {
        hourHand.moveTo(50, 15);
        hourHand.lineTo(53, 50);
        hourHand.lineTo(50, 53);
        hourHand.lineTo(47, 50);
        hourHand.lineTo(50, 15);
    }

    // Create a cool minute hand
    protected static GeneralPath minuteHand = new GeneralPath();
    static
    {
        minuteHand.moveTo(50, 2);
        minuteHand.lineTo(53, 50);
        minuteHand.lineTo(50, 58);
        minuteHand.lineTo(47, 50);
        minuteHand.lineTo(50, 2);
    }

// And a cool second hand
    protected static GeneralPath secondHand = new GeneralPath();
    static
    {
        secondHand.moveTo(49, 5);
        secondHand.lineTo(51, 5);
        secondHand.lineTo(51, 62);
        secondHand.lineTo(49, 62);
        secondHand.lineTo(49, 5);
    }

// Create some colors for the pieces of the clock
    protected static Color faceColor = new Color(220, 220, 220);
    protected static Color hourColor = Color.red.darker();
    protected static Color minuteColor = Color.blue.darker();
    protected static Color secondColor = new Color(180, 180, 0);
    protected static Color pinColor = Color.gray.brighter();

    // Create circles for the pivot and center pin
    protected Ellipse2D pivot = new Ellipse2D.Float(47, 47, 6, 6);
    protected Ellipse2D centerPin = new Ellipse2D.Float(49, 49, 2, 2);

   
    // Create three transforms that center around the pivot point
    protected AffineTransform hourTransform =
                    AffineTransform.getRotateInstance(0, 50, 50);
    protected AffineTransform minuteTransform =
                    AffineTransform.getRotateInstance(0, 50, 50);
    protected AffineTransform secondTransform =
                    AffineTransform.getRotateInstance(0, 50, 50);

    // Create a timer that fires once a second and a Calendar
    // instance for getting the time values
    protected Timer timer = new Timer(1000, this);
    protected Calendar calendar = Calendar.getInstance();

    // Constructor - hardcode a preferred size of 100x100
    public Clock2DPanel()
    {
        setPreferredSize(new Dimension(100, 100));
    }

// Invoked when panel is added to a container
    public void addNotify()
    {
// Call the superclass and start the timer
        super.addNotify();
        timer.start();
    }

// Invoked when panel is removed from a container
    public void removeNotify()
    {
// Call the superclass and stop the timer
        timer.stop();
        super.removeNotify();
    }

    //
    public void actionPerformed(ActionEvent event)
    {
        // Update the calendar's time
        this.calendar.setTime(new java.util.Date());
       
        // Extract the hours minutes and seconds
        int hours = this.calendar.get(Calendar.HOUR);
        int minutes = this.calendar.get(Calendar.MINUTE);
        int seconds = this.calendar.get(Calendar.SECOND);
       
        // Using a little trigonometry, set the transforms to rotate
        // each hand into the proper position.  Center the rotation
        // around the pivot point (50, 50) instead of the origin
        hourTransform.setToRotation(((double) hours) *
                                            (Math.PI / 6.0), 50, 50);
        minuteTransform.setToRotation(((double) minutes) *
                                            (Math.PI / 30.0), 50, 50);
        secondTransform.setToRotation(((double) seconds) *
                                            (Math.PI / 30.0), 50, 50);
       
        // Force the component to repaint ASAP
        repaint();
    }

    // This is an alternative to creating a UI delegate.  Since JPanel's
    // paint() method only paints the border and backgound, we can just
    // override the paint method of the component to do the graphics.
    public void paint(Graphics g)
    {
        // Call the superclass first to paint the border (if one is assigned)
        super.paint(g);
       
        // Get the graphics context and turn on anti-aliasing
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);

        // Set the paint for the clock face and fill it in
        g2.setPaint(faceColor);
        g2.fill(face);

// Set the paint to black and draw the clock's outline
        g2.setPaint(Color.black);
        g2.draw(face);
       
        // Fill in the 12 ticks around the face of the clock
        for (double p = 0.0; p < 12.0; p += 1.0)
        {
            // This is probably terribly inefficient and should be
            // done statically or in the constructor - draw the
            // tick as a transformed shape that is rotated.
            g2.fill(tick.createTransformedShape(
                AffineTransform.getRotateInstance((Math.PI / 6.0)  * p,
                        50, 50)));
        }

        // Set the paint and draw the hour hand.  It is lowest in the
        // 'z-order' so will appear underneath the other hands.  Notice
        // how each hand is transformed by a different <AffineTransform>.
        g2.setPaint(hourColor);
        g2.fill(hourHand.createTransformedShape(hourTransform));

        // Set the paint and draw the minute hand, the second hand,
        // the pivot and the center pin
        g2.setPaint(minuteColor);
        g2.fill(minuteHand.createTransformedShape(minuteTransform));
        g2.setPaint(secondColor);
        g2.fill(secondHand.createTransformedShape(secondTransform));
        g2.fill(pivot);
        g2.setPaint(pinColor);
        g2.fill(centerPin);
    }

// A little test frame to show off our fancy clock
    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setLocation(700, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new Clock2DPanel());
        frame.pack();
        frame.show();
    }
}

 

【上篇】
【下篇】

抱歉!评论已关闭.