Java核心技术卷一基础知识-第7章-图形程序设计-读书笔记

第7章 图形程序设计

本章内容:
* Swing概述
* 创建框架
* 框架定位
* 在组件中显示信息
* 处理2D图形
* 使用颜色
* 文本使用特殊字体
* 显示图像
  1. 本章主要讲述如何编写定义屏幕上的窗口大小和位置的程序;如何在窗口中采用多种字体显示文本;如何显示图像等。

7.1 Swing概述

  1. 在Java 1.0刚刚出现的时候,包含了一个用于基本GUI程序设计的类库,Sun将它称为抽象窗口工具箱(Abstract Window Toolkit,AWT)。基本AWT库采用将处理用户界面元素的任务委派给每个目标平台(Window、Solaris、Macintosh等)的本地GUI工具箱的方式,由本地GUI工具箱负责用户界面元素的创建和动作。在不同的平台上,操作行为存在着一些微妙的差别。有的图形环境(如X11/Motif)并没有像Window或Macintosh这样丰富的用户界面组件集合。在不同平台上的AWT用户界面库中存在着不用的bug。研发人员必须在每一个平台上测试应用程序。
  2. 在1996年,Netscape创建了一种称为IFC(Internet Foundation Class)的GUI库,它采用了与AWT完全不同的工作方式。它将按钮、菜单这样的用户界面元素绘制在空白窗口上,面对等体只需要创建和绘制窗口。因此,Netscape的IFC逐渐在程序运行的所有平台上的外观和动作都一样。Sun与Netscape合作完善了这种方式,创建了一个名为Swing的用户界面库。Swing可作为Java 1.1的扩展部分使用,现已成为Java SE 1.2标准库的一部分。
  3. Swing没有完全替代SWT,而是基于AWT架构之上。Swing仅仅提供了能力更加强大的用户界面组件。尤其在采用Swing编写的程序中,还需要使用基本的AWT处理事件。从现在开始,Swing是指“被绘制的”用户界面类;AWT是指像事件处理这样的窗口工具箱的底层机制。
  4. 在用户屏幕上显示基于Swing用户界面的元素要比显示AWT的基于对等体组件的速度慢一些。鉴于以往的经验,对于任何一台现代的计算机来说,微小的速度差别无房大碍。另外,由于下列几点无法抗拒的原因,人们选择Swing:
    • Swing拥有一个丰富、便捷的用户界面元素集合。
    • Swing对底层平台依赖的很少,因此与平台相关的bug很少。
    • Swing给予不用平台的用户一致的感觉。

7.2 创建框架

  1. 在Java中,顶层窗口(就是没有包含在其他窗口中的窗口)被称为框架(frame)。在AWT库中有一个称为Frame的类,用于描述顶层窗口。这个类的Swing版本名为JFrame,它扩展于Frame类。JFrame是极少数几个不绘制在画布上的Swing组件之一。因此,它的修饰部件(按钮、标题栏、图标等)由用户的窗口系统绘制,而不是由Swing绘制。
  2. 所有的Swing组件必须由时间分派线程(event dispatch thread)进行配置,线程将鼠标点击和按键控制转移到用户接口组件。
  3. 许多Swing程序并没有在事件分配线程中初始化用户界面。在主线程中完成初始化时通常采用的方式。

7.3 框架定位

  1. JFrame类本身包含若干个改变框架外观的方法。当然,通过继承,从JFrame的各个超类中继承了许多用于处理框架大小和位置的方法。其中最重要的有下面几个:
  • setLocation和setBounds方法用于设置框架的位置。
  • setIconImages用于告诉窗口系统在标题栏、任务切换窗口等位置显示哪个图标。
  • setTitle用于该表标题栏的文字。
  • setResizable利用一个boolean值确定框架的大小是否允许用户改变。
  1. Component类找你哥的setLocation方法是重定位组件的一个方法。Complement中的setBounds方法可以实现一步重定位组件大小和位置的操作。
  2. 对于框架来说,setLocation和setBounds中的坐标均相对于整个屏幕。

