当前位置:编程学习 > JAVA >>

核心Swing组件(一)

在第3章,我们简要介绍了JFC/Swing工程组件所用的Model-View-Controller(MVC)模式。在本章中,我们将会开始探讨如何使用许多可用组件中的关键部分。

所有的Swing组件都是以JComponent类为起点的。尽管Swing库的某些部分并不以JComponent类为根,但所有的组件在其继承的某些级别上共享JComponent类作为通用父类。JComponent类定义通用的行为与属性。在本章中,我们将会了解一些通用功能,例如组件绘制,自定义义,工具提示以及变化大小。

随着特定JComponent子孙类被关注 ,我们将会特别了解JLabel,JButton以及JPanel,三个更为广泛使用的Swing组件类。为了组件内显示图像,我们需要理解Icon接口,以及当使用预定义图像时的ImageIcon类与GrayFilter类的支持。另外,我们将会了解AbstractButton类,他是JButton类的父类。所有的AbstractButton的子类所共享的数据模型是ButtonModel接口;我们将会探讨这个接口及其特定实现,DefaultButtonModel。

4.1 JComponent类

JComponent类是所有的Swing组件继承的抽象基类。JComponent类有42个派生子类,每一个都继承了JComponent的功能。图4-1显示了继承层次结构。

尽管JComponent类是所有Swing组件的共同基类,但是Swing工程库中的许多类并不是由JComponent类派生类。这包括所有的高层窗口对象,例如JFrame,JApplet以及JInternalFrame;所有的MVC相关的类;事件处理相关的接口与类;等。所有这些类将会后面的章节中进行讨论。

尽管所有的Swing组件扩展JComponent,JComponent类扩展AWT的Container类,相应的,其扩展AWT的Component类。这就意味着许多的JComponent方面都是由AWT的Component与Container类所共享的。

4.1.1 组件分片

JComponent类定义了许多超出原始的AWT组件集合功能的AWT组件面。这包括自定义绘制行为以及自定义显示设置的不同方法,例如颜色,字体以及其他的客户端设置。

绘制JComponent对象

因为Swing的JComponent类是由Container类扩展而来的,因而会遵循基本的AWT绘制模型:所有的绘制都是通过paint()方法来完成的,而repaint()方法则用来触发更新。然而,许多任务的完成是不同的。JComponent类优化了绘制的许多方面从而改进性能与可扩展性。另外,RepaintManager类可以用来自定义绘制行为。

为了改进绘制性能与扩展性,JComponent将绘制操作分为三个任务。public void paint(Graphics g)方法被分为三个独立的protected方法调用。由调用的顺序,他们依次为paintComponent(g), paintBorder(g)以及paintChildren(g),通过原始的paint()调用传递Graphics参数。组件本身首先通过paintComponent(g)进行绘制。如果我们希望自定义Swing组件的绘制,我们可以重写paintComponent()方法而不是paint()方法。除非我们希望完全替换所有的绘制,我们需要首先调用super.paintComponent(),正如下面所示的,来获得默认的paintComponent()行为。

public class MyComponent extends JPanel {
  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    // Customize after calling super.paintComponent(g)
  }
  ...
}

paintBorder()与paintChildren()方法是不可重写的。paintBorder()方法绘制组件周围的边框,第7章会对其概念进行更为完全的描述。如果在Swing容器对象内存在组件,则paintChildren()方法会绘制这些组件。

为了优化绘制,JComponent类提供了三个额外的绘制属性:opaque, optimizedDrawingEnabled以及doubleBuffered。其作用如下:

  • Optacity:JComponent的opaque属性定义了一个组件是否透明。当透明时,JComponent容器必须在组件之后绘制背景。为了改进性能,我们可以保留JComponent的不透明物并使得JComponent绘制其背景,而不要依赖于容器来绘制被覆盖的背景。
  • Optimization:optimizedDrawingEanbled属性紧邻的子元素是否可以重叠。如果子元素不可以重叠,可以极大的减少重绘时间。在默认情况下,优化绘制对于绝大多数的Swing组件是允许的,除了JDesktopPane,JLayeredPane以及JViewport。
  • Double buffering:在默认情况下,所有的Swing组件会将他们的绘制操作重复缓存到一个完整的容器层次结构所共享的缓冲区中;也就是,在一个窗体内的所有组件。这极大的改善了绘制性能,因为当允许双缓冲时(通过doubleBuffered属性),只有一个屏幕更新绘制。

