JList用法小结

news/2024/7/24 5:02:14
 

JList用法小结


今天从《java核心编程》中学习了JList 的用法,写下自己的感受,以免时间久了又忘记了。JList从含义上看是一个列表,有点和JComboBox相似。其实不然,JComboBox的内容只能用一列显示出来,而JList的内容可以多列显示,我想这就是JList存在的意义。

首先是JList的构造,没什么特别的,给他一个对象数组就可以了,代码说明一切:

String[] words =   { "quick", "brown", "hungry", "wild"} ;
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来实现,算是一点小小的难度。

http://www.niftyadmin.cn/n/523349.html

相关文章

java通讯录管理系统的设计与实现

一、课题要求 1. 设一个通信录由以下几项数据信息构成 数据项 类型 姓名 字符串 地址 字符串 邮政编码 字符串 电话号码 字符串 2. 主要功能 &#xff08;1&#xff09; 能建立、查询、修改和增删学生通讯…

SQL Server数据库视图详解

SQL Server数据库视图详解 目录 A:什么是视图: B:视图与查询的区别: C:视图的优点: D:视图的创建和管理 A:什么是视图: 视图(view):从一个或几个基本表中根据用户需要而做成一个虚表 1:视图是虚表,它在存储时只存储视图的定义,而没有存储对应的数据 2:视图只在刚…

Vuex-总结(4)

1. 使用vuex2. State3. Getters4. mutation5. Action6. Mutation与Action差异7. Module 1. 使用vuex //main.js import store from ./store.js;new Vue({// 把 store 对象提供给 “store” 选项&#xff0c;这可以把 store 的实例注入所有的子组件store,...App }).$mount(#ap…

几个小型数据库的比较

Access&#xff0c;MSDE 2000&#xff0c;Embedded Firebird&#xff0c;SQLite等都是可以免费再分发&#xff08;free redistributable&#xff09;的数据库。 相比而言&#xff0c;MSDE 2000 显著缺点是需要安装&#xff0c;最大优点是和服务器端的 SQL Server 编程模型一致&…

Android SQLite 数据库 增删改查操作

Android SQLite 数据库 增删改查操作 一、使用嵌入式关系型SQLite数据库存储数据 在Android平台上,集成了一个嵌入式关系型数据库——SQLite,SQLite3支持NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际…

Eclipse 在线安装fat jar插件

在线安装步骤&#xff1a; eclipse菜单栏 help >software updates >Search for new features to install>new update site> 填写name 和url name&#xff1a;任意起个&#xff0c; 就写fat吧 url:这个是fat jar的地址 输入http://kurucz-grafika.de/fatjar 剩下的…

Eclipse 打JAR包,插件FatJar 安装与使用

下载fatJar插件&#xff0c;解压缩后是一个.../plugins/(net...)把plugins下面的(net..)文件夹拷贝到eclipse的plugins下&#xff0c;重新启动Eclipse3.1,Windows>prefernce>fat jar preference看到他就说明已经安装成功了。如果没有看到&#xff0c;没有关系&#xff0c…

解决:[Vue warn]: Unknown custom element: router-link, [Vue warn]: $listeners and $attrs is readonly

1.[Vue warn]: Unknown custom element: <router-link> vue项目中引入了vue-router报了如下第一个错误&#xff1a; 第二个错误&#xff1a; 代码如下&#xff1a; //App.vue <router-link to"/">bar</router-link> <router-link to"/…