7.3.1 框架属性

  1. 从概念上讲,title是框架的一个属性。当设置这个属性时,希望这个标题能够改变用户屏幕上的显示。当获取这个属性时,希望能够返回已经设置的属性值。
  2. 针对get/set约定有一个例外:对于类型为boolean的属性,获取方法由is开头。

7.3.2 确保合适的框架大小

  1. 要记住:如果没有明确地指定框架的大小,所有框架的默认值为0x0像素。
  2. 为了得到屏幕的大小,需要按照下列步骤操作。调用Toolkit类的静态方法getDefaultToolkit得到一个Toolkit对象(Toolkit类包含很多与本地窗口系统打交道的方法)。然后,调用getScreenSize方法,这个方法以Dimension对象的形式返回屏幕的大小。Dimension对象同时用公有实例变量width和height保存着屏幕的宽度和高度。
  3. 下面是为了处理框架给予的一些提示:
  • 如果框架中只包含标准的组件,如按钮和文本框,那么可以通过调用pack方法设置框架大小。框架将被设置为刚好能够防止所有组件的大小。在通常情况下,将程序的主框架尺寸设置为最大。正如Java SE 1.4,可以通过调用下列方法将框架设置为最大。frame.setExtendedState(Frame.MAXINIZED_BOTH)
  • 牢记用户定位应用程序的框架位置、重置框架大小,并且在应用程序再次启动时恢复这些内容是一个不错的想法。
  • 如果缩写一个使用多个显示屏幕的应用程序,应该利用GraphicsEnvironment和Graphics Device类获得显示屏幕的大小。
  • GraphicsDevice类允许在全屏模式下执行应用程序。
  1. java.awt.Component 1.0
    • boolean isVisible()
    • void setVisible(boolean b)
      获取或设置visible属性。组件最初是可见的,但JFrame这样的顶层组件例外。
    • void setSize(int width,int height) 1.1
      使用给定的宽度和高度,重新设置组件的大小。
    • void setLocation(int x,int y) 1.1
      将组件移到一个新的位置上。如果这个组件不是顶层组件,x和y坐标(或者p.x和p.y)是容器坐标;否则是屏幕坐标(例如:aJFram)。
    • void setBounds(int x,int y,int width,int height) 1.1
      移动并重新设置组件的大小。
    • Dimension getSize() 1.1
    • void setSize(Dimension d) 1.1
      获取或设置当前组件的size属性。
  2. java.awt.Window 1.0
    • void toFront()
      将这个窗口显示在其他窗口前面。
    • void toBack()
      将这个窗口移到桌面窗口栈的后面,并重新排列所有的可见窗口。
    • boolean isLocationByPlatform() 5.0
    • void setLocationByPlatform(boolean b) 5.0
      获取或设置locationByPlatform属性。这个属性在窗口显示之前被设置,由平台选择一个合适的位置。
  3. java.awt.Frame 1.0
    • boolean isResizable()
    • void setResizable(boolean b)
      获取或设置resizable属性。这个属性设置后,用户可以重新设置框架的大小。
    • String getTitle()
    • void setTitle(String s)
      获取或设置title属性,这个属性确定框架标题栏中的文字。
    • Image getIconImage()
    • void setIconImage(Image image)
      获取或设置iconImage属性,这个属性确定框架的图标。窗口系统可能会将图标作为框架装饰或其他部位的一部分显示。
    • boolean isUndecorated() 1.4
    • void setUndecorated(boolean b) 1.4
      获取或设置undecorated属性。这个属性设置后,框架显示中将没有标题栏或关闭按钮这样的装饰。早框架显示之前,必须调用这个方法。
    • int getExtendedState() 1.4
    • void setExtendedState(int state) 1.4
      获取或设置窗口状态。状态是下列值之一。Frame.NORNAL、Frame.ICONIFIED、Frame.MAXIMIZED_HORIZ、Frame.MAXIMIZED_VERT、Frame.MAXIMIZED_BOTH。
  4. java.awt.Toolkit 1.0
    • static Toolkit getDefaultToolkit()
      返回默认的工具箱。
    • Dimension getDcreenSize()
      返回用户屏幕的尺寸。
  5. javax.swing.ImageIcon 1.2
    • ImageIcon(String filename)
      构造一个图标,其图像存储在一个文件中。
    • Image getImage()
      获取该图标的图像。