JComponent的public void revalidate()方法也提供绘制支持。当这个方法被调用时,组件的高级容器会验证其本身。这与AWT的直接调用高级组件的revalidate()方法不同。

Swing组件绘制加强的最后一个方面就是RepaintManager类。

RepaintManager类

RepaintManager类负责保证当前显示的Swing组件之上的重绘请求的高效,确保当一个区域无效时只更新屏幕的最小“脏”区域。

尽管不能进行自定义,RepaintManager是公开并且提供了一个静态的安装例程来使用自定义管理器:public static void setCurrentManager(RepaintManager manager)。要获得当前的管理器,只需要调用public static void currentmanager(JComponent)方法。参数通常为null,除非我们已经自定义了管理器来提供组件级别的支持。一旦我们拥有管理器在,我们可以做的一件事就是将屏幕缓冲区获取为图像。因为缓冲区就是实际显示在屏幕上的内容,这可以使得我们高效的实现窗体内部的屏幕复制。

Component comp = ... 
RepaintManager manager = RepaintManager.currentManager(null);
Image htmlImage = manager.getOffscreenBuffer(comp, comp.getWidth(),
  comp.getHeight());
// or
Image volatileImage = manager.getVolatileOffscreenBuffer(comp, comp.getWidth(),
  comp.getHeight());

表4-1显示了RepaintManager的两个属性。他可以使得我们禁止一个组件(层次结构)的所有绘制操作的双缓冲,并且设置最大的双缓冲尺寸,默认为终端用户的屏幕尺寸。

RepaintManager属性

属性名
数据类型

可访问性

doubleBufferingEnabled
boolean

读写

doubleBufferMaximumSize
Dimension

读写

尽管很少实现,提供我们自己的RepaintManager子类确实允许我们自定义屏幕脏区域的绘制机制,或者是当绘制完成时的最少跟踪。重写下面四个方法的一个可以允许我们自定义机制:

public synchronized void addDirtyRegion(JComponent component, int x, int y,
  int width, int height)
public Rectangle getDirtyRegion(JComponent component)
public void markCompletelyClean(JComponent component)
public void markCompletelyDirty(JComponent component)

UIDefaults类

UIDefaults类表示为当前的观感所安装的包含显示设置的查询表,例如JList中所用的字体,在JTree节中所显示的颜色或图标。UIDefaults的使用将会在第20章探讨Java可插拨的观感体系结构时进行详细讨论。在这里,我们只是简要介绍UIDefaults表。

当我们创建一个组件时,组件会自动的请求UIManager在UIDefaults表中查找组件所用的当前设置。大多数的颜色,字体相关的组件设置,以及其他的一些与颜色与字体无关的设置,都是可配置的。如果你不喜欢一个特定的设置,我们可以简单的通过更新UIDefaults查询表中的相应项目进行修改。

首先我们需要知道我们希望修改的UIDefaults设置的名字。我们可以在本书的附录A中找到这些设置名字,在这个附录中包含J2SE 5.0中预定义观感的所有已知设置的完整列表。(由于发行版本的不同会略有不同。)另外,包含有每个组件描述的是一个包含UIResource相关属性元素的表。(要查找本书中特定组件部分,请查看内容表或是索引。)

一旦我们知道了设置的名字,我们可以使用UImanager的public static void put(Object key, Object value)方法来存放一个新的设置,其中key是键值字符串。例如,下面的代码会将新创建的按钮的背景颜色改变黑色,而前景色改变红色:

UIManager.put("Button.background", Color.BLACK);
UIManager.put("
		
	
补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,