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()
返回字体的绘制环境