7.4 在组件中显示信息

  1. 在JFrame中有四层面板。其中的根面板、层级面板和玻璃面板人们并不太关心;它们是用来组织菜单栏和内容窗格以及实现观感的。Swing程序员最关心的是内容窗格(content pane)。在设计框架的时候,将所有的组件添加到内容窗格中。
  2. 绘制一个组件,需要定义一个扩展JComponent的类,并覆盖其中的paintComponent方法。paintComponent方法有一个Graphics类型的参数,这个参数保存着用于绘制图像和文本的设置。在Java中,所有的绘制都必须使用Graphics对象,其中包含了绘制图案、图像和文本的方法。
  3. 无论何种原因,只要窗口需要重新绘图,事件处理器就会通告组件,从而引发执行所有组件的paintComponent方法。
  4. 一定不要自己调用paintComponent方法。在应用程序需要重新绘图的时候,这个方法将被在佛那个地调用,不要人为的干预这个自动的处理过程。
  5. 如果需要强制刷新屏幕,就需要调用repaint方法,而不是paintComponent方法。它将引发采用相应配置的Graphics对象调用所有组件的paintComponent方法。
  6. 在框架中添加一个或多个组件时,如果只想使用它们的首选大小,可以调用pack方法而不是setSize方法。
  7. 有些程序员更喜欢扩展JPanel,而不是JComponent。JPanel是一个可以包含其他组件的容器(container),但同样也可以在其上面进行绘制。有一点不同之处是,面板不透明,这意味着需要在面板的边界内绘制所有的像素。最容易实现的方法是,在每个面板子类的paintComponent方法中调用super.paintComponent来用背景色绘制面板。
  8. javax.swing.JFrame 1.2
    • Container getContentPane()
      返回这个JFrame的内容窗格对象。
    • Component add(Component c)
      将一个给定的组件添加到改框架的内容窗格中(在Java SE 5.0以前的版本中,这个方法将抛出一个异常)。
  9. java.awt.Component 1.0
    • void repaint()
      “尽可能快地”重新绘制组件。
    • Dimension getPreferredSize()
      要覆盖这个方法,发挥这个组件的首选大小。
  10. javax.swing.JComponent 1.2
    • void paintComponent(Grphics g)
      覆盖这个方法来描述应该如何绘制自己的组件。
  11. java.awt.Window 1.0
    • void pack()
      调整窗口大小,要考虑到其组件的首选大小。

