目录

第3章 Java图形处理和Java 2D

3.1 Java图形坐标系统和图形上下文

3.2 Color类

3.3 Font类和FontMetrics类

3.3.2 FontMetrics类

3.4 常用的绘图方法

3.4.1 绘制直线

3.4.2 绘制矩形

3.4.3 绘制椭圆

3.4.4 绘制弧形

3.4.5 绘制多边形和折线段

3.4.6 清除绘制的图形

3.5 Java 2D简介

3.5.1 Java 2D API

3.5.2 Graphics2D简介

3.5.3 Graphics2D绘制

3.5.4 Graphics2D的属性设置

3.5.5 路径类

3.5.6 平移、缩放或旋转图形


第3章 Java图形处理和Java 2D

Java语言的类库提供了丰富的绘图方法,其中大部分对图形、文本、图像的操作方法都定义在Graphics类中,Graphics类是java.awt程序包的一部分。

3.1 Java图形坐标系统和图形上下文

绘制图形,需要一个坐标系统给予该图形定位。

Java的坐标系统的原点(0, 0)在屏幕的左上角,坐标度量以像素为单位,水平向右为x轴的正方向,垂直向下为y轴的正方向,每个坐标点的值表示屏幕上的一个像素点的位置,所有坐标点的值都取整数。

在屏幕上绘制图形时,所有输出都通过一个图形上下文( graphics context) 来产生。图形上下文有时也称为图形环境,是指允许用户在屏幕上绘制图形的信息,它由Graphics类装,Graphics类的对象可以通过Component类的getGraphics()方法获得。图形上下文表示一个绘制图层,如组件的显示区、打印机上的一页、或者一个屏幕外的图像缓冲区。它提供了绘制3种图形对象(形状、文本和图像)的方法。

public class Demo {public static void main(String[] args) {JFrame frame = new JFrame();frame.setLocation(200, 200);frame.setSize(500, 500);// 获取图形上下文,Graphics类的对象可以通过Component类的getGraphics(方法获得Graphics graphics = frame.getGraphics();frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

在游戏程序开发中,常常在组件的paint()方法内获得java.awt包中的Graphics类的对象,然后调用Graphics类中相应的绘制函数来实现输出。paint()方法是java.awt.Component 类(所有窗口对象的基类)所提供的一个方法,当系统需要重新绘制组件时,将调用该方法。paint() 方法只有一个参数,该参数是Graphics 类的实例。

public class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 一些基本绘制g.setColor(new Color(255, 0, 0));g.drawString("这是Java中带颜色的文字串", 100, 100);g.drawRect(10, 10, 100, 100);}
}

显示TestFrame界面

public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

绘制组件的时机如下所述:

  • (1 )组件外形发生变化时:如窗口的大小、位置、图标等显示区域更新时,AWT自动从高层直到叶结点组件相应地调用各组件的paint(方法,但这可能有一个延迟感。
  • (2)程序员也可直接调用某一个组件的repaint()或 paint(方法,以立即更新外观(例如在添加新的显示内容后)。

如果要求保留上次的输出结果时可以调用paint()方法,不要求保留上次的输出结果只希望用户能看到最新的输出结果时则可以调用repaint()方法。

3.2 Color类

可以使用java.awt.Color类为绘制的图形设置颜色。Color类使用了sRGB ( standard RGB,标准RGB )颜色空间来表示颜色值。颜色由红(R)、绿(G)、蓝(B)三原色构成,每种原色的强
度用一个byte 值表示,每种原色取值范围从0 (最暗)~255 (最亮),可以根据这3种颜色值的不同组合,显示不同的颜色效果,例如( 0,0,0)表示黑色,(255,255,255)表示白色。

在Java中Color类定义了13种颜色常量供用户使用,它们分别为: Color.blackColor.blueColor.cyanColor.darkGrayColor.grayColor.greenColor.lightGrayColor.magenta、Color.orangeColor.pinkColor.redColor.whiteColor.yellow。从JDK 1.4开始,也可以使用Color类中定义的新常量,它们与上述颜色常量一一对应,分别为: Color.BLACKColor.BLUEColor.CYANColor.DARK_ GRAYColor.GRAYColor.GREENColor.LIGHT_ GRAYColor.MAGENTAColor.ORANGEColor.PINKColor.REDColor. WHITEColor. YELLOW

public class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 使用常量设置颜色g.setColor(Color.GREEN);// 绿色}
}

除此之外,用户也可以通过Color类提供的构造方法Color(int r,int g,int b)创建自己需要的颜色。该构造方法通过指定红、绿、蓝3种颜色的值来创建一一个新的颜色,参数r、g、b的取值范围为0~ 255。例如:

Color color = new Color(255, 0, 255);

Graphics类的setColor(Color c)方法可以设置画笔的颜色。如例:

public class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 设置画笔的颜色Color green=new Color(0,255,0);g.setColor(green);// 绿色g.drawString("Hello Color!",200,200);}
}

一旦用户生成了自己需要的颜色,就可以通过java.awt.Component 类中的setBackground
(Color c)
setForeground(Color c)方法来设置组件的背景色和前景色,也可以使用该颜色作为当前的绘图颜色。

