在运行时更改JList行颜色

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

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

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

基于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(); } }); } } 

很简单,使用以下命令将自定义ListCellRenderer设置为JList:

 list.setCellRenderer(myListCellrenderer); 

现在在重写方法内部getListCellRendererComponent()执行以下操作:

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

上面的示例假定您的自定义渲染器覆盖DefaultListCellRenderer

实现方法getListCellRendererComponent自定义ListCellRenderer将有权访问JList及其正在进行的值。 这为您提供了几个选项来确定何时将第n行绘制为绿色:

  1. 您可以JList并让渲染器询问它用于bg的颜色。 当业务逻辑确定第n行为绿色时, JList子类可以触发重绘,然后启动Swing Timer触发重绘,使bg恢复正常
  2. 当业务逻辑确定何时应将行显示为绿色时,您还可以选择在行的后备对象上设置状态,并在getListCellRendererComponent针对该状态进行getListCellRendererComponent ,如果状态正确则将bg设置为绿色。 同样,您可以选择设置Swing Timer以还原备份对象上的状态。