7.5 处理2D图形

  1. Graohics类包含绘制直线、矩形和椭圆等方法。但是,这些绘制图形的操作能力非常有限。例如,不能改变先的粗细,不能旋转这个图形。
  2. Java SE 1.2引入了Java 2D库,这个库实现了一组功能强大的图形操作。
  3. 要想使用Java 2D库绘制图形,需要获得一个Graphics2D类对象。这个类是Graphics类的子类。自从Java SE 2版本依赖,paintComponent方法就会自动地获取一个Graphics2D类对象,只需要进行一次类型转换就可以了。
  4. Java 2D库采用面向对象的方式将几何图形组织起来。包括描述直线、矩形的椭圆的类:LINE2D、Rectangle2D、Ellipse2D这些类都实现了Shape接口。
  5. 要想绘制图形,首先要创建一个实现了Shape接口的类的对象,然后调用Graphics2D类中的draw方法。
  6. 使用Java 2D图形或许会增加一些复杂度。在1.0的绘制方法中,采用的是整型像素坐标,而Java 2D图形采用的是浮点坐标。在很多情况下,用户可以使用更有意义的形式(例如,微米或英寸)指定图形的坐标,然后再将其转换成像素,这样做很方便。在Java 2D库中,内部的很多浮点极端都采用单精度float。毕竟,几何计算的最终目的是要设置屏幕或打印机的像素,所以单精度完全可以满足要求了。只要舍入误差限制在一个像素的范围内,视觉效果就不会受到任何影响。另外,在某些平台上,float计算的速度比较快,并且只占据double值的一般存储量。
  7. 由于后缀和类型转换都有点麻烦,所以2D库的设计者决定为每个图形类提供两个版本:一个是为那些节省空间的程序员提供的float类型的坐标;另一个是为那些懒惰的程序员提供的double类型的坐标。
  8. Rectangle2D方法的参数和返回值均为double类型。
  9. 直接使用Double图形类可以避免处理float类型的值,然后如果需要创建上千个图形对象,还是应该考虑使用Float类,这样可以节省存储空间。
  10. Rectangle2D和Ellipse2D类都是由公共超类RectangularShape继承来的。
  11. RectangularShape类定义了20多个有关图形操作的通用方法,其中比较常用的方法有getWidth、getHeight、getCenterX、getCenterY等。
  12. 从Java 1.0遗留下来的两个类也被放置在图形类的继承层次中。它们是Rectangle和Point类,分别扩展于Rectangle2D和Point2D类,并用整型坐标存储矩形和点。
  13. Rectangle2D和Ellipse2D对象很容易构造,需要给出
  • 左上角的x和y坐标。
  • 宽和高。
  1. java.awt.geom.RectangularShape 1.2
    • double getCenterX()
    • double getCenterY()
    • double getMinX()
    • double getMinY()
    • double getMaxX()
    • double getMaxY()
      返回闭合矩形的中心,以及最小、最大x和y坐标值。
    • double getWidth()
    • double getHeight()
      返回闭合矩形的宽和高。
    • double getX()
    • double getY()
      返回闭合矩形左上角的x和y坐标。
  2. java.awt.geon.Rectengle2D.Double 1.2
    • Rectangle2D.Double(double x,double y,double w,double h)
      利用给定的左上角、宽和高,构造一个矩形。
  3. java.awt.geom.Rectangle2D.Float 1.2
    • Rectangle2D.Float(float x,float y,float w,float h)
      利用给定的左上角、宽和高,构造一个矩形。
  4. java.awt.geom.Ellipse2D.Double 1.2
    • Ellopse2D.Double(double x,double y,double w,double h)
      利用给定的左上角、宽和高的外接矩形,构造一个椭圆。
  5. java.awt.geom.Point2D.Double 1.2
    • Point2D.Double(double x,double y)
      利用给定坐标构造一个点。
  6. java.awt.geom.Line2D.Double 1.2
    • Line2D.Double(Point2D start,Point2D end)
    • Line2D.Double(double startX,double startY,double endX,double endY)
      使用给定的起点和终点,构造一条直线。