public class Demo {public static void main(String[] args) {JFrame frame = new JFrame();frame.setLocation(200, 200);frame.setSize(500, 500);// 设置组件的颜色// 设置组件的前景色Color foregroundColor = new Color(255, 123, 0);frame.setForeground(foregroundColor);// 设置组件的背景色Color backgroundColor = new Color(0, 255, 12);frame.setBackground(backgroundColor);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.3 Font类和FontMetrics类

可以使用java.awt.Font类创建字体对象。Java提供了物理字体和逻辑字体两种字体。AWT定义了5种逻辑字体,分别为SansSerif、Serif、 Monospaced、 Dialog 和DialogInpu。

Font类的构造方法如下:

Font (String name, int style, int size) ;
  • 其中参数name为字体名,可以设置为系统上可用的任一种字体,如SansSerifSerifMonospacedDialogDialogInput等;
  • 参数style为字型,即设置加粗、斜体等。可以设置为Font.PLAINFont.BOLDFont.ITALIC或Font.BOLD + Font.ITALIC等;
  • 参数size为字号,其取值为正整数。

例如:

Font font = new Font ("Serif", Font. ITALIC,10) ;

如果需要找到系统上的所有可用字体,可以通过创建java.awt.GraphicsEnviroment类的静态方法getLocalGraphicsEnviroment()的实例,调用getAllFonts()方法来获得系统的所有可用字体;或者通过getAvailableFontFamilyName()方法来取得可用字体的名字。

public class Test {public static void main(String[] args) {// 获取GraphicsEnviroment实例对象,通过静态方法getLocalGraphicsEnvironment()GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();// 通过getAllFonts()方法获取系统所有的可用字体Font[] allFonts = graphicsEnvironment.getAllFonts();// 查看系统有哪些可用字体for (Font font : allFonts) {System.out.println(font.getFontName());}}
}

例如:在生成可用的字体对象后,可以通过java.awt.Component类中的setFont(Font f)方法设置组件的字体,任何组件都可以设置字体,包括Graphics画笔又可以设置字体。

public class Demo {public static void main(String[] args) {JFrame frame = new JFrame();frame.setLocation(200, 200);frame.setSize(500, 500);Panel panel = new Panel();JButton button = new JButton("按钮");button.setSize(50, 100);button.setLocation(50, 50);// 创建字体Font font = new Font("Dialog", Font.BOLD, 25);// 设置按钮的字体button.setFont(font);panel.add(button);frame.add(panel);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.3.2 FontMetrics类

使用drawString(String s, int x, int y)方法我们可以指定在框架的(x, y)位置开始显示字符串,但是如果想在框架的中央显示字符串,则需要使用FontMetrics类。FontMetrics 类是一个抽象类,要使用FontMetrics对象,可以通过调用Graphics类中的getFontMetrics()方法。FontMetrics 类定义字体的度量,给出了关于在特定的组件上描绘特定字体的信息。这些字体信息包括ascent (上升量)、descent (下降量)、leading (前导宽度)和height (高度)。其中leading 用于描述两行文本间的间距,如图3-4所示。

FontMetrics类提供了下面几种方法用于获取ascent、descent、 leading 和height:

