java 处理2D图形 及代码

  • Post author:
  • Post category:java


Graphics类包含绘制直线,矩形或者椭圆的方法。但是绘制图形的能力有限,不能改变线的粗细,不能旋转这些图形

Java se 引入了Java 2D库,这个库实现了功能强大的图形操作。

要想使用Java 2D库绘制图形,需要获得一个Graphics2D类对象。这个类是Graphics的子类。自从JavaSE 2版本以来,paintComponent方法就会自动的获得一个Graphics2D类对象,我们只需要进行一次类型转换就可以了

public void paintComponent(Graphics g )
{
    Graphics2D g2=(Graphics2D ) g;
}

java 2D库采用面向对象的方式将几何图形组织起来,包含直线、矩形椭圆类:

Line2D
Rectangle2D
Ellipse2D

Java 2D 支持更加复杂的图形,如圆弧,二次曲线,三次曲线和通用路径。

要想绘制图形,首先要创建一个实现了Shape接口的类的对象。然后调用Graphics2D类中的draw方法。

Rectangle2D rect =...;
g2.draw(rect);

========
draw

public abstract void draw(Shape s)
使用当前 Graphics2D 上下文的设置勾画 Shape 的轮廓。应用的呈现属性包括 Clip、 Transform、 Paint、 Composite 和 Stroke 属性。
参数:
s - 要呈现的 Shape

注释:在Java 2D库出现之前,程序员使用Graphics类中的drawRectangle方法绘制图形。从表面上看,老式风格的方法调用更简单,但是,使用Java2D库,可以选择Java 2D库中提供的一些工具提高绘图能力

有时候程序员处理float不太方便,这是因为java程序设计语言在double值转换为float只是必须进行类型转化(常用的都是double类型)

float f=1.2;   //error  会损失精度
float f=1.2F;

现在看一下这条语句:

Rectangle2D r=new Rectangle2D.Double();
float f=r.getWidth();   //Error
这条语句也无法通过编译,因为getWidth方法返回的类型是double
getWidth
public abstract double getWidth()
返回 double精度框架矩形的宽度。
//正确方法:
float f=(float) r.getWidth();

类型转换有点麻烦,所以2D库的设计者为每一个图形类都设计了两个版本:

类型2D.Double
类型2D.Float
以上两个继承于类型2D
//构造Rectangle2D.Float类对象时,提供左上角坐标以及宽度
Float
public Float(float x,
             float y,
             float w,
             float h)
构造并初始化一个 Rectangle2D从指定的 float坐标。
参数
x - 新构建的左上角的X坐标 Rectangle2D
y - 新构建的左上角的Y坐标 Rectangle2D
w -的新构造的宽度 Rectangle2D
h -的新构造的高度 Rectangle2D
Ractangle2D.Float(1.0F,2.0F,1.0F,2.0F);
Ractangle2D.Double(10.0,25.0,10.0,11.0);
实际上,由于Rectangle2D.Float和Rectangle2D.Double都扩展于Rectangle2D类,并且子类只覆盖了Rectangle2D中的超类方法,所以没有必要记住图形类型是double还是float,可以直接使用Rectangle2D变量保存矩形的引用:
Rectangle2D floatRectangle=new Rectangle2D.Float(...);
Rectangle2D doubleRectangle=new Rectangle2D.Double(...);


也就是说,只有在构造图形对象时,才需要使用内部类,而在引用的时候, 不需要使用内部类


实际上,Rectangle2D.Float包含了一个不是由Rectangle2D继承来的附加方法,setRect(。。。。)。如果将Rectangle2D.Float的引用存储在Rectangle2D的变量中,将失去这个方法,但是,这也没有太大的关系,因为在Rectangle2D中有一个类型为double类型的setRect方法。

setRect
public void setRect(float x,
                    float y,
                    float w,
                    float h)
将此 Rectangle2D的位置和大小设置为指定的 float值。
参数
x - 这个 Rectangle2D左上角的X Rectangle2D
y - 这个 Rectangle2D左上角的Y Rectangle2D
w - 这个宽度 Rectangle2D
h - 这个 Rectangle2D的高度
==============
setRect
public abstract void setRect(double x,
                             double y,
                             double w,
                             double h)
