`

Swing框架之Component:续文三

阅读更多

Swing框架之Component:续文三

Swing事件与事件处理器模型

         Component在Swing模型中是事件触发源。前一篇文章在描述Swing的事件处理模型时就已经提到了这个事件处理过程。简单来说,Swing组 件在侦听到原生事件并处理后,往往产生新的逻辑事件。逻辑事件是某些组件所特有的、具有特定语义的事件,比如JButton按下时产生 ActionEvent、JComboBox一项被选中时产生ItemEvent,等等。和原生事件不同,它们并不被派发到系统事件队列中,而是由组件直 接触发。事件处理器作为组件的观察者添加到组件上并侦听触发的事件。假设事件名叫XXX,Swing中实现这个模式的一般模式是:

1.定义一个XXXEvent

public class XXXEvent extends Event{
    ...
    public void XXXEvent(Object src){
        super(src);
        ...
     }
   
...
}

2.定义一个事件处理器接口XXXListener,声明所有和该事件相关的处理方法:

public interface XXXListener extends EventListener{
    void action1(XXXEvent evt);
    void action2(XXXEvent evt);
    ...
}

3.在触发它的组件中定义一下方法:

public class MyComponent extends Jcomponent{
   
...
   
//存放事件处理器的队列
   
private ArrayList<XXXListener>xxxListeners=new ArrayList<XXXListener>();
       
//定义以下各种方法,访问符号用public,以方便添加删除处理器
       
public void addXXXListener(XXXListener listener){
           
xxxListeners.add(listener);
       
}
       
public void removeXXXListener(XXXListener listener){
           
xxxListeners.remove(listener);
       
}
       
//定义各种触发(fire)action1、action2...的方法,注意一般使用protected,以便继承和扩展
       
//每一个action都要定义一个相应触发(fire)的方法
       
protected void fireAction1(XXXEvent evt){
           
for(XXXListener listener:xxxListeners){
               
listener.action1(evt);
           
}
       
}
       
protected void fireAction2(XXXEvent evt){
           
for(XXXListener listener:xxxListeners){
               
listener.action2(evt);
       
}
   
}
   
...
   
//在某些地方,比如鼠标处理函数中触发相应的动作
   
void myMouseReleased(MouseEvent evt){
       
...
       
if(应该触发action1)
           
fireAction1(new XXXEvent(this));
       
...
       
if(应该触发action2)
           
fireAction2(new XXXEvent(this));
       
...
    
}
}

         XXXEvent、XXXListener、addXXXListener、removeXXXListener以及各种fireAction函数多是重复性代码,有些Java IDE如JBuilder中能够根据开发者的指定参数的自动生成这些代码。

         实际上这个观察者模式的编程范式可以推广到任何JavaBeans,不一定是可视化的Swing组件。以前曾经见过JBuilder做的一个所谓数据库操 作的JavaBeans,它没有界面,但它和Swing组件完全一样添加删除处理器。它的功能是异步操作数据库,在数据操作完了之后触发注册在上面的事件 处理器,该事件处理器就可以将查询结果展现在表格中,或者输出成报表等等。

         在这个模型中,JavaBeans本身既可以是事件源(被观察对象),也可以是事件处理器(观察者),JavaBeans也可以侦听自身的事件并且处理。 比如前面文章所提的MyButton在处理鼠标事件时就是自己侦听自己发出的鼠标事件,自己既是事件源,又是事件处理器,形成自反系统。各种各样的 JavaBeans通过这种机制联系成一张事件网,各种JavaBeans就是这个网上的节点,而它们之间的事件触发与事件处理关系就是这张网络上的线。 当某个节点被外界或自身发出的事件所触发时,行成了事件的传播。这个过程很像网络上节点的振动引起周围周围节点振动的模型。下图示意了这种 JavaBeans之间的事件网:

         例如new JscrollPane(new JtextArea())这个系统,它里面包括两个JScrollBar和一个JTextArea,当鼠标拖动事件触发JScrollBar时, JScrollBar处理了这个鼠标拖动事件,并发出滚动条拖动事件,这个事件传播给JTextArea,JTextArea处理这个拖动事件,相应的更 新自己显示的内容,如果JTextArea之后又根据更新发出了一个新的事件,这个事件便会继续传播下去。

Swing布局管理器

         现在高级图形用户界面工具一般都包括布局管理器机制。什么叫做布局管理器?如果所有窗口的大小是不变的,那么我们在往窗口中添加组件时,只要将组件的拖放 到固定位置、调整好尺寸就可以了,就像VB的界面工具一样。可大多数情况并非如此,用户经常需要调整窗口的大小,以便和其他程序协同工作。这种情况下,在 传统界面工具中,比如VB,就需要显式的侦听窗口尺寸调整事件,根据当前窗口的大小重新计算并调整各个组件的大小和位置。AWT/SWT/Swing将这 个过程自动化、模块化了,抽象出一个布局管理器来负责管理界面组件的布局。

         它们实现原理是相似的:容器类组件侦听初始化、invalide/validate以及容器尺寸调整等事件,一旦发生这些事件,容器类组件检查自己是否配 置了布局管理器,如果没有,则不做任何事情;如果有,则将容器内组件的布局代理给布局管理器,让它来完成容器内组件的重新布局。

         容器管理器对象对实现两类接口:LayoutManager和LayoutManager2,LayoutManager2是LayoutManager的一个扩展,允许组件在添加时指定位置参数。它们的定义和含义如下:

public interface LayoutManager {
   
//添加组件comp,并和name关联起来,name可以作为位置等特殊含义参数来使用
   
void addLayoutComponent(String name, Component comp);
   
//删除组件comp
   
void removeLayoutComponent(Component comp);
   
//根据容器内的当前组件,计算容器parent的最优尺寸。
   
Dimension preferredLayoutSize(Container parent);
   
//根据容器内的当前组件,计算容器parent的最小尺寸。
   
Dimension minimumLayoutSize(Container parent);
   
//重新布局容器parent,这儿是主要布局逻辑所在。
   
void layoutContainer(Container parent);
}
public interface LayoutManager2 extends LayoutManager {
   
//添加组件comp,constraints用作指定如何以及位置的参数,这个函数主要是弥补LayoutManager版的addLayoutComponent表达能力欠缺而添加。
   
void addLayoutComponent(Component comp, Object constraints);
   
//根据容器内的当前组件,计算容器parent的最大尺寸。看来除了最优、最小,某些情况下还是需要知道最大。
   
public Dimension maximumLayoutSize(Container target);
   
//指定水平方向上组件之间的相对对齐方式,0表示和源组件对齐,1表示远离源组件。
   
public float getLayoutAlignmentX(Container target);
   
//指定垂直方向上组件之间的相对对齐方式,0表示和源组件对齐,1表示远离源组件。
   
public float getLayoutAlignmentY(Container target);
   
//invalidate这个布局管理器,有时布局管理器为了计算迅速,可能第一次计算之后就将一些数据给缓冲,但是后容器内的组件数目发生变化,这儿的缓冲值就需要调用这个方法通知更新
   
public void invalidateLayout(Container target);


}

         Swing在java.awt和javax.swing中都分别提供大量的布局管理器,这些布局管理器有简单的如FlowLayout,有复杂的如GridBadLayout。用户还可以自己定义自己的布局管理器,由于篇幅原因,这儿略去例子。

         Java 6中在布局管理中引入了BaseLine / Anchor的概念,能协助Java IDE的用户界面设计工具,方便用户来设计布局组件。NetBeans的Matisse组件首先引入了一个GroupLayout布局管理器,结合 Matisse使用,提供了非常方便的布局管理和界面设计。GroupLayout和BaseLine/Anchor概念以及Matisse可以说是 Java界面设计工具的一大进步,可以说足以成为Java桌面应用史上的一个里程碑。在这之前,缺乏有力的界面设计工具是Java在桌面应用失败的一个重 要原因。虽然Anchor概念早就在Delphi界面设计工具出现过,但是这个工具的出现还是Java界面设计史上的一大事件。随着Java 6桌面应用支持的增强,以及NetBeans Matisse之类界面设计工具的出现,使得Java桌面应用时代已经到来。Seeing is believing,你不妨试一下就知道了。

=====================================

         本想再加一节讲述Swing双缓冲机制,但是想到双缓冲并不是Swing模型的核心概念,没有它并不影响理解Swing的总体模型,因此打算把它作为以后的一篇专门技术文章来写。

         这样Swing模型中的Component部分就算是描述完了,从明天开始,讲述Swing模型中的另外三个重要概念:Model、UI Delegate和Renderer。

分享到:
评论

相关推荐

    Swing框架定制Component

    ### Swing框架定制Component详解 Swing作为Java图形用户界面(GUI)编程的重要组成部分,提供了丰富的组件库和灵活的自定义选项。本文旨在深入探讨Swing框架中Component的定制方法,特别是GUI的绘制机制以及Swing的...

    精通java-swing开发.doc

    `JComponent`是Swing组件层次结构的基础,它扩展了AWT的`Component`类,添加了许多高级特性,如内置的事件处理、可定制的外观(LookAndFeel)以及丰富的组件属性。通过`JComponent`,开发者可以方便地自定义组件的...

    Java Swing大神必经之路

    第3篇 Java Swing大神必经之路3:JavaSwing-AbstractButton详解 本篇文章对 AbstractButton 进行了详细的介绍,包括其定义、构造方法、setParameter() 等,幫助讀者更好地理解 AbstractButton 的使用。 第4篇 Java ...

    swing教程之经典

    - **Swing概述**:Swing是Java中用于构建GUI应用程序的一个轻量级组件库,它是建立在AWT基础之上的一个高级框架。Swing组件不仅提供了更丰富的功能,而且在不同操作系统上具有一致的表现形式,这主要得益于Swing采用...

    swing框架详细讲解

    Swing框架是Java GUI开发中的一个重要部分,它是建立在AWT(Abstract Window Toolkit)之上,提供了更丰富的组件和更现代的用户界面。Swing使用Java2D API来绘制组件,确保了平台独立性,使得在不同操作系统上都能...

    Java_Swing_with_Samples.pdf

    Java Swing是Java平台的一个图形用户界面(GUI)工具包,它构建于AWT之上,并提供了一系列更丰富、更强大的组件来帮助开发者创建美观且功能丰富的应用程序。Swing不仅支持基本的GUI组件如按钮、文本框等,还提供了更...

    Java Swing桌面开发经典案例

    3. **布局管理**: Swing提供多种布局管理器,如FlowLayout、BorderLayout、GridLayout、CardLayout和BoxLayout,用于控制组件在容器中的排列方式。通过灵活使用布局管理器,开发者可以创建出符合不同设计需求的用户...

    Swing用户界面设计

    Swing用户界面设计是Java...总的来说,Swing用户界面设计提供了一个强大而灵活的框架,用于构建功能丰富的Java应用程序。通过深入理解和熟练掌握Swing,开发者可以创建出符合现代用户需求的、具有吸引力的图形界面。

    swing圆角矩形按钮

    根据给定的信息,本文将详细解释如何在Java Swing框架中创建具有圆角效果的自定义按钮。这将涉及Swing的基本概念、自定义组件的方法以及如何实现特定的视觉效果。 ### Swing简介 Swing是Java平台的一个图形用户...

    计算机软件及应用jaaPPT课件.pptx

    Swing组件的继承层次结构始于`java.lang.Object`,然后是`java.awt.Component`,接着是`java.awt.Container`,再是`javax.swing.JComponent`。从`JComponent`派生出的常用组件包括`JLabel`, `JTextField`, `...

    Swing之JTable详解

    在Swing框架中,`JTable`是构建GUI应用程序中表格的主要组件。它继承自`JComponent`类,这使得`JTable`能够支持丰富的图形用户界面功能。下面展示了`JTable`的类层次结构: 1. `java.lang.Object` - `java.awt....

    swing jframe 窗体抓取 (源码)

    例如,可以使用JUnit或TestNG等单元测试框架,结合Swing提供的`Robot`类来模拟键盘和鼠标操作,配合窗体抓取技术,实现对GUI应用的自动化测试。 在这个项目中,"AmsSwing"可能是项目的源代码文件夹,包含了实现窗体...

    swing演示排序动画

    本项目通过Swing框架实现了一个动态演示排序过程的应用程序。主要目标是让用户能够直观地看到各种排序算法(例如冒泡排序、插入排序等)在数组上的执行过程。 #### 二、程序结构分析 ##### 1. `AlgorithmAnimation...

    java GUI 参考资料

    11. **Swing框架之Component**:"Swing框架之Component.txt"可能深入讨论了Component类,它是所有Swing组件的基类,包含了一些基本的属性和方法,如可见性、尺寸、位置等。 以上就是基于给定的文件名和描述所推断出...

    cyber_kustom_component:该框架旨在帮助开发接口,为组件提供易于编辑的特征

    cyber_kustom_component 该项目旨在开发具有可定制的Swing组件的库。 使用Cyber​​KustomComponent库,您可以快速编辑组件的主要视觉特征。 要将新组件添加到netbeans面板,请。 可以通过下载Jar 版本0.1.0具有...

    Component.jar 自己封装的框架

    基于SWing,聊天软件的框架。 可以重用,基本修改,是改变了所有的透明特性。

    JavaSwing用户界面设计[IT_CLUB].doc

    Swing组件的类层次结构主要建立在AWT的Component和Container类之上。JComponent是大部分Swing组件的基类,它扩展了AWT的Component,添加了更多的特性和功能。 5. Swing包: Swing包含多个子包,如javax.swing.*,...

    Java教程编程中国\\JAVA教程 第七讲 Swing用户界面设计

    创建一个Swing应用程序的基本步骤包括设置主类、初始化框架、添加组件以及设置布局管理器。 **5.2 使用Swing组件** Swing提供了丰富的组件库,如按钮、文本框、列表、树等。开发者可以通过调用组件类的方法来定制...

    Swing换肤——JavaSE技术

    Swing则是在AWT之上构建的,它使用纯Java实现,因此提供了更好的跨平台一致性。Swing组件不仅比AWT更丰富,还支持自定义外观,这使得实现换肤成为可能。 Swing的外观(LookAndFeel)机制允许开发者通过更换不同的...

Global site tag (gtag.js) - Google Analytics