[翻译]核心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("Button.foreground", Color.RED);
 

获取UIResource属性

如果我们正在创建自己的组件,或者是我们只需要查看当前的设置值,我们可以请求UIManager。尽管public static Object get(Object key)方法是最为通用的,却需要我们将返回值转换为合适的类型。相对应的,我们可以下列更为特定的getXXX()方法,这些方法会为我们执行錾,从而返回合适的类型:

public static boolean getBoolean(Object key)
public static Border getBorder(Object key)
public static Color getColor(Object key)
public static Dimension getDimension(Object key)
public static Font getFont(Object key)
public static Icon getIcon(Object key)
public static Insets getInsets(Object key)
public static int getInt(Object key)
public static String getString(Object key)
public static ComponentUI getUI(JComponent target)
 

这是一组接受Locale参数的重载的方法集合。

客户属性

除了UIManager维护一个key/value对设置以外,每一个组件实例还维护一个自己的key/value对集合。这对于维护一个不同于一定观感的组件或者是维护与一个组件关联的数据而不需要新类或是方法来存储这些数据的情况十分有用。

public final void putClientProperty(Object key, Object value)
public final Object getClientProperty(Object key)
 

例如,JTree类具有一个属性通过Metal观感来连接线风格或是显示JTree中的节点。因为设置特定于一个观感,因而向树API中添加一些内容并不合理。相反,我们可以通过下面的代码在一个特定的树实例上设置属性:

tree.putClientProperty(" JTree.lineStyle", " None")

然后,当观感是默认的Metal时,树的节点将会用线连接。如果安装了其他的观感,客户属性就会被忽略。图4-2显示具有与不具有线的树。

Swing_4_2

4.1.2 JComopnent属性

我们已经了解了一些不同的JComponent子类所共享的属性。现在是了解JavaBean属性的时候了。表4-2显示了JComponent所定义的完整属性列表,包括由AWT Container为戌Component类所继承的属性。

JComponent属性

属性名数据类型组件访问容器访问JComponent访问
accessibleContextAccessibleContext

只读

N/A

只读

actionMap

ActionMap

N/A

N/A

读写

alignmentX

float

只读

只读

读写

alignmentY

float

只读

只读

读写

ancestorListeners

AncestorListener[]

N/A

N/A

只读

autoscrolls

boolean

N/A

N/A

读写

background

Color

读写绑定

N/A

只写

backgroundSet

boolean

只读

N/A

N/A

border

Border

N/A

N/A

读写绑定

bounds

Rectangle

读写

N/A

N/A

colorModel

ColorModel

只读

N/A

N/A

componentCount

int

N/A

只读

N/A

componentListeners

ComponentListener[]

只读

N/A

N/A

componentOrientation

ComponentOrientation

读写绑定

N/A

N/A

componentPopupMenu

JPopupMenu

N/A

N/A

读写

components

Component[]

N/A

只读

N/A

containerListeners

ContainerListener[]

N/A

只读

N/A

cursor

Cursor

读写

N/A

N/A

cursorSet

boolean

只读

N/A

N/A

debugGraphicsOptions

int

N/A

N/A

读写

displayable

boolean

只读

N/A

N/A

doubleBuffered

boolean

只读

N/A

读写

dropTarget

DropTarget

读写

N/A

N/A

enabled

boolean

读写

N/A

只写绑定

focusable

boolean

读写绑定

N/A

N/A

focusCycleRoot

boolean

N/A

读写绑定

N/A

focusCycleRootAncestor

Container

只读

N/A

N/A

focusListeners

FocusListener[]

只读

N/A

N/A

focusOwner

boolean

只读

N/A

N/A

focusTraversalKeyEnabled

boolean

读写

N/A

N/A

focusTraversalPolicy

FocusTraversalPolicy

N/A

读写绑定

N/A

focusTraversalPolicyProvider

boolean

N/A

读写绑定

N/A

focusTraversalPolicySet

boolean

N/A

只读

N/A

font

Font

读写绑定

只写

只写

fontSet

boolean

只读

N/A

N/A

foreground

Color

读写绑定

N/A

只写

foregroundSet

boolean

只读

N/A

N/A

graphics

Graphics

只读

N/A

只读

graphicsConfiguration

GraphicsConfiguration

只读

N/A

N/A

height

int

只读

N/A

N/A

hierarchyBoundsLIsteners

HierarchyBoundsListener[]

只读

N/A

N/A

hierarchyListeners

HierarchyListener[]

只读

N/A

N/A

ignoreRepaint

boolean

读写

N/A

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值