  • int getAscent();//取得由当前FontMetrics对象描述的字体的ascent值。
  • int getDescent();//取得由当前FontMetrics对象描述的字体的descent值。
  • int getLeading();//取得由当前FontMetrics对象描述的字体的leading值。
  • int getHeight();//取得使用当前字体的- -行文本的标准高度。
class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 设置字体Font font = new Font("楷体", Font.BOLD, 35);// 设置当前使用的字体g.setFont(font);// 获取FontMetrics对象FontMetrics fontMetrics = g.getFontMetrics();// 获取字符串的宽度int width = fontMetrics.stringWidth("Java游戏编程");// 获取当前使用字体的ascent值int ascent = fontMetrics.getAscent();// 获取当前使用字体的descent值int descent = fontMetrics.getDescent();int x = (getWidth() - width) / 2;int y = (getHeight() + ascent) / 2;g.drawString("Java游戏编程", x, y);}
}public class Demo {public static void main(String[] args) {final TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.4 常用的绘图方法

3.4.1 绘制直线

在Java中可用使用下面的方法绘制一条直线:

drawLine(int x1, int y1, int x2, int y2);

其中,参数x1、x2、x2、y2分别表示该直线的起点(x1, y1)和终点(x2, y2)的坐标值。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 画一条直线g.drawLine(0, 0, 200, 300);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.4.2 绘制矩形

Java中提供了绘制空心矩形(只绘制矩形的轮廓)和填充矩形的方法,分别针对普通直角矩形、圆角矩形和三维矩形有不同的绘制方法。

(1)普通直角矩形

  • 可以使用下面方法绘制普通直角矩形的轮廓:drawRect(int x,int y, int width, int height);
  • 如果需要绘制一个有填充颜色的普通直角矩形,可以使用下面的方法:fillRect(int x, int y, int width, int height) ;

这两种方法的参数含义相同,x、y分别表示矩形左上角的x坐标和y坐标,width、 height 分别表示矩形的宽和高。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 画一个普通的直角矩形g.drawRect(100, 100, 100, 150);// 画一个填充颜色的直角矩形,默认填充黑色,可以指定颜色g.setColor(Color.GREEN);g.fillRect(250, 100, 100, 150);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

(2)圆角矩形

  • 可以使用下面的方法绘制圆角矩形的轮廓:drawRoundRect(int x,int y, int width, int height, int arcwidth, int arcHeight) ;
  • 如果需要绘制一个有填充颜色的圆角矩形,可以使用下面的方法:fillRoundRect(int x, int y, int width, int height, int arcwidth, int arcHeight) ;

这两种方法的参数含义相同, x、y分别表示矩形左上角的x坐标和y坐标,width、 height 分别表示矩形的宽和高,参数arcWidth和arcHeight分别表示圆角弧的水平直径和竖直直径,如图3-6所示。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 画一个普通的圆角矩形g.drawRoundRect(100, 100, 100, 150, 30, 30);// 画一个填充颜色的圆角矩形,默认填充黑色,可以指定颜色g.setColor(Color.GREEN);g.fillRoundRect(250, 100, 100, 150, 30, 30);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

(3)三维矩形

  • 可以使用下面方法绘制三维矩形的轮廓:draw3DRect(int x,int y, int width, int height, boolean raised) ;
  • 如果需要绘制-个有填充颜色的三维矩形,可以使用下面的方法:fill3DRect(int x,int y,int width, int height, boolean raised) ;

这两种方法的参数含义相同,x、y分别表示矩形左上角的x坐标和y坐标,width、 height 分别表示矩形的宽和高,raised 为真( True )表示矩形从表面凸起,raised 为假( False )表示矩形从表面凹进。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 画一个普通的三维矩形g.draw3DRect(100, 100, 100, 150, true);// 画一个填充颜色的三维矩形,默认填充黑色,可以指定颜色g.setColor(Color.GREEN);g.fill3DRect(250, 100, 100, 150, false);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.4.3 绘制椭圆

  • 可以使用下面的方法绘制空心椭圆:drawOval (int x,int y, int width, int height) ;
  • 如果需要绘制一个有填充颜色的椭圆,可以使用下面的方法:fillOval(int x,int y, int width, int height) ;

这两种方法的参数含义相同, x、y分别表示该椭圆外接矩形左上角的x坐标和y坐标, width、height分别表示外接矩形的宽和高,如图3-7所示。如果设置外接矩形为正方形,即width和height相等,则可以绘制圆。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 画一个空心椭圆g.drawOval(100, 100, 100, 150);// 画一个填充颜色的椭圆,默认填充黑色,可以指定颜色g.setColor(Color.GREEN);g.fillOval(250, 100, 100, 150);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.4.4 绘制弧形

弧形可以看做椭圆的部分,因此它的绘制也是根据其外接矩形进行的。通过drawArc()方法和fillArc()方法可以分别绘制弧线和扇形。这两种方法为:

  • 绘制弧线:drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) ;
  • 绘制扇形:fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) ;

其中x、y、width、height 参数的含义与drawOval0方法的参数含义相同,参数startAngle表示该弧的起始角度,参数arcAngle表示生成角度(从startAngle开始转了多少度),且水平向右方向表示0度,从0度开始沿逆时针方向旋转为正角,如图3-9所示。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 绘制弧线g.drawArc(100, 100, 100, 150, 30, 100);// 画一个填充颜色的椭圆,默认填充黑色,可以指定颜色g.setColor(Color.GREEN);g.fillArc(250, 100, 100, 150, 30, 100);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.4.5 绘制多边形和折线段

(1)绘制多边形

使用drawPolygon(方法和fllPolygon)方法可以分别绘制多边形的外框轮廓和填充多边形。

  • 绘制只有轮廓的多边形:drawPolygon(int[ ] xPoints, int[ ] yPoints, int nPoints) ;
  • 绘制带有颜色填充的多边形:fillPolygon(int[ ] xPoints, int[ ] yPoints, int nPoints) ;

其中多边形的顶点是由数组xPoints和yPoints中对应下标的相应元素组成的坐标来指定,数组xPoints存放所有顶点的x坐标,数组yPoints存放所有顶点的y坐标,参数nPoints指定多边形的顶点个数。drawPolygon()方法在绘制多边形时并不自动关闭多边形的最后一条边,而仅是一段开放的折线。因此,如果需要画封闭的边框型多边形,记住在数组的尾部再添上一个起始点的坐标。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 绘制只有轮廓的多边形g.drawPolygon(new int[]{90, 20, 30, 40, 50, 90}, new int[]{50, 70, 80, 20, 60, 50}, 6);// 绘制带有颜色填充的多边形,默认填充黑色,可以指定颜色g.setColor(Color.GREEN);g.fillPolygon(new int[]{100, 200, 230, 240, 250, 100}, new int[]{150, 170, 180, 120, 160, 150}, 6);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

除此以外,drawPolygon(Polygon p)方法和fllPolgon(Polygon p)方法也可以用来绘制多边形。这两种方法的参数是一个Polygon类的对象。如果想在多边形上增加一个顶点,可以使用addPoint (int x, int y) 方法。因此可以通过先创建一个空的Polygon对象,再重复调用addPoint()方法将所有多边形的顶点加入创建的Polygon对象中,然后通过调用drawPolygon(Polygon p)方法或者fllPolygon(Polygon p)方法绘制多边形。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 绘制只有轮廓的多边形Polygon p1 = new Polygon();p1.addPoint(10, 20);p1.addPoint(20, 30);p1.addPoint(40, 70);p1.addPoint(100, 30);p1.addPoint(10, 20);g.drawPolygon(p1);// 绘制带有颜色填充的多边形,默认填充黑色,可以指定颜色Polygon p2 = new Polygon();p2.addPoint(110, 120);p2.addPoint(120, 130);p2.addPoint(40, 70);p2.addPoint(200, 130);p2.addPoint(110, 120);g.setColor(Color.GREEN);g.fillPolygon(p2);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

(2)绘制折线段