将此 Rectangle2D的位置和大小设置为指定的 double值。
参数
x - 这个 Rectangle2D左上角的X Rectangle2D
y - 这个 Rectangle2D左上角的Y Rectangle2D
w - 这个宽度 Rectangle2D
h - 这个 Rectangle2D的高度

Rectangle2D 方法的参数和返回值都为double类型,例如,即使Rectangle2D.Float对象f存储float类型的宽度,f.getWidth方法也返回一个double类型。


直接使用Double图形类可以避免使用Float类型。然而,如果需要创建上千个图形对象,还是应该考虑使用Float类型,这样可以节省存储空间。


前面对Rectangle2D类的讨论也适用于其他的类。另外,Point2D类也有两个子类Point2D.Float和Point2D.Double下面是构造一个点对象的方法:

Point2D p=new Point2D.Double(..,..);

point2D类是很有用的,使用Point2D对象比使用单独的x和y更具有面向对象的风格

Rectangle2D和Ellipse2D都是由公共超类RectangularShape继承来的。

其中比较常用的有getWidth、getHeight,getCenterX,getCenterY等

point是Point2D的直接子类

Rectangle是Rectangle2D的直接子类


Rectangle2D和Ellipse2D是RectangularShape的直接子类


Rectangle2D和Ellipse2D对象很容易构造出来:

需要:左上角的x,y坐标

宽和高

Rectangle2D不能直接构造对象,必须通过Rectangle2D.Double或者Rectangle2D.Float来构造

Rectangle2D f=new Rectangle2D.Float(x,y,width,height);
Ellipse2D e=new Ellipse2D.Float(x,y,width,height);
//用外接矩形构造一个椭圆

然而,有时候不知道左上角的位置,知道矩形的两个对角点,而对焦点不一定为左上角点

在这种情况下:首先创建一个空矩形,然后调用setFrameFromDiagonal方法,如下所示:

Rectangle2D f=new Rectangle2D.Double();
f.setFrameFromDiagonal(ax, ay,bx,by);
或者f.setFrameFromDiagonal(point a, point b);

在构造椭圆是,通常可以知道椭圆的中心,宽和高,而不是外界矩形的定点,setFrameFromCenter方法使用中心点,但仍然要给出摸一个顶点(外接矩形的顶点),通常,用下列方式构造椭圆:

Ellipse2D e=new Ellipse2D.Double();
e.setFrameFromCenter(centerX-width/2,centerY-height/2,width,height);
======================
setFrameFromCenter
public void setFrameFromCenter(double centerX,
                               double centerY,
                               double cornerX,
                               double cornerY)
根据指定的中心点坐标和角点坐标设置此Shape的框架矩形。 框架矩形由RectangularShape的RectangularShape用于定义其几何。
参数
centerX - 指定 centerX的X坐标
centerY - 指定 centerY的Y坐标
cornerX - 指定角点的X坐标
cornerY - 指定角点的Y坐标
======================
setFrameFromCenter
public void setFrameFromCenter(Point2D center,
                               Point2D corner)
根据指定的中心Point2D和角Point2D设置此Shape的框架Point2D 。 框架矩形由RectangularShape的RectangularShape用于定义其几何。
参数
center - 指定中心 Point2D
corner - 指定的角 Point2D

要想构造一条直线,需要提供起点和终点,这个点可用Point2D来表示,也可以用一对数值来表示:

Line2D line=new Line2D.Double(start,end);
//或者
Line2D line =new Line2D.Double(x,y,x,y);
                外接矩形
setFrame
public void setFrame(Rectangle2D r)
设置此窗体矩形Shape是指定的Rectangle2D 。 框架矩形由RectangularShape的RectangularShape用于定义其几何。
参数
r - 指定的 Rectangle2D
package NEW_DATE_SEQUENCE_PACKAGE;
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
/**
 *
 * @author cmx
 */
