JList

JList从含义上看是一个列表,有点和JComboBox相似。其实不然,JComboBox的内容只能用一列显示出来,而JList的内容可以多列显示,我想这就是JList存在的意义。

        首先是JList的构造 ,没什么特别的,给他一个对象数组就可以了,代码说明一切:
String[] words =   ;
JList wordList 
=   new  JList(words);
        然后就是JList的多列显示 , 使用setLayoutOrientation(参数)方法来实现,共有3个参数,默认值是JList.VERTICAL,只用一列来显示,但不会自动滚 动,需要添加滚动面板才能出现滚动条。setVisibleRowCount(n);方法可以设置最多显示多少行(若没有添加滚动面板,此设置无效,所有 内容均会显示)。另外两个参数是JList.VERTICAL_WRAP和JList.HORIZONTAL_WRAP,其含义分别是“在保证行数不超过 setVisibleRowCount(n)的情况下,纵向或横向排列元素”。此时滚动面板无效,因为行数永远不可能超标,因此滚动面板也永远不会出 现 。比如最大显示行数为4,总共有5个元素,显示结果如下:
        接下来就是事件的处理 , 与其他控件不同,他处理的不是Action事件,而是ListSelectionEvent事件,监听器为ListSelectionListener。 在这个事件处理过程中,又将鼠标的操作分为2种状态:1.按下鼠标不松手,在各个元素间拖动;2.松开鼠标。也就是说,当你按下鼠标后,会触发一个事件, 拖动到另一个控件,又触发一个事件,继续拖动则继续触发事件,最后松手,触发一个事件。那么,你如何区分这2种情况 呢?ListSelectionEvent提供了一个方法getValueIsAdjusting(),如果该方法返回true,则代表情况1;反之代表 情况2。同时请注意,JList控件不提供鼠标双击元素的处理事件,若要处理鼠标双击的情况,则应该添加鼠标监听器,代码如下:
public   void  mouseClicked(MouseEvent evt)
{
   
if  (evt.getClickCount()  ==   2 )
   
{
      JList source 
=  (JList) evt.getSource();
      Object[] selection 
=  source.getSelectedValues();
      doAction(selection);
   }

}
        JList还有一个很有趣的特性,就是你根本没必要把元素存入一个数组,只要能临时把元素计算出来就行。 具体实现方法就是继承AbstractListModel类,实现其中的2个方法即可,代码如下:

class  WordListModel  extends  AbstractListModel
{
   
/**
      Constructs the model.
      
@param  n the word length
   
*/

   
public  WordListModel( int  n)  { length  =  n; }

   
public   int  getSize()
   
{
      
return  ( int ) Math.pow(LAST  -  FIRST  +   1 , length);
   }


   
public  Object getElementAt( int  n)
   
{
      StringBuilder r 
=   new  StringBuilder();;
      
for  ( int  i  =   0 ; i  <  length; i ++ )
      
{
         
char  c  =  ( char )(FIRST  +  n  %  (LAST  -  FIRST  +   1 ));
         r.insert(
0 , c);
         n 
=  n  /  (LAST  -  FIRST  +   1 );
      }

      
return  r;
   }


   
private   int  length;
   
public   static   final   char  FIRST  =   ' a ' ;
   
public   static   final   char  LAST  =   ' z ' ;
}
        接下来就是元素的插入和删除了 , 这个看似简单的功能,实现起来可不是一件容易的事情。最天真的想法:我用一个数组构造JList,那么我只要将数组中的元素增加或减少,那么JList的 内容自然会增加或减少。这绝对是个错误的认识,对数组内容的修改不会影响到JList。正确的做法是,用一个特别的类来构造JList,也就是DefaultListModel 类,然后对这个类的内容添加或者减少,那么JList会很快的做出响应。为什么这个类会这么神奇呢?查看他的源代码得知,他继承自 AbstractListModel类,内部用一个Vector来存储数据。在它的添加元素方法中,他调用了父类的fireIntervalAdded方 法,同理,在他的删除元素方法中,他调用了父类的fireIntervalRemoved方法,因此可以将JList的内容刷。
    最后就是内部元素的绘制了。 在 JList中,内部显示的每一个元素叫做一个Cell。如果我想让内部元素的显示方式更完美一些,比如居中显示,比如每一个Cell字体颜色不一样,那么 我们就要借助JList的setCellRenderer方法来实现。该方法接受一个实现了ListCellRenderer接口的参数,而该接口只有一 个方法getListCellRendererComponent,但是,该方法的实现是比较简单的,他只需要构造一个Component对象并返回这个 对象,这个对象就是一个Cell。因此,真正的难点在于,如何修改这个Component的内部显示方式,从而使得他可以满足一个Cell的显示方式。一 般来讲,我们都是用一个JPanel作为绘制Cell的对象,因为在JPanel上显示文字和图像都是很方便的。最后说一个小技巧,我们实现一个类,从 JPanel继承而来,同时又实现了ListCellRenderer接口,那么我们只用实现这一个类就可以了,到时候把自己返回,呵呵,真的好方便哦。 下面我们来看一下具体的代码:
  class  FontCellRenderer  extends  JPanel  implements  ListCellRenderer
 
{
    
public  Component getListCellRendererComponent(JList list, Object value,  int  index,
       
boolean  isSelected,  boolean  cellHasFocus)
    
{
       text 
=  (String)value;
       background 
=  isSelected  ?  list.getSelectionBackground() : list.getBackground();
       foreground 
=  isSelected  ?  list.getSelectionForeground() : list.getForeground();
       
return   this ;
    }


    
public   void  paintComponent(Graphics g)
    
{
       g.setColor(background);
       g.fillRect(
0 0 , getWidth(), getHeight());  //设置背景色
       g.setColor(foreground);
       g.drawString(text, 
5 15 );    // 在制定位置绘制文本
    }


    
public  Dimension getPreferredSize()
    
{
       
return   new  Dimension( 30 20 );    // Cell的尺寸
    }


    
private  String text;
    
private  Color background;
    
private  Color foreground;
 }

    我们来简单分析一下上面的代码。我们定义了一个类,继承自JPanel并实现了指定接口。在这个类里面有3个私有变量,分别存放Cell的内容,Cell 的前景色和背景色。因为Cell的绘制完全由程序员来实现,因此这些内容都是必须的。之后就是接口中规定的 getListCellRendererComponent方法,这个方法其实很简单,就是对三个变量进行赋值并返回自己。其中前景色和背景色又分为2中 情况,就是选中时和未选中时,这点需要注意。接下来我们有实现了2个方法,其中PaintComponent负责Cell的绘 制,GetPreferedSize负责设置Cell的尺寸。对于尺寸有一点需要注意,上述代码给的是一个固定尺寸。如果尺寸不固定有变化,那么最终会选 择最大的那个尺寸作为所有Cell的尺寸。如果你想在绘制Cell的时候加入什么花样,那么尽管在PaintComponent中施展你的才华吧,上述代 码只提供了在指定位置绘制文本,算是抛砖引玉了。这里也有一点需要注意,那就是JPanel本身提供的“居中”,“设置背景色”,“设置前景色”,等方法 一律失效,所有的功能一律要使用JAVA 2D来实现,算是一点小小的难度。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值