详解所有的Swing核心组件

开发 后端
本文详细介绍Swing核心组件,以及展示创建一个自定义组件,类似WINDOWS Vista Explorer 中新的 view slider。这个组件按看上去很像一个滑标嵌入一个pop-up menu。

当提到比较awt组件和Swing组件的区别时, 首先被提到的就是Swing 是轻量级的(lightweight).确切的说其按钮、框架和菜单都没有使用本地化控制(native controls).所有组件包括渲染和事件处理都是靠纯java控制的。这给我们提供了很多方法去创建真正与平台无关的组件,而创建一个在所有平台上外观一致的自定义组件并非一件简单的事,这篇文章将演示如何创建自定义组件的过程并高亮显示重点、步骤和易犯的错误。

基础部分

Swing architecture overview这篇文章提供了非常优秀的Swing结构和开发的高级概述(high-level overview)。虽然创建组件要遵循一些规则会略微有点麻烦,不过最终代码会更容易理解。它遵循”不重复发明轮子”的原则。最初你会想要把所有的东西都集中到一个类里,包括扩展API,模型处理(状态和通知),事务处理,布局和绘制。但是按照MVC (model-view-controller)结构将其划分为多个类可以让你的组件代码更容易理解,并且从长远来说更加容易扩展。
所有Swing核心组件的主要部分如下:

◆组件(component)类本身,他负责提供创建、修改和查询组件状态的API
◆模型接口和和模型接口的默认实现,它负责处理组件的业务逻辑和组件改变通知
◆UI delegate 负责处理组件布局,事件处理(鼠标和键盘事件)以及组件的绘制。

本文将配图展示创建一个自定义组件,类似WINDOWS Vista Explorer 中新的 view slider。这个组件按看上去很像一个滑标嵌入一个pop-up menu。但他和常规的JSlider又有所不同,首先,它会含有关联标签(labels)和图标(icon)的选项(control points),其次,若range是相邻的,(如Small Icons和Medium Icons),能够动态的修改图标大小,若range是非关联的(如Tiles-Details),滑块只能滑动到这些选项上,不能滑动到这些选项之间的位置。

Windows Vista OS 中的 View slider

组件类:UI Delegate 装配
自定义组件的***个类就是组件本身的API,这个API足够简单并且委托大部分业务逻辑给模型(参考下一章),除此之外,为了设置合适的UI delegate,你需要增加一个样板(boilerplate)(详细介绍请参考Enhancing Swing Applications 一文),最终,你的代码应该是类似这样的:

  1. privatestaticfinalStringuiClassID="FlexiSliderUI";  
  2.  
  3. publicvoidsetUI(FlexiSliderUIui){  
  4. super.setUI(ui);  
  5. }  
  6.  
  7. publicvoidupdateUI(){  
  8. if(UIManager.get(getUIClassID())!=null){  
  9. setUI((FlexiSliderUI)UIManager.getUI(this));  
  10. }else{  
  11. setUI(newBasicFlexiSliderUI());  
  12. }  
  13. }  
  14.  
  15. publicFlexiSliderUIgetUI(){  
  16. return(FlexiSliderUI)ui;  
  17. }  
  18.  
  19. publicStringgetUIClassID(){  
  20. returnuiClassID;  

这里需要注意的一点是:你需要提供一个可靠的UI delegate,如果当前安装的look and feel 没有提供特殊的UI delegate时,这个UI delegate将处理组件的绘制,布局和事件处理。


模型接口

这可能是这个组件最重要的接口了。它将从业务层面表现的你的组件功能。模型接口不要包含任何和界面绘制相关的方法(像setFont或getPreferredSize)。我们的组件将遵循LinearGradientPaint API并且定义模型为一些range序列:

  1. publicstaticclassRange{  
  2. privatebooleanisDiscrete;  
  3.  
  4. privatedoubleweight;  
  5.  
  6. publicRange(booleanisDiscrete,doubleweight){  
  7. this.isDiscrete=isDiscrete;  
  8. this.weight=weight;  
  9. }  
  10.  
  11. ...  

模型中设置和查询range的API

  1. public void setRanges(Range... range);     
  2. public int getRangeCount();       
  3. public Range getRange(int rangeIndex); 

这个模型还提供当前值对象的get和set方法:
模型接口的***一部分为增加/移除变化监听器(ChangeListeners)的方法,他遵循Swing核心组件的model接口风格(参考BoundedRangeModel);

  1. void addChangeListener(ChangeListener x);     
  2. void removeChangeListener(ChangeListener x);    


模型实现

模型的实现类非常简单,参考DefaultBoundedRangeModel,变化监听器(ChangeListeners)使用EventListenerList来保存。当模型值被改变时将触发ChangeEvent:

  1. protectedvoidfireStateChanged(){  
  2. ChangeEventevent=newChangeEvent(this);  
  3. Object[]listeners=listenerList.getListenerList();  
  4. for(inti=listeners.length-2;i>=0;i-=2){  
  5. if(listeners[i]==ChangeListener.class){  
  6. ((ChangeListener)listeners[i+1]).stateChanged(event);  
  7. }  
  8. }  

以上为Swing核心组件源代码,我们从后向前检索所有listener.提取出stateChanged方法实现来执行。相关方法非常简单,检查值是否有效,并且复制slider ranges数组(之所以这样做是为了让那些恶意程序代码不能直接作用于model)

【编辑推荐】

  1. 浅谈Java Swing的连接数据库
  2. 介绍JFace、Swing、AWT和SWT
  3. 详解SwingWorker与Swing程序
  4. 介绍轻量级Swing组件
  5. Swing组件都扩展自JComponent
责任编辑:佚名 来源: eNet硅谷动力
相关推荐

2009-07-17 12:54:13

2009-07-10 12:30:12

Swing组件

2009-07-15 10:52:13

JTree组件

2023-02-09 08:01:12

核心组件非阻塞

2009-07-15 13:06:38

Swing组件

2009-07-10 18:06:59

JTree Swing

2019-05-28 12:03:59

vuejavascript前端

2024-01-10 12:26:16

2009-07-15 16:18:08

JSci.swing包

2009-07-17 14:57:41

SwingWorkerSwing程序

2009-07-09 11:55:17

Swing模型过滤

2009-07-14 17:21:42

Swing组件

2009-07-15 11:02:32

Swing组件

2009-07-17 11:13:46

AWT和SwingSwing组件

2009-07-17 14:38:51

轻量级Swing组件

2009-07-10 17:03:17

AWT组件Swing组件

2009-07-10 16:29:32

Swing组件

2009-07-14 18:05:28

轻量级Swing组件

2009-07-10 16:14:29

MVC设计模式Swing

2009-07-10 10:19:57

JFormattedTSwing
点赞
收藏

51CTO技术栈公众号