public class J_9_2_2 
{
    public static void main(String[] args)
    {
        EventQueue.invokeLater(()->
        {
            JFrame f=new DrawFrame();
            f.setTitle("这是用java绘制的第一个图形?");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setVisible(true);
        });
    }

}
class DrawFrame extends JFrame
{
    public DrawFrame()
    {
        add(new DrawComponent());
        pack();
    }
}
class DrawComponent extends JComponent
{
    private static final int DEFUALT_WIDTH=300;
    private static final int DEFUALT_HEIGHT=300;
    public void paintComponent(Graphics g)
    {
        Graphics2D g2=(Graphics2D) g;

        double leftX=0;
        double leftY=0;
        double width=200;
        double height=200;

        Rectangle2D f=new Rectangle2D.Double(leftX,leftY,width,height);
        g2.draw(f);

        Ellipse2D ellipse = new Ellipse2D.Double();
        ellipse.setFrame(f);
        g2.draw(ellipse);

        Line2D l=new Line2D.Double(leftX,leftY,leftX+width,leftY+height);
        g2.draw(l);

        double centerX=f.getCenterX();
        double centerY=f.getCenterY();
        double radius=150;

        Ellipse2D circle=new Ellipse2D.Double();
        circle.setFrame(f);
        g2.draw(circle);

    }
    public Dimension getPreferredSize()
    {
        return new Dimension(DEFUALT_WIDTH,DEFUALT_HEIGHT);
    }
}
java.awt.geom.RectangularShape
    double getCenterX();
    double getCenterY();
    double getMinX();
    double getMinY();
    double getMaxY();
    double getMaxY();
    返回闭合矩形的中心,以及最小,最大x和y的值
    double getWidth();
    double getHeight();
    返回闭合矩形的宽和高
    double getX();
    double getY();
    返回闭合矩形左上角的x和y坐标
java.awt.geom.Rectangle2D.Double
    Rectangle2D.Double(double x, double y,double w,double height);
    利用给定的左上角宽和高构造一个矩形
java.awt.geom.Rectangle2D.Float
    Rectangle2D.Float(float x, float y, float width,float height);
    利用给定的左上角,宽和高构造一个矩形
java.awt.geom.Ellipse2D.Double
    ...
    利用给定的左上角的点的坐标和宽和高构造一个椭圆
java.awt.geom.Point2D.Double
    ...
java.awt.geom.Line2D.Double()
    Line2D.Double(Point2D x,Point2D y);
    Line2D.Double(double x, double y,double x, double y);

使用颜色

使用Graphics2D类的setPaint方法可以为图形环境上的所有后续绘制的绘制操作选择颜色。例如:

setPaint

public abstract void setPaint(Paint paint)
为 Graphics2D 上下文设置 Paint 属性。使用为 null 的 Paint 对象调用此方法对此 Graphics2D 的当前 Paint 属性没有任何影响。
参数:
paint - 呈现过程中用于生成颜色的 Paint 对象;或者为 null
 g2.setPaint(Color.RED);
        g2.draw(circle);
g2.setPaint(Color.RED);
        g2.drawString("waring", 100, 100);

只需要将调用draw替换为调用fill就可以用一种颜色田勇另一个封闭图形(例如矩形或者椭圆的内部);

Rectangle2D rect=...;
g2.setPaint(Color.RED);
g2.fill(rect);

要想绘制多种颜色,就要按照选择颜色,setPaint,绘制图形,draw,在选择颜色,在绘制图形的过程实施

fill 方法会在右侧和下方少绘制一个像素,例如,如果绘制一个new Rectangle2D.Double(0,0,10,20),绘制的矩形包括x=10,y=20的像素,但是填充矩形则不包括。

Color 类用于定义颜色,在java.awt.Color中提供了13个预定义的常量:BLACK。。。

 g2.setPaint(new Color(1,128,128));
        g2.drawString("well", 100, 200);

调用颜色构造器的方法Color(int red,int green, int blueness);

三种颜色都是在0~255(一个字节)之间的整数值表示

除了纯色之外,还可以设置更复杂的颜料,如改变色调或者图像

如果是Graphics而不是Graphics2D,就要使用setColor而不是setPaint来设置颜色