  • 可以使用drawPolygonline()方法绘制折线段:drawPolygonline (int[ ] xPoints, int[ ] yPoints, int nPoints);

其中数组xPoints存放所有顶点的x坐标,数组yPoints存放所有顶点的y坐标,nPoints 指定折线段顶点的个数。

class TestFrame extends JFrame {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 绘制折线段g.drawPolyline(new int[]{10, 50, 90, 20}, new int[]{30, 100, 200, 250}, 4);}
}public class Demo {public static void main(String[] args) {TestFrame frame = new TestFrame();frame.setLocation(200, 200);frame.setSize(500, 500);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.4.6 清除绘制的图形

可以使用clearRect()方法清除绘制的图形。clearRect(int x,int y,int width,int height)用背景色填充指定矩形以达到清除该矩形的效果,也就是说当-个Graphics对象使用该方法时,相当于在使用一个“橡皮擦”。参数x、y是被清除矩形的左上角的坐标,另外两个参数是被清除矩形的宽和高。

public class Demo {public static void main(String[] args) {final JFrame frame = new JFrame();frame.setLocation(200, 200);frame.setSize(500, 500);final Panel panel = new Panel();JButton button1 = new JButton("绘制图形");button1.setSize(100, 200);button1.setLocation(50, 50);button1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Graphics g = panel.getGraphics();// 绘制一个填充矩形g.setColor(Color.ORANGE);g.fillRect(50, 50, 100, 100);}});panel.add(button1);JButton button2 = new JButton("清除绘制图形");button2.setSize(100, 200);button2.setLocation(300, 300);button2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Graphics g = panel.getGraphics();// 调用方法清除绘制的图形,即清除原来画出来的矩形g.clearRect(50, 50, 100, 100);}});panel.add(button2);frame.setContentPane(panel);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.5 Java 2D简介

3.5.1 Java 2D API

Java 2D API ( Application Programming Interface )增强了抽象窗口工具包( AWT )的图形、文本和图像功能,可以创建高级图形库,开发更为强大的用户接口和新型的Java 应用程序。Java2D API对AWT进行了扩展,提供了更加灵活、功能更全面的绘制包,使其支持更多的图形绘制操作。

Java 2D是Java核心库的一部分,它包含的包有如下几个:

  • java.awt:java.awt包含了一些新增的2DAPI类和接口。其中Graphics2D 继承自java.awt.Graphics ,是描绘2D图形的对象。同时在Graphics2D中新增了许多状态属性,如Stroke、Paint、Clip、Transform等。
  • java.awt.imagejava.awt.image.renderable:java.awt.image和java.awt.image.renderable包中包含用于图像定义和绘制的类和接口。
  • java.awt.colorjava.awt.font:java.awt.font包中包含用于文本布局和字体定义的类和接口; Font 类的功能已得到增强,可支持详细的字体信息规范和复杂印刷特性的使用。Font 对象代表系统上可用字样集的字样实例。
  • java.awt.geom:java.awt.geom包则包含可以勾勒任何形状的GeneralPath 类。它可以由许多不同种类的subpath构成,例如lines和quadratic curves等。为了兼顾方便性,在此包中还定义了许多基本几何图形,包括Arc2D、CubicCurve2D、Line2D 等。
  • java.awt.print:java.awt.print包中包含用于打印所有基于Java 2D的文本、图形和图像的类及接口。

3.5.2 Graphics2D简介

Graphics2D扩展了java.awt.Graphics 包,使得对形状、文本和图像的控制更加完善.Graphics2D对象保存了大量用来确定如何绘制图形的信息,其中大部分都包含在- 个Graphics2D对象的6个属性中,这6个属性分别如下所述:

  • (1)绘制( paint): 该属性确定所绘制线条的颜色,以及填充图形的颜色和图案等。用户可以通过setPaint(Paint p)方法进行该属性值的设置。
  • (2)画笔( stroke ): 该属性可以确定线条的类型以及粗细,还有线段端点的形状。用户可以通过setStroke(Stroke s)方法进行该属性值的设置。
  • (3)字体( font ):该属性可以确定所显示字符串的字体。用户可以通过setFont(Font f)方法进行该属性值的设置。
  • (4)转换( transform ):该属性确定了图形绘制过程中要应用的转换方法,通过指定转换方法可将所画内容进行平移、旋转和缩放。用户可以通过setTransform()方法进行该属性值的设置。
  • (5)剪切( clip): 该属性定义了组件上某区域的边界。用户可以通过setCIlip(Clip c)方法进行该属性值的设置。
  • (6)合成( composite ): 该属性定义了如何绘制重叠的几何图形,使用合成规则可以确定重叠区域的显示效果。用户可以通过setComposite(Composite c)方法来设置该属性的值。

使用Griphics2D对象的方法进行图形的绘制,该对象的常用方法如下:

  • (1)abstract void clip(Shape s):将当前Clip与指定Shape的内部区域相交,并将Clip设置为所得的交集。
  • (2)abstract void draw(Shape s):使用当前Graphics2D.上下文的设置勾画Shape的轮廓。
  • (3)abstract void drawImage(BufferedImage img, BufferedImageOp op, intx, inty):呈现使用BufferedlmageOp过滤的BufferedImage 应用的呈现属性,包括Clip、 Transform 和Composite属性。
  • (4)abstract boolean drawlmage(Image img, Affine Transform xform, ImageObserver obs):呈现一幅图像,在绘制前进行从图像空间到用户空间的转换。
  • (5)abstract void drawString(String s,float x,float y):使用Graphics2D 上下文中当前文本属性状态呈现由指定String 指定的文本。
  • (6)abstract void drawString(String str, int x, int y):使用Graphics2D.上下文中的当前文本属性状态呈现指定String 的文本。
  • (7)abstract void fill(Shape s):使用Graphics2D上下文的设置,填充Shape的内部区域。
  • (8)abstract Color getBackground(:返回用于清除区域的背景色。
  • (9)abstract Composite getComposite():返回Graphics2D.上下文中的当前Composite。
  • (10)abstract Paint getPaint():返回Graphics2D上下文中的当前Paint。
  • (11)abstract Stroke getStroke(): 返回Graphics2D 上下文中的当前Stroke。
  • (12)abstract boolean hit(Rectangle rect, Shape s, boolean onStroke):检查指定的Shape 是否与设备空间中的指定Rectangle 相交。
  • (13)abstract void rotate(double theta):将当前的Graphics2D Transform 与旋转转换连接。
  • (14)abstract void rotate(double theta, double x, double y):将当前的Graphics2DTransform与平移后的旋转转换连接。
  • (15)abstract void scale(double sx, double sy):将当前Graphics2D Transform与可缩放转换连接。
  • (16)abstract void setBackground(Color color):设置Graphics2D上下文的背景色。
  • (17)abstract void setComposite(Composite comp):为Graphics2D 上下文设置Composite。Composite用于所有绘制方法中,例如drawImage、drawString、 draw 和fill。它指定新的像素如何在呈现过程中与图形设备上的现有像素组合。
  • (18)abstract void setPaint(Paint paint):为Graphics2D.上下文设置Paint属性。
  • (19)abstract void setStroke(Stroke s):为Graphics2D.上下文设置Stroke。
  • (20)abstract void setTransform(AffineTransform Tx):重写Graphics2D.上下文中的Transform。
  • (21)abstract void shear(double shx, double shy):将当前Graphics2D Transform 与剪裁转换连接。
  • (22)abstract void translate(double tx, double ty):将当前的Graphics2D Transform与平移转换连接。
  • (23)abstract void translate(int x, int y):将Graphics2D上下文的原点平移到当前坐标系统中的点(x,y)。

3.5.3 Graphics2D绘制

Graphics2D是Graphics类的子类,也是一个抽象类,不能实例化Graphics2D对象,为了使用Graphics2D,可以通过Graphics对象传递-一个组件的绘制方法给Graphics2D 对象。方法如下面的代码段所示:

    @Overridepublic void paint(Graphics g) {Graphics2D graphics2D = (Graphics2D) g;}

Java 2D API提供了几种定义点、直线、曲线、矩形、椭圆等常用几何对象的类,这些新几何类是java.awt.geom包的组成部分,包括Point2D、Line2D、Arc2D、Rectangle2D、 Ellipse2D、CubicCurve2D等。每个类都有单精度和双精度两种像素定义方式,例如Point2D.double 和Point2D.float, Line2D.double和Lint2D.float等,用这些类可以很容易地绘制基本的二维图形对象。

class TestPanel extends JPanel {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 获取Graphics2DGraphics2D g2D = (Graphics2D) g;// 获取Line2D对象,绘制直线Line2D line = new Line2D.Float(1.0f, 2.0f, 150.0f, 20.0f);g2D.draw(line);// 获取Rectangle2D对象,绘制矩形Rectangle2D rect = new Rectangle2D.Float(50, 80, 100, 100);Color color = new Color(100, 20, 0);g2D.setColor(color);g2D.draw(rect);// 获取Ellipse2D对象,绘制圆形Ellipse2D ellipse = new Ellipse2D.Double(200, 180, 100, 100);g2D.setColor(Color.RED);g2D.fill(ellipse);// 设置字符串g2D.drawString("Java游戏编程", 20, 200);// 获取CubicCurve2D对象,绘制弧线,比直线多了两个控制点CubicCurve2D cubic = new CubicCurve2D.Float(0, 100, 120, 50, 170, 270, 220, 50);g2D.draw(cubic);}
}public class Demo {public static void main(String[] args) {JFrame frame = new JFrame();frame.setLocation(200, 200);frame.setSize(500, 500);TestPanel panel = new TestPanel();frame.setContentPane(panel);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.5.4 Graphics2D的属性设置

下面介绍在Graphics2D的图形上下文中设置常用的属性如paint、stroke和composite。

(1)paint

paint用于填充绘制图形的颜色或图案。API提供了两种方式:GradientPaint和TexturePaint。

  • GradientPaint定义在两种颜色间渐变的填充方式。
  • TexturePaint是利用重复图像片段的方式定义的一种纹理填充方式。

GradientPaint类提供了下面的构造方法来建立颜色渐变方式:

  • ①GradientPaint(float x1, float y1, Color colorl, float x2, float y2, Color color2);
  • ②GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2, boolean cyclic);
  • ③GradientPaint(Point2D p1, Color colorl, Point2D p2, Color color2);
  • ④GradientPaint(Point2D pl, Color colorl, Point2D p2, Color color2, boolean cyclic);

其中,构造方法①和②中参数x1、y1指定颜色渐变的起点坐标,x2、y2指定颜色渐变的终点坐标,填充颜色从colorl渐变至color2。构造方法②中参数cyclic 为True时,填充方式与构造方法①定义的相同;如果cyclic 为False,则填充方式为非周期性渐变。构造方法③与构造方法①类似,构造方法④与构造方法②类似,只是在构造方法③和④中使用了Point2D 对象来指定填充颜色渐变的起始(p1)和结束(p2)位置。

class TestPanel extends JPanel {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 获取Graphics2DGraphics2D g2D = (Graphics2D) g;// 实例化GradientPaint对象GradientPaint gradientPaint = new GradientPaint(20f, 30f, Color.RED, 200f, 200f, Color.GREEN);// 设置paint属性g2D.setPaint(gradientPaint);// 填充一个矩形来显示渐变g2D.fill(new Rectangle2D.Float(10f, 10f, 100f, 200f));}
}public class Demo {public static void main(String[] args) {JFrame frame = new JFrame();frame.setLocation(200, 200);frame.setSize(500, 500);TestPanel panel = new TestPanel();frame.setContentPane(panel);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

而TexturePaint类的构造方法为:TexturePaint(BufferedImage txtr, Rectangle2D anchor)。其中txtr用来定义一个单位的填充图像的材质,anchor用来复制材质。

class TestPanel extends JPanel {// 只需要继承任意组件类(Component类的子类),都可以重写paint(Graphics g)方法@Overridepublic void paint(Graphics g) {// 获取Graphics2DGraphics2D g2D = (Graphics2D) g;// 创建BufferedImage对象,width是宽度,height是高度,imageType是创建的图像类型BufferedImage texture = new BufferedImage(5, 5, 1);// 创建一个Graphics2D对象Graphics2D pattern=texture.createGraphics();// 设置纹理图案的颜色pattern.setColor(Color.GREEN);// 填充纹理图案pattern.fillRect(0, 0, 20, 20);pattern.setColor(Color.ORANGE);pattern.fillOval(0, 0, 20, 20);// 创建用于定位和复制纹理的Rectangle2D对象Rectangle2D rect = new Rectangle2D.Float(0, 0, 20, 20);// 创建TexturePaint对象TexturePaint texturePaint = new TexturePaint(texture, rect);// 以指定的纹理设置绘图方式g2D.setPaint(texturePaint);// 以纹理方式绘制填充矩形g2D.fill(new Rectangle2D.Double(100, 50, 270, 270));}
}public class Demo {public static void main(String[] args) {JFrame frame = new JFrame();frame.setLocation(200, 200);frame.setSize(500, 500);TestPanel panel = new TestPanel();frame.setContentPane(panel);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

(2)stroke

stroke用于在绘制图形的轮廓时确定线条的形状和粗细,通常使用BasicStroke 对象来定义,通过setStroke()方法设定stroke的属性值。BasicStroke 定义的特性包括线条宽度、笔形样式、线段连接样式和短划线图案等。使用stroke属性设定图形轮廓的绘制方式时,首先调用setStroke()方法设定轮廓的绘制方式,然后使用setPaint()方法定义画笔如何绘制该图形,最后使用draw()方法来绘制该图形。

在BasicStroke中定义了一组基本的简单图形轮廓的直线绘制和点划线绘制方式,它提供了3种绘制粗线的末端样式: CAP_BUTT、CAP_ROUND和CAP_ SQUARE;以及3种线段连接样式:JOIN_BEVEL、JOIN_MITER和JOIN_ROUND。

BasicStroke类提供了下面的构造方法来建立画笔的绘制方式:

  • ①BasicStoke 0);
  • ②BasicStoke (float width);
  • ③BasicStoke (float width, int cap, int join);
  • ④BasicStoke (float width, int cap, int join, float miterlimit);
  • ⑤BasicStoke (float width, int cap, int join, float miterlimit, float[} dash, float dash phase);

其中width表示轮廓线的宽度;cap 表示轮廓线末端的样式(可选值为:BasicStroke.CAP_BUTTBasicStroke.CAP_ROUNDBasicStroke.CAP_ SQUARE);join 表示相交线段的连接样式(可选值为:BasicStroke.JOIN_BEVELBasicStroke.JOIN_MITERBasicStroke.JOIN_ROUND);miterlimit表示在JOIN_MITER 模式下若相交的尖形末端大于miterlimit,则超过部分被削去;dash为虛线的样式,数组内的值为短划线和空白间距的值;dash_ phase为虚线样式数组的起始索引。

public class Frame extends JFrame {@Overridepublic void paint(Graphics g) {Graphics2D g2 = (Graphics2D) g;// 创建一个BasicStroke对象来设置直线的绘制方式Line2D line = new Line2D.Double(30, 50, 100, 80);Stroke stroke = new BasicStroke(10.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);g2.setStroke(stroke);g2.draw(line);// 创建一个BasicStroke对象来设置椭圆的绘制方式Ellipse2D ellipse = new Ellipse2D.Double(150, 50, 90, 90);stroke = new BasicStroke(8, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 2, new float[]{10, 5}, 0);g2.setStroke(stroke);g2.draw(ellipse);// 创建一个BasicStroke对象来设置矩形的绘制方式Rectangle2D rect = new Rectangle2D.Double(30, 100, 80, 80);stroke = new BasicStroke(10, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, 0);g2.setStroke(stroke);g2.draw(rect);}public static void main(String[] args) {Frame frame = new Frame();frame.setTitle("测试");frame.setSize(300, 300);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

(3)composite

composite用于定义绘制重叠图形的绘制方式。当绘制多个图像时,遇到图像重叠的情况,需要确定重叠部分的颜色显示方式,重叠区域的像素颜色决定了该部分图像的透明程度。在composite的定义中,最常用的就是AlphaComposite, 我们可以通过setComposite()方 法来将AlphaComposite对象添加到Graphics2D上下文中,设置图像重叠部分的复合样式。

AlphaComposite有两个构造器方法如下:

private AlphaComposite(int rule)
private AlphaComposite(int rule, float alpha)

AlphaComposite类中定义了多种新颜色与已有颜色的复合规则,例如SRC _OVER表示混合时新颜色(源色)应覆盖在已有颜色(目标色)之上; DST_OUT表示混合时去除已有颜色; SRC _OUT表示混合时去除新颜色; DST_ OVER 表示混合时用已有颜色覆盖新颜色。

在设置混合颜色的同时,还可以设置颜色的透明度alpha 值,它用百分比表示在颜色重叠时当前颜色的透明度,alpha 取值范围从0.0(完全透明) ~ 1.0 (完全不透明)。

public class Frame extends JFrame {@Overridepublic void paint(Graphics g) {Graphics2D g2 = (Graphics2D) g;g2.setColor(Color.RED);Rectangle2D rect1 = new Rectangle2D.Double(50, 50, 100, 100);g2.fill(rect1);g2.setColor(Color.GREEN);Rectangle2D rect2 = new Rectangle2D.Double(120, 70, 100, 100);AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f);g2.setComposite(comp);g2.setColor(Color.red);g2.setComposite(comp);g2.fill(rect2);}public static void main(String[] args) {Frame frame = new Frame();frame.setTitle("测试");frame.setSize(300, 300);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.5.5 路径类

在java.awt.geom包中定义了几何图形类,包括点、直线、矩形、圆、椭圆、多边形等。

路径类用于构造直线、二次曲线和三次曲线的几何路径,它可以包括多个子路径。

下面讲解GeneralPath类,介绍路径类的功能和应用。

1.构造方法

  • (1) GeneralPath(int rule):以rule指定缠绕规则构建对象。缠绕规则确定路径内部的方式。有两种方式的缠绕规则: Path2D.WIND_ EVEN ODD用于确定路径内部的奇偶(even-odd) 缠绕规则;Path2D.WIND NON ZERO用于确定路径内部的非零(non-zero) 缠绕规则。
  • (2) GeneralPath():以默认的缠绕规则Path2D.WIND NON ZERO构建对象。
  • (3) GeneralPath(int rule, int initialCapacity):以rule指定缠绕规则和initialCapacity指定的容量(以存储路径坐标)构建对象。
  • (4) GeneralPath(Shape s):以Shape对象s构建对象。

2.常用方法

路径对象的常用方法如下:

  • (1)void append(Shape s, boolean connect):将指定Shape对象的几何形状追加到路径中,也许会使用一条线段将新几何形状连接到现有的路径段。如果connect为True并且路径非空,则被追加的Shape几何形状的初始moveTo操作将被转换为lineTo 操作。
  • (2)void closePath():回到初始点使之形成闭合的路径。
  • (3)boolean contains(double x, double y):测试指定坐标是否在当前绘制的边界内。
  • (4)void curveTo(float x1, float y1, float x2, float y2, float x3, float y3):将3个新点定义的曲线段添加到路径中。
  • (5)Rectangle2D getBounds2D():获得路径的边界框。
  • (6)Point2D getCurrentPoint():获得当前添加到路径的坐标。
  • (7)int getWindingRule():获得缠绕规则。
  • (8)void lineTo(float x, floaty):绘制一条从当前坐标到(x, y)指定坐标的直线,将(x, y)坐标添加到路径中。
  • (9)void moveTo(float x, float y):从当前坐标位置移动到(x,y) 指定位置,将(x, y)添加到路径中。.
  • (10)void quadTo(float x1, float y1, float x2, float y2):将两个新点定义的曲线段添加到路径中。
  • (11)void reset():将路径重置为空。
  • (12)void setWindingRule(int rule):设置缠绕规则。
  • (13)void transform(AffineTransform at):使用指定的Affine Transform变换此路径的几何形状。
public class Frame extends JFrame {@Overridepublic void paint(Graphics g) {Graphics2D g2 = (Graphics2D) g;// 用路径画一个三角形GeneralPath path = new GeneralPath();path.moveTo(50f, 50f);path.lineTo(300f, 100f);path.lineTo(150f, 150f);path.lineTo(50f, 50f);g2.draw(path);}public static void main(String[] args) {Frame frame = new Frame();frame.setTitle("测试");frame.setSize(400, 400);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

3.5.6 平移、缩放或旋转图形

需要平移、缩放或旋转一个图形,可以使用AffineTransform类来实现对图形的这些操作。
(1)首先使用AffineTransform类创建一个对象:AffineTransform trans=new AffineTransform();。对象trans具有最常用的3个方法来实现对图形变换的操作:

  • translate(double a,double b):将图形在x轴方向移动a个单位像素, y轴方向移动b个单位像素。a是正值时向右移动,负值是向左移动; b是正值时是向下移动,负值是向上移动。
  • scale(double a,double b):将图形在x轴方向缩放a倍, y轴方向缩放b倍。
  • rotate(double number,double x,double y):将图形沿顺时针或逆时针以(x, y)为轴点旋转number个弧度。

(2)进行需要的变换,比如要把一个矩形绕点(100,100)顺时针旋转60°, 那么就要先做好准备:transrotate (60.0*3.1415927/180,100,100) ;
(3)把Graphics对象,比如g2d设置为具有trans这种功能的“画笔”:g2d. setTransform(trans) ;假如rect是一个矩形对象,那么g2d.draw(rect)画的就是旋转后的矩形。

public class Frame extends JFrame {@Overridepublic void paint(Graphics g) {Graphics2D g2 = (Graphics2D) g;// 用路径画一个矩形Rectangle2D rect = new Rectangle2D.Double(250, 50, 80, 150);g2.setColor(Color.yellow);g2.fill(rect);// 创建AffineTransform类对象AffineTransform transform = new AffineTransform();// 将图形以点(100,100)为轴点选择45°transform.rotate(45, 100, 100);// 设置旋转g2.setTransform(transform);// 绘制旋转后的图形g2.fill(rect);}public static void main(String[] args) {Frame frame = new Frame();frame.setTitle("测试");frame.setSize(400, 400);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

《Java游戏编程原理与实践教程》读书笔记(第3章——Java图形处理和Java 2D)相关推荐

  1. Java课设对对碰_第11章对对碰游戏(图形版)(Java游戏编程原理与实践教程课件).ppt...

    游戏界面和相关图片素材 11.3 程序设计的步骤 11.3.1 设计游戏窗口类(GameRoom.java) 游戏窗口类GameRoom实现游戏全部功能,继承JFrame组件实现的.是由上方Panel ...

  2. java游戏编程原理与实践教程_第18章青蛙过河游戏(Java游戏编程原理与实践教程课件).ppt...

    第18章 青蛙过河游戏 青蛙过河游戏是一个有趣的智力游戏.六只青蛙分成两队,左边三只,右边三只,都要过河,但是互不相让.中间只有一块空白石头.你需要用一种方法将左面的青蛙和右面的青蛙互换. 游戏说明: ...

  3. Unix朝代歌《精通Unix下C语言编程与项目实践》读书笔记(7)

      文章试读  <精通Unix下C语言编程与项目实践>读书笔记(new) <精通Unix下C语言编程与项目实践>文章试读 第1回 回评论读者展迷茫,出<笔记>浪子释 ...

  4. Java 核心技术卷 II(第 8 版) – 读书笔记 – 第 1 章(下)

    22.一旦获得了一个 Charset,就可以在 Java 的 Unicode 和指定的编码格式之间进行转化,下面以 GBK 和 Unicode 之间做为例子. 从 Unicode 到 GBK: imp ...

  5. 《Python从入门到实践》读书笔记——第五章 if语句

    <Python从入门到实践>读书笔记--第五章 if语句 1. 一个简单示例 cars = ['audi', 'bwm', 'subaru', 'toyota']for car in ca ...

  6. 《Python从入门到实践》读书笔记——第六章 字典

    <Python从入门到实践>读书笔记--第六章 字典 1. 一个简单的字典 alien_0 = {'color': 'green', 'points': 5}print(alien_0[' ...

  7. python第三章上机实践_《机器学习Python实践》读书笔记-第三章

    <机器学习Python实践>,第三章,第一个机器学习项目 以往目录:橘猫吃不胖:<机器学习Python实践>读书笔记-第一章​zhuanlan.zhihu.com 书中介绍了一 ...

  8. 《Hbase原理与实践》读书笔记——1.HBase概述

    1.1 HBase前世今生 Google当年风靡一时的"三篇论文":GFS -> HDFS , Mapreduce -> hadoop mapreduce , bigT ...

  9. Windows游戏编程大师技巧第二版学习笔记之第一章 实验补充

    前面记录的一下看书中的重点,编程还是要动手,下面就来动手试试,这里选择VC6.0编译器 这里先来配置游戏编程环境,原书中的dx81sdk_full.exe一共是1百多MB,其实没必要整那么多,看我在我 ...

  10. 《深度学习与图像识别原理与实践》—读书笔记

    机器视觉在行业中的应用 机器视觉的发展背景 人工智能 人工智能(Artificial Intelligence, AI)是计算机科学的一个分支,其意在了解智能的实质,并生产出一种新的能以人类智能相似的 ...

最新文章

  1. 《DDIA》读书笔记
  2. 华硕p8b75v主板说明书_我们测了22块主板 发现128GB内存不是想上就上
  3. 区分各浏览器的CSS hack(包括360、搜狗、opera)
  4. .Net Micro Framework SDK 2.5 发布
  5. GitHub上值得收藏的100个精选前端项目!
  6. VS Code配置C/C++
  7. java search 不能使用方法_java – 无法使用TERMS QUERY从ELASTIC SEARCH查询字母数字字段...
  8. 代码合并工具_合并上千个Excel表格,1秒就能完成
  9. chrome自定义背景_Android Chrome自定义标签
  10. MySQL 5.7: Page Cleaner的刷脏问题
  11. 华为u2020操作指南_用手机水平仪检测水平,操作简单,帮助甚大
  12. 注解@PostConstruct与@PreDestroy讲解及实例
  13. HTML如何把输入框变成必填值,required输入框为必填项
  14. 最新团长头像制作小程序源码+云开发的/支持流量主
  15. 语法歧义现象(一):牛津逗号(Oxford Comma)
  16. 繁体字转换 java_java代码实现简体繁体转换
  17. 免费短链接生成器推荐,长网址缩短工具。
  18. python中rect用法_pyGame中rect对象的方法解释,pygame,Rect,详解
  19. 天空卫士参与编写的《数据安全治理实践指南(2.0)》正式发布
  20. STM32c8t6Flash地址空间的数据读取

热门文章

  1. Java之API的使用
  2. 计算机软件实习项目四 —— 校园一卡通管理系统 (代码实现) 12-27
  3. linux 查看添加的镜像源,linux镜像源的查看、配置以及删除
  4. ssm电影院订票系统 前端layui
  5. 父与子学编程python_Python入门《父与子的编程之旅第2版》+《教孩子学编程Python语言版》...
  6. Matlab2018a安装包Linux版本
  7. Latex定宽单栏长表格(双栏环境)
  8. 毕向东的Java基础视频教程的学习,作为java基础的基础学习视频
  9. 物业收费管理系统c语言编程,C语言程序设计-物业管理系统.doc
  10. Linux和Windows文件实时同步