7.6 使用颜色

  1. 使用Graphics2D类的setPaint方法可以为图形环境上的所有后续的绘制操作选择颜色。
  2. 只需要将调用dra替换为调用fill就可以用一种颜色填充一个封闭图形的内部。
  3. 要想绘制多种颜色,就需要按照选择颜色、绘制图形、再选择另外一种颜色、再绘制图形的过程实施。
  4. fill方法会在右侧和下方少绘制一个像素。
  5. Color类用于定义颜色。在java.awt.Color类中提供了13个预定义的常量,它们分别表示13种标准颜色。BLANK、BLUE、CYAN、DARK_GRAY、GRAY、LIGHT_GRAY、MAGENTA、ORANGE、PINK、RED、WHITE、WELLOW。
  6. 可以通过提供红、绿和蓝三色成分来创建一个Color对象,以达到定制颜色的目的。
  7. 要想设置背景颜色,就需要使用Component类中的setBackground方法。Component类是JComponent类的祖先。
  8. setForeground方法是用来设定在组件上进行绘制时使用的默认颜色。
  9. Color类中的brighter()方法和darker()方法的功能,它们分别加亮或变暗当前的颜色。使用brighter方法也是加亮条目的好办法。实际上,brighter()只微微地加亮一点。要达到耀眼的效果,需要调用三次这个方法:c.brighter().brighter().brighter()
  10. java在SystemColor类中与定义了很多颜色的名字。在这个类中的常量,封装了用户系统的各个元素的颜色。
  11. 系统颜色
    desktop桌面的背景颜色textText文本的前景颜色
    activeCaption 标题的背景颜色 textInactiveText 非活动组件的文本颜色
    activeCaptionText 标题的文本颜色 textHighlight 高亮度文本的背景颜色
    activeCaptionBorder 标题文本的边框颜色 textHighlightText 高亮度文本的文本颜色
    inactiveCaption 非活动标题的背景颜色 control 组件的背景颜色
    inactiveCaptionText 非活动标题的文本颜色 controlText 组件的文本颜色
    inactiveCaptionBorder 非活动标题的边框颜色 controlLtHightlight 组件的浅高亮度颜色
    Window 窗口的背景 controlHightlight 组件的高亮度颜色
    windowBorder 窗口边框的颜色 controlShadow 组件的阴影颜色
    windowText 窗口内的文本颜色 controlDkShadow 组件的暗阴影颜色
    menu 菜单的背景颜色 scrollbar 滚动条的背景颜色
    menuText 菜单的文本颜色 info 帮助区文本的颜色
    text 文本的背景颜色 infoText 帮助区的文本颜色
  12. java.awt.Color 1.0
    • Color(int r,int g,int b)
      创建一个颜色对象。
      参数: r 红色值(0-255)、g 绿色值(0-255)、b 蓝色值(0-255)。
  13. java.awt.Graphics 1.0
    • Color getColor()
    • void setColor(Color c)
      获取或改变当前的颜色。所有后续的绘图操作都是用这个新颜色。
      参数:c 新颜色
  14. java.awt.Graphics2D 1.2
    • Paint getPaint()
    • void setPaint(Paint p)
      获取或设置这个图形环境的绘制属性。Color类实现了Paint接口。因此,可以使用这个方法将绘制属性设置为纯色。
    • void fill(Shape s)
      用当前的颜料填充该图形。
  15. java.awt.Component 1.0
    • Color getBackground()
    • void setBackground(Color c)
      获取或设置背景颜色。
      参数:c 新背景颜色
    • Color getForeground()
    • void setForeground(Color c)
      获取或设置前景颜色。
      参数:c 新前景颜色。