要想设置背景颜色,就要使用Component中的setBackground方法。Component是JComponent类的超类

MyComponent p=new MyComponent();
p.setBackground();

setForeground,设置在组件上绘制的默认颜色

Color类brighter()和darker加量或者变暗当前的颜色

要娴熟的加亮颜色,需要

c.brighter().brighter().brighter();

例如:

package NEW_DATE_SEQUENCE_PACKAGE;
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
import java.awt.font.*;
/**
 *
 * @author cmx
 */
public class J_9_2_7
{
    public static void main(String[] args)
    {
        EventQueue.invokeLater(()->
        {
            JFrame frame=new FontFrame();
            frame.setTitle("Font Test.....");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        });
    }

}
class FontFrame extends JFrame
{
    public FontFrame()
    {
        add(new FontComponent());
        pack();
    }
}
class FontComponent extends JComponent
{
    private static final int DEFAULT_WIDTH=300;
    private static final int DEFAULT_HEIGHT=200;

    public void paintComponent(Graphics g)
    {
        Graphics2D g2=(Graphics2D) g;

        String message="Hello,world.........";

        Font f=new Font("Cambria",Font.BOLD+Font.ITALIC,20);
        g2.setFont(f);

        FontRenderContext context=g2.getFontRenderContext();
        Rectangle2D bounds2=f.getStringBounds(message,context);

        double x=(getWidth()-bounds2.getWidth())/2;
        double y=(getHeight()-bounds2.getHeight())/2;

        double ascent=-bounds2.getY();
        double baseY=y+ascent;

        g2.drawString(message, (int ) x, (int) y);

        g2.setPaint(Color.LIGHT_GRAY);
        g2.draw(new Line2D.Double(x,baseY,bounds2.getWidth(),bounds2.getHeight()));

        Rectangle2D rect=new Rectangle2D.Double(x,y,bounds2.getWidth(),bounds2.getHeight());
        g2.draw(rect);


    }
    public Dimension getPreferredSize()
    {
        return new Dimension(DEFAULT_WIDTH,DEFAULT_HEIGHT);
    }
}
java.awt.Font
    Font(String name, int style, int size)
    创建一个新字体对象
    参数:name 字体名。不是字体名,就是逻辑字体名
         style 字体风格
         size 字体大小
    String getFontName()
    返回字体名
    String  getFamily()
    返回字体家族名
    String getName()
    如果采用逻辑字体创建字体,将返回逻辑值,否则返回字体名
    Rectangle2D getStringBounds(String s,FontRenderContext context)
    饭回报为这个字符串的矩形。矩形的起点为基线。矩形顶端的y坐标等于上坡度的负值。矩形的高度等于上坡度、下坡度之和
    LineMetrics  getLineMetrics(String s,FontRenderContext context)
    返回测定字符串款的的一个线性metrics对象
    Font driveFont(int style)
    Font driveFont(float size)
    Font driveFont(int style, float size);
    返回一个新字体,出给定大小和字体风格外,其余与原字体一样
java.awt.font.LineMetrics
    float getAscent();
    返回字体的上坡度
    float getDescent();
    返回字体的下坡度
    float getLeading
    返回字体的行间距
    float getHeight()
    返回字体的总高度
java.awt.Graphics
    Font getFont()
    void setFont(Font font)
    获取或设置当前的字体。这种字体将被应用于后续的文本绘制操作中。
    void drawString(String str, int x, int y);
    采用当前的字体和颜色绘制一个字符串
        参数:str 将要绘制的字符串
            x    字符串开始的x坐标
            y    字符串基线的y坐标
java.awt.Graphics
    FontRenderContext getFontRenderContext()
    返回这个图形文本中,指定字体特征的字体绘制环境
    void drawString(String str, float x, float y)
    str
javax.swing.JComponent
    FontMetrics getFontMetrics(Font f)
    获取给定字体的度量。FontMetrics类是LineMetrics类的早先版
java.awt.FontMetrics
    FontRenderContext getFontRenderContext()
    返回字体的绘制环境



版权声明:本文为weixin_37770552原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。