`
djsl6071
  • 浏览: 595313 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

制作更酷的JList界面

阅读更多

turbochen(原作)制作更酷的JList界面    

 
作者:eclipse     发表时间:2002/09/03 03:46pm
 
制作更酷的JList界面    turbochen(原作)
 
关键字     java,listcellrenderer,callback
 

内容:
1。绘制器的工作原理。
2。用自订的绘制器更换JList和JComboBox的外观。
3。让新的外观响应鼠标事件。

借助swing体系的mvc设计理念,为组件更换不同的外观成为轻而易举的事情。本文主要以JList和JComboBox为例讲解ListCellRenderer的原理与用法.


一、绘制器的工作原理
不管是JList还是JComboBox,它们都用到了ListCellRenderer,因为JComboBox本身就是由一个下拉式的JList和TextField组成的. 在这里,它们使用了callback的机制。

callback的一是种常见的方式是在A类中调用B类中的方法,在A类中先要登记一个(也可以是多个)B类的实例引用,在需要调用时再通过该实例来调用它的内部方法.这样的机制在很多的设计模式中都有用到,如Observer等.还有AWT的事件机制也用到了callback.

要实现callback,通常将B类设计成一个能被callback的接口.在JList的绘制器中,swing提供了一个ListCellRenderer接口,
public interface ListCellRenderer {
   Component getListCellRendererComponent(
       JList list,
       Object value,
       int index,
       boolean isSelected,
       boolean cellHasFocus);
}
这个接口只提供一个方法,我们只要实现了这个接口,并将它的实例引用传给JList,就可以将JList替换成不同的样式了.看一下ListCellRenderer是如何工作的,

在绘制JList的每个Cell之前,它会去调用getListCellComponent( ),得到一个Component,并
将这个Component绘制在正确的位置.因为getListCellComponent( )返回的是Component,所以我们几乎可以扩展任意一个Component,来改变JList,JComboBox等的外观.

二、制作自已的绘制器
我们现在要想让JList中显示一组学生名单,同时每个名单前显示该学生的图标.如下图所示

我们先来想一想,Swing中有什么组件既可以显示图标也可以显示文字? JLabel.对了。我们就用JLabel作为JList的绘制器, 看看我扩展的JLabel类,它实现了ListCellRenderer接口:
       /* 可以显示图标的ListCell绘制器 */
       public class IconListItemRenderer extends JLabel implements ListCellRenderer
       {
           private Border
               selectedBorder = BorderFactory.createLineBorder(Color.blue,1),
               emptyBorder = BorderFactory.createEmptyBorder(1,1,1,1);

           public Component getListCellRendererComponent(
                       JList list,
                       Object value,
                       int index,
                       boolean isSelected,
                       boolean cellHasFocus)
               {

               IconListItem item = (IconListItem)value;
               this.setIcon(item.getIcon());
               this.setText(item.getText());

               if ( isSelected ) setBorder (selectedBorder);
               else setBorder(emptyBorder);
               return this;
           }
       }
大家看到,getListCellRendererComponent方法会传入几个参数,我们就用它传入的几个参数设置JLabel的外观:图标与文字。在这个类中,我们用一个IconListItem接收调用者传过来的value,
       IconListItem item = (IconListItem) value;
IconListItem是我另外定义好的一个类,它用来存放每一个List Item的值,
       import javax.swing.*;
       public class IconListItem
       {
           Icon icon;
           String text;
           public IconListItem(Icon icon, String text)
           {
               this.icon = icon;
               this.text = text;
           }
           public Icon getIcon() { return icon;}
           public String getText() { return text;}
           public void setIcon(Icon icon){ this.icon = icon;}
           public void setText(String text){ this.text = text; }
       }
这样的话,我就可以用getIcon()和getText()方法取得每个List Item的值了,
       IconListItem item = (IconListItem) value;
       this.setIcon(item.getIcon());
       this.setText(item.getText());

至此,我们就可以用以下方法方便的更换JList的外观了,
       JList list = new JList();
       list.setCellRenderer(new IconListItemRenderer());  file://安装我们自订的cellRenderer
       DefaultListModel listModel = new DefaultListModel();
       list.setModel(listModel);
       IconListItem item = new IconListItem(new ImageIcon(...),"John");
       listModel.addElement(item);    // 为List增加Item
       ...
由于JComboBox也有一个下拉式清单,所以它的清单也是用ListCellRenderer来绘制的,所以我们也可以将这个IconListItemRenderer给它用:
       JComboBox list = new JComboBox();
       list.setRenderer(new IconListItemRenderer());  //装我们自订的cellRenderer
       DefaultComboBoxModel comboModel = new DefaultComboBoxModel();
       list.setModel(comboModel);
       IconListItem item = new IconListItem(new ImageIcon(...),"John");
       comboModel.addElement(item);    // 为List增加Item
       ...
注意,JComboBox安装绘制器时是用setRenderer()方法,JList是用setCellRenderer()方法,名字稍有不同.

以上大家看到的是可显示一个图标的List, 下面我们再看一个可显示CheckBox的List是如何实现的,以下是例图:

代码实现:
       import javax.swing.*;
       import java.awt.*;
       import javax.swing.border.*;
       import java.awt.event.*;
       /* 可以显示CheckBox的ListCell绘制器 */
       public class CheckListItemRenderer extends JCheckBox implements ListCellRenderer
       {
           public Component getListCellRendererComponent(
                       JList list,
                       Object value,
                       int index,
                       boolean isSelected,
                       boolean cellHasFocus)
           {
               CheckListItem item = (CheckListItem)value;
               this.setSelected(item.getCheck());
               this.setText(item.getText());
               this.setFont(list.getFont());
               this.setEnabled(list.isEnabled());
               return this;
           }
       }
同样这个绘制器中用一个CheckListItem存放每个List Item的值:
       public class CheckListItem
       {
           boolean check;
           String text;
           public CheckListItem(boolean check, String text)
           {
               this.check = check;
               this.text = text;
           }
           public boolean getCheck() { return check; }
           public void setCheck(boolean _check) { check = _check; }
           public String getText() { return text; }
           public void setText(String _text) { text = _text; }
       }
这个绘制器的用法同IconListItemRenderer一样,不多讲了.

三、让自订的绘制器响就鼠标事件
使用以上的CheckListItemRenderer时,大家会发现,虽然List中可以显示CheckBox了,但是用鼠标点击时,没有反应! 现在我就来解决这个问题.要澄清的是,ListCellRenderer本身是只返回一个组件用来绘制一个单元格,不能对用户动作作出反应。为些我们必须在JList上下功夫.JList有一个addMouseListener()方法可以为自身安装一个鼠标监听器,在这里,我实现了一个MouseAdapter,并让它对mousePressed作出响应:
       class CheckListMouseListener extends MouseAdapter
       {
             public void mousePressed(MouseEvent e) {
               JList list = (JList) e.getSource();
               int index = list.locationToIndex(e.getPoint());
               CheckListItem item = (CheckListItem)list.getModel().getElementAt(index);
               item.setCheck(! item.getCheck());
               Rectangle rect = list.getCellBounds(index, index);
               list.repaint(rect);
           }
       }
使用时, 用addMouseListener(new CheckListMouseListener())就行了.

除了包含CheckBox的JList外,许多情况下,我们需要为自制的绘制器加上动作响应,如我们要实现一个可编辑的JList, 除了要扩展JTextField及实现ListCellRenderer之外,还要写一个鼠标监听器和键盘监听器,当双击时,JList变成可编辑状态,当回车时,还原成不可编辑状态.具体的实现过程,我就不详叙了,留给大家作练习.


上面内容,我写了一个演示程序,下面是它的演示画面,

你可以从这里下载完整的演示程序.

 
 
我自己做了一个CheckListCellRenderer   和CheckListModel如下,  
  但是为什么程序执行后,JList没有办法点击呢?  
   
  import   javax.swing.*;  
  import   java.awt.*;  
  import   javax.swing.border.*;  
  import   java.awt.event.*;  
   
  public   class   CheckListCellRenderer   extends   JCheckBox   implements   ListCellRenderer  
  {  
          private   Border  
                  redBorder   =   BorderFactory.createLineBorder(Color.red,2),  
                  emptyBorder   =   BorderFactory.createEmptyBorder(2,2,2,2);  
   
          public   Component   getListCellRendererComponent(  
                                  JList   list,  
                                  Object   value,  
                                  int   index,  
                                  boolean   isSelected,  
                                  boolean   cellHasFocus)  
                  {  
                  CheckListModel   model   =   (CheckListModel)list.getModel();  
                  setText(model.getValue(value));  
                  setSelected(model.getCheck(value).booleanValue());  
                  if   (   isSelected   )   setBorder   (redBorder);  
                  else   setBorder(emptyBorder);  
                  return   this;  
          }  
   
   
  }  
   
  class   CheckListModel   extends   DefaultListModel  
  {  
          public   CheckListModel()  
          {  
                  super();  
          }  
   
          public   CheckListModel(String[]   names,   Boolean[]   checks)  
          {  
                  for(int   i=0;i<names.length;   ++i)  
                  {  
                          addElement(new   Object[]  
                                                  {  
                                                          names[i],checks[i]  
                                                  });  
                  }  
          }  
   
          public   String   getValue(Object   object)  
          {  
                  Object[]   array=(Object[])object;  
                  return   (String)array[0];  
          }  
   
          public   Boolean   getCheck(Object   object)  
          {  
                  Object[]   array   =   (Object[])   object;  
                  return   (Boolean)array[1];  
          }  
   
   
  }  

 

public   class   RadioButtonPanel   extends   JPanel   {  
          JRadioButton[]   buttons;  
   
          RadioButtonPanel(String[]   str)   {  
              setLayout(new   BoxLayout(this,   BoxLayout.X_AXIS));  
              buttons   =   new   JRadioButton[str.length];  
              for   (int   i=0;   i<buttons.length;   i++)   {  
                  buttons[i]   =   new   JRadioButton(str[i]);  
                  buttons[i].setFocusPainted(false);  
                  add(buttons[i]);  
              }  
          }  
   
          public   void   setSelectedIndex(int   index)   {  
              for   (int   i=0;i<buttons.length;i++)   {  
                  buttons[i].setSelected(i   ==   index);  
              }  
          }  
   
          public   int   getSelectedIndex()   {  
              for   (int   i=0;   i<buttons.length;   i++)   {  
                  if   (buttons[i].isSelected())   {  
                      return   i;  
                  }  
              }  
              return   -1;  
          }  
   
          public   JRadioButton[]   getButtons()   {  
              return   buttons;  
          }  
      }  
   
      public   class   RadioButtonRenderer   extends         RadioButtonPanel  
                                                          implements   TableCellRenderer   {  
          RadioButtonRenderer(String[]   strs)   {  
              super(strs);  
          }  
   
          public   Component   getTableCellRendererComponent(JTable   table,   Object   value,  
                                        boolean   isSelected,   boolean   hasFocus,   int   row,   int   column)   {  
              if   (value   instanceof   Integer)   {  
                  setSelectedIndex(((Integer)value).intValue());  
              }  
              return   this;  
          }  
      }  
   
      public   class   RadioButtonEditor   extends         DefaultCellEditor  
                                                      implements   ItemListener   {  
          RadioButtonPanel   panel;  
   
          public   RadioButtonEditor(JCheckBox   checkBox,RadioButtonPanel   panel)   {  
              super(checkBox);  
              this.panel   =   panel;  
              ButtonGroup   buttonGroup   =   new   ButtonGroup();  
              JRadioButton[]   buttons     =   panel.getButtons();  
              for   (int   i=0;   i<buttons.length;   i++)   {  
                  buttonGroup.add(buttons[i]);  
                  buttons[i].addItemListener(this);  
              }  
          }  
   
          public   Component   getTableCellEditorComponent(JTable   table,   Object   value,  
                                        boolean   isSelected,   int   row,   int   column)   {  
              if   (value   instanceof   Integer)   {  
                  panel.setSelectedIndex(((Integer)value).intValue());  
              }  
              return   panel;  
          }  
   
          public   Object   getCellEditorValue()   {  
              return   new   Integer(panel.getSelectedIndex());  
          }  
   
          public   void   itemStateChanged(ItemEvent   e)   {  
              super.fireEditingStopped();  
          }  
      }  

  在程序中加入以上类  
  然后在你的Table类中加入一下方法:  
      public   void   setCloumnToRadioButton(Object   cloumnName,   String[]   selections)   {  
          getColumn(cloumnName).setCellRenderer(  
              new   RadioButtonRenderer(selections)  
          );  
          getColumn(cloumnName).setCellEditor(  
                  new   RadioButtonEditor(new   JCheckBox(),  
                                                  new   RadioButtonPanel(selections))  
          );  
      }    

分享到:
评论

相关推荐

    javaswing更酷的Jlist.pdf

    JavaSwing 中的 JList 组件自定义渲染器 JavaSwing 是一个功能强大且灵活的 GUI 组件库,提供了许多自定义组件的方式。JList 是其中的一个重要组件,用于显示列表数据。但是,JList 的默认外观并不美观,如何...

    java_swing_更酷的Jlist.

    ### Java Swing 更酷的 JList:实现列表项带有图片标签 在Java Swing中,`JList` 是一个非常有用的组件,用于展示一个可滚动的列表。对于那些希望为列表增加更多视觉元素(如图片)的应用程序来说,使用 `...

    JList的一些用法

    在Java的Swing图形用户界面库中,`JList`组件提供了展示列表项的强大功能,不仅能够支持单列或多列显示,还提供了丰富的事件处理机制,使得它成为构建用户交互界面时不可或缺的一部分。本文将深入探讨`JList`的基本...

    JList动态改变图片

    这在创建图像库、画廊应用或者进行图形用户界面设计时可能会非常有用。 首先,`JList`默认只能显示文本,若要展示图片,我们需要自定义`ListModel`和`ListCellRenderer`。`ListModel`用于存储数据,而`...

    swing炫酷界面与功能实现

    比如,JTable 可用于显示和编辑表格数据,JTree 显示层次结构的数据,JList 显示可选项目列表,而JTabbedPane 可以创建选项卡式界面。此外,JOptionPane 可以方便地弹出警告、确认或输入对话框。 Swing 还包含...

    JList 上下左右拖动

    它在用户界面设计中常用于创建列表视图,允许用户通过单击或键盘导航来选择项目。在本教程中,我们将深入探讨如何实现`JList`的上下左右拖动功能,以增强用户交互体验。 首先,`JList`的基本使用包括创建`...

    JList example

    `JList` 可以用作单选或多选列表,常用于创建下拉菜单、列表视图等用户界面元素。在这个例子中,我们将深入探讨`JList` 的使用方法,并结合给出的`List.java`文件来解析其关键知识点。 首先,`JList` 是javax.swing...

    java构建几种个性的JList

    在`JList`中添加图片,可以使用户界面更加生动和直观。这可以通过创建一个`DefaultListModel`,然后将包含图片和文字的自定义对象添加到模型中来实现。自定义对象需要重写`toString()`方法以显示文本,同时需要提供...

    JAVA JList使用例子

    在Java Swing库中,`JList`是一个非常重要的组件,用于显示一组可选择的项。在GUI应用程序中,它常用于展示列表数据,允许用户进行单选或多选操作。本篇将深入探讨如何使用`JList`以及如何为其添加滚动条。 首先,`...

    swing中jlist点击事件demo

    swing中的jlist 代码中定义了两个jlist 从一个jlist双击列表项可以将该项从这个列表删除并添加至另外一个列表中去

    图片+文字的Jlist

    在默认情况下,`JList` 只能显示字符串元素,但通过自定义渲染器(CellRenderer),我们可以扩展其功能以显示更丰富的信息,如图片和文字的组合。标题“图片+文字的Jlist”正是指这个功能的实现。 描述中的“重新...

    JList中使用JCheckBox示例

    在Java Swing库中,`JList`是一个常用...通过自定义`ListModel`、渲染器和鼠标监听器,我们可以使`JList`具有勾选功能,从而增强用户界面的交互性。这在创建GUI应用程序时非常有用,特别是在用户需要选择多项的情况下。

    自定义JList

    在这个自定义`JList`的例子中,我们将会探讨如何扩展`JList`的功能,使其具有点击按钮后删除当前条目并实时更新界面的能力。 首先,要实现自定义`JList`,我们需要创建一个新的类继承自`JList`。这个新类可以包含...

    JList事件监听器的实现例子

    在Java Swing库中,`JList`是一个非常重要的组件,用于显示一组可选择的项。在用户与`JList`进行交互时,如选择、取消选择等操作,我们可能需要捕获这些事件并做出响应。这就涉及到事件监听器的使用。本教程将详细...

    JList多选值的获取

    在Java Swing中,`JList` 组件被广泛用于创建用户界面中的列表框。不同于选择框(通常指`JComboBox`),`JList` 支持多种选择模式,使得用户能够灵活地进行单选或多选操作。本文将详细介绍如何通过`JList` 实现不同...

    用JComboBox和JList实现的一个文件浏览器组件

    在提供的压缩包`FileBrowsePane`中,可能包含了这个自定义组件的源代码,通过阅读和分析这些代码,可以学习到更多关于如何在Java Swing中集成`JComboBox`和`JList`以创建复杂用户界面的知识。同时,这也是一个很好的...

    JList点击空白处不让其选中最后一项

    在Java Swing中,`JList` 是一个常用的组件,用于展示一系列可选择的项。当用户点击`JList`的空白区域时,默认行为是选中列表的最后一项。这对于某些应用场景,比如带有右键菜单的界面,可能会带来不便,因为用户...

    JFC Swing活学活用系列之定制JList显示.rar

    默认情况下,JList会按照字符串形式展示元素,但有时我们需要更复杂的展示方式,例如带图标的列表项或者自定义颜色的文本。这就需要我们定制JList的显示。 首先,要定制JList的显示,我们需要创建一个自定义的...

    Java Swing组件:Jlist学习笔记

    如果需要更灵活地管理列表项(如添加、删除等),则可以使用 `ListModel` 来构造 JList。这种方式下,可以动态地改变列表内容。 ```java DefaultListModel&lt;String&gt; listModel = new DefaultListModel(); ...

    JList的使作

    JLIst的使用,主要是介绍基础

Global site tag (gtag.js) - Google Analytics