7.7 文本使用特殊字体

  1. 可以通过字体名(font dace name)指定一个字体。字体名由”Helvetica”这样的字体家族名(font family name)和一个可选的”Bold”后缀组成。
  2. 要想知道某台特定计算机上允许使用的字体,就需要调用GraphicsEnvironment类中的getAvailableFontFamilyNames方法。这个方法将返回一个字符型数组,其中包了所有可用的字体名。GraphicsEnvironment类描述了用户系统的图形环境,为了得到这个类的对象,需要调用静态的getLocalGraphicsEnvironment方法。
  3. 点数目是排版中普遍使用的表示字体大小的单位,每英寸包含72个点。
  4. 字体风格值:Font.PLAIN、Font.BOLD、Font.ITALIC、Font.BOLD+Font.ITALIC。
  5. 要想得到屏幕设备字体属性的描述对象,需要调用Graphics2D类中的getFontRenderContext方法。它将返回一个FontRenderContext类对象。
  6. 基线(baseline)是一条虚构的线。上坡度(ascent)是从基线到坡顶(ascenter)的距离。下坡度(descent)是从基线到坡顶(descenter)的距离。
  7. 行间距(leading)是某一行的坡底与其下一行的坡顶之间的空隙。字体的高度是连续两个基线之间的距离,它等于下坡度+行间距+上坡度。
  8. getStringBounds方法返回的矩形宽度是字符串水平方向的宽度。矩形的高度是上坡度、下坡度、行间距的总和,如果需要知道下坡度或行间距,可以使用Font类的getLineMetrics方法,这个方法将返回一个LineMetrics类对象。
  9. 为了能够获得中央的位置,可以使用getWidth()得到组件的宽度。使用bounds.getWidth()得到字符串的宽度。前者减去后者就是两侧应该剩余的空间,因此,每侧剩余的空间应该是这个差值的一般。高度也一样。
  10. java.awt.Font 1.0
    • Font(String name,int style,int size)
      创建一个字体对象。
      参数: name 字体名。不是字体名(例如,“Helvetica Bold”),就是逻辑字体名(例如,“Serif”、“SansSerif”)。style 字体风格(Font.PLAIN、Font.BOLD、Font.ITALIC或Font.BOLD+Font.ITALIC)。size 字体大小(例如,12)。
    • String getFontName()
      返回字体名,例如,“Helvetica Bold”。
    • String getFamily()
      返回字体家族名,例如,“Helvetica”。
    • String getName()
      如果采用逻辑字体名创建字体,将返回逻辑字体,例如,“SansSerif”;否则,返回字体名。
    • Rectangle2D getStringBounds(String s,FontRenderContext context) 1.2
      返回包围这个字符串的矩形。矩形的起点为基线。矩形顶端的y坐标等于上坡度的负值。矩形的高度等于上坡度、下坡地和行间距之和。宽度等于字符串的宽度。
    • LineMetrics getLineMetrics(String s,FontRenderContext context) 1.2
      返回测定字符串宽度的一个线性metrics对象。
    • Font deriveFont(int style) 1.2
    • Font deriveFont(float size) 1.2
    • Font deriveFont(int style,float size) 1.2
      返回一个新字体,除给定大小和字体风格外,其余与原字体一样。
  11. java.awt.font.LineMetrics 1.2
    • float getAscent()
      返回字体的上坡度—从基线到大写字母顶端的距离。
    • float getDescent()
      返回字体的下坡度—从基线到坡底的距离。
    • float getLeading()
      返回字体的行间距—从一行文本底端到下一行文本顶端之间的空隙。
    • float getHeight()
      返回字体的总高度—两条文本基线之间的距离(下坡度+行间距+上坡度)。
  12. java.awt.Graphics 1.0
    • Font getFont()
    • void setFont(Font font)
      获取或设置当前的字体。这种字体将被应用于后续的文本绘制操作中。
      参数:font 一种字体。
      • void drawString(String str,int x,int y)
        参数:str 将要绘制的字符串。x 字符串开始的x坐标。y 字符串基线的y坐标。
  13. java.awt.Graphics 1.2
    • FontRenderContext getFontRenderContext()
      返回这个图形文本中,指定字体特征的字体绘制环境。
    • void drawString(String str,float x,float y)
      采用当前的字体和颜色绘制一个字符串。
      参数:str 将要绘制的字符串。 x 字符串开始的x坐标。y 字符串基线的y坐标。
  14. javax.swing.JComponent 1.2
    • FontMetrics getFontMetrics(Font f) 5.0
      获取给定字体的度量。FontMetrics类是LineMetrics类的早先版。
  15. java.awt.FontMetrics 1.0
    • FontRenderContext getFontRenderContext() 1.2
      返回字体的字体绘制环境。

7.8 显示图像

  1. 使用Graphics类的drawImage方法将图像显示出来。
  2. java.awt.Graphics 1.0
    • boolean drawImage(Image img,int x,int y,ImageObserver observer)
      绘制一副非比例图像。注意:这个调用可能会在图像还没有绘制完毕就返回。
      参数:img 将要绘制的图像。x 左上角的x坐标。y 左上角的y坐标。observer 绘制进程中以通告为目的的对象(可能为null)。
    • boolean drawImage(Image img,int x,int y,int width,int height,ImageObserver observer)
      绘制一副比例图像。系统按照比例将图像放入给定宽和高的区域。注意:这个调用可能会在图像还没有绘制完毕就返回。
      参数:img 将要绘制的图像。x 左上角的x坐标。y 左上角的y坐标。width 描述图像的宽度。height 描述图像的高度。observer 绘制进程中以通告为目的的对象(可能为null)。
    • void copyArea(int x,int y,int width,int height,int dx,int dy)
      拷贝屏幕的一块区域。
      参数:x 原始区域左上角的x坐标。y 原始区域左上角的y坐标。width 原始区域的宽度。 height 原始区域的高度。dx 原始区域到目的区域的水平距离。dy 原始区域到目的区域的数值距离。
posted on 2018-09-11 20:47  zhangmiao14  阅读(485)  评论(0编辑  收藏  举报