2009-11-03 200 views
5

我正在尝试动态更改JList行。我需要改变第n行颜色,突出显示它(n在编译期间是未知的)。我看到很多自定义ListCellRenderer的例子,但都是“静态的”。在运行时更改JList行颜色

换句话说,我必须用JList的x行。在运行期间,我的“业务逻辑”检测第n行很重要。所以我想让它的背景变成绿色,等一秒钟,然后再把它变成白色。还有一件事,不要改变行选择。

什么是这样做的最佳方法是什么?

+0

msawicki注意,我的回答以前的版本会阻止整个事件调度线程。这意味着当行被突出显示时,你不能在GUI中做任何事情。我再说一次只是一个快速肮脏的示例 – jitter 2009-11-03 04:57:48

+0

好的,谢谢。我更新了我的版本。 – 2009-11-03 16:31:26

回答

5

自定义渲染基于从SUN ListDemo样品。

如果你进入这是不是在列表中的文本框的一些文本和你打突出显示被添加。

如果文本是在列表中,你打突出显示列表中的条目被暂时蓝色高亮显示。

注意这里的解决方案与匹配字段是仅用于演示。欲了解更多正确实施考虑提出其他的想法,并考虑使用javax.swing.Timer

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.event.*; 

public class ListDemo extends JPanel { 
    private JList list; 
    private DefaultListModel listModel; 
    public String match = null; 

    private static final String hireString = "Highlight"; 
    private JTextField employeeName; 

    public ListDemo() { 
     super(new BorderLayout()); 

     listModel = new DefaultListModel(); 
     listModel.addElement("Test1"); 
     listModel.addElement("Test2"); 
     listModel.addElement("Test3"); 

     list = new JList(listModel); 
     list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
     list.setSelectedIndex(0); 
     list.setVisibleRowCount(5); 
     list.setCellRenderer(new MyListCellRenderer()); 
     JScrollPane listScrollPane = new JScrollPane(list); 

     JButton hireButton = new JButton(hireString); 
     HireListener hireListener = new HireListener(hireButton); 
     hireButton.setActionCommand(hireString); 
     hireButton.addActionListener(hireListener); 
     hireButton.setEnabled(false); 

     employeeName = new JTextField(10); 
     employeeName.addActionListener(hireListener); 
     employeeName.getDocument().addDocumentListener(hireListener); 
     listModel.getElementAt(list.getSelectedIndex()).toString(); 

     JPanel buttonPane = new JPanel(); 
     buttonPane.setLayout(new BoxLayout(buttonPane, 
              BoxLayout.LINE_AXIS)); 
     buttonPane.add(Box.createHorizontalStrut(5)); 
     buttonPane.add(employeeName); 
     buttonPane.add(hireButton); 
     buttonPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 

     add(listScrollPane, BorderLayout.CENTER); 
     add(buttonPane, BorderLayout.PAGE_END); 
    } 
    class MyListCellRenderer extends JLabel implements ListCellRenderer { 
     public MyListCellRenderer() { 
      setOpaque(true); 
     } 
     public Component getListCellRendererComponent(JList paramlist, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
      setText(value.toString()); 
      if (value.toString().equals(match)) { 
       setBackground(Color.BLUE); 
       SwingWorker worker = new SwingWorker() { 
        @Override 
        public Object doInBackground() { 
         try { 
          Thread.sleep(5000); 
         } catch (InterruptedException e) { /*Who cares*/ } 
         return null; 
        } 
        @Override 
        public void done() { 
         match = null; 
         list.repaint(); 
        } 
       }; 
       worker.execute(); 
      } else 
       setBackground(Color.RED); 
      return this; 
     } 
    } 
    class HireListener implements ActionListener, DocumentListener { 
     private boolean alreadyEnabled = false; 
     private JButton button; 
     public HireListener(JButton button) { 
      this.button = button; 
     } 
     public void actionPerformed(ActionEvent e) { 
      String name = employeeName.getText(); 
      if (listModel.contains(name)) { 
       match = name; 
       list.repaint(); 
       employeeName.requestFocusInWindow(); 
       employeeName.selectAll(); 
       return; 
      } 
      if (name.equals("")) { 
       Toolkit.getDefaultToolkit().beep(); 
       employeeName.requestFocusInWindow(); 
       employeeName.selectAll(); 
       return; 
      } 
      int index = list.getSelectedIndex(); 
      if (index == -1) 
       index = 0; 
      else 
       index++; 
      listModel.insertElementAt(employeeName.getText(), index); 
      employeeName.requestFocusInWindow(); 
      employeeName.setText(""); 
      list.setSelectedIndex(index); 
      list.ensureIndexIsVisible(index); 
     } 
     public void insertUpdate(DocumentEvent e) { 
      enableButton(); 
     } 
     public void removeUpdate(DocumentEvent e) { 
      handleEmptyTextField(e); 
     } 
     public void changedUpdate(DocumentEvent e) { 
      if (!handleEmptyTextField(e)) 
       enableButton(); 
     } 
     private void enableButton() { 
      if (!alreadyEnabled) 
       button.setEnabled(true); 
     } 
     private boolean handleEmptyTextField(DocumentEvent e) { 
      if (e.getDocument().getLength() <= 0) { 
       button.setEnabled(false); 
       alreadyEnabled = false; 
       return true; 
      } 
      return false; 
     } 
    } 
    private static void createAndShowGUI() { 
     JFrame frame = new JFrame("ListDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JComponent newContentPane = new ListDemo(); 
     newContentPane.setOpaque(true); 
     frame.setContentPane(newContentPane); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { createAndShowGUI(); } 
     }); 
    } 
} 
+0

难道不会暂停美国东部时间一秒钟? – akf 2009-11-03 04:36:48

+0

谢谢。它完美的作品。 – 2009-11-03 04:48:37

+0

你当然是对的。取而代之的是摆动工具的实施 – jitter 2009-11-03 04:55:03

2

实现方法getListCellRendererComponent的自定义ListCellRenderer将有权访问JList以及它正在重写的值。这给你如何确定何时绘制ñ个行绿色几个选项:

  1. 你可以继承JList并有渲染要求它使用的BG的颜色。当商业逻辑决定了它是时间ñ个行是绿色的JList子类可能引发重绘,然后启动一个秋千Timer触发重绘返回BG恢复正常
  2. 当商业逻辑确定何时应该将行显示为绿色,还可以选择在行的后备对象上设置状态,并在getListCellRendererComponent内测试该状态,如果状态正确,则将bg设置为绿色。再次,您可以选择设置Swing Timer以恢复支持对象上的状态。

    list.setCellRenderer(myListCellrenderer); 
    

    现在覆盖的方法getListCellRendererComponent()内做这样的事情:

6

简单,使用设置自定义ListCellRenderer您的JList

public Component getListCellRendererComponent(.....) { 
    Component c = super.getListCellRendererComponent(); 
    c.setBackGround(Color.blue) 
    return c; 
} 

上面的例子假设你overrid DefaultListCellRenderer