在hover时更改JList项目背景颜色

我正在尝试更改JList单元格的背景颜色,但是我不知道该怎么做。 这是我目前拥有的:

package cats.youtube.gui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.util.LinkedList; import javax.swing.AbstractListModel; import javax.swing.DefaultListCellRenderer; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.ListSelectionModel; import javax.swing.border.EmptyBorder; import cats.youtube.search.YoutubeSearchResult; public class SearchResultsList extends JPanel{ private class Renderer extends DefaultListCellRenderer{ public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean focused){ final JTextArea area = new JTextArea(model.get(index).toString()); area.setBorder(new EmptyBorder(5, 0, 5, 0)); area.setForeground(selected || focused ? Color.WHITE : Color.BLACK); area.setBackground(selected || focused ? Color.RED : Color.WHITE); return area; } } public class Model extends AbstractListModel{ private LinkedList results; private Object lock; private Model(){ results = new LinkedList(); lock = new Object(); } public int getSize(){ return results.size(); } public String getElementAt(final int i){ return results.get(i).toString(); } public YoutubeSearchResult get(final int i){ return results.get(i); } public void add(final YoutubeSearchResult r){ synchronized(lock){ results.add(r); fireContentsChanged(this, 0, getSize()); try{ lock.wait(500L); }catch(InterruptedException e){ e.printStackTrace(); } } } public void remove(final YoutubeSearchResult r){ results.remove(r); fireContentsChanged(this, 0, getSize()); } public void removeAll(){ results.clear(); fireContentsChanged(this, 0, getSize()); } } private JList list; private JScrollPane scroll; private Model model; private Renderer renderer; public SearchResultsList(){ super(new BorderLayout()); list = new JList(){ public void processMouseMotionEvent(final MouseEvent e){ super.processMouseMotionEvent(e); final int i = locationToIndex(e.getPoint()); if(i > -1){ final Rectangle bounds = getCellBounds(i, i+1); if(bounds.contains(e.getPoint())){ // <--------- here is line 95 } } } }; list.setModel(model = new Model()); list.setCellRenderer(renderer = new Renderer()); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); add(scroll = new JScrollPane(list), BorderLayout.CENTER); } public Model getModel(){ return model; } } 

问题出在第95行; 我不知道该放什么。 我尝试了多种方法,一种是通过我的渲染器调用getListCellRendererComponent方法并更改背景,但这不起作用。

hover部分确实有效(它确实得到了正确的索引)我只是不知道在95号线上放什么。如果有人能帮助我,我将非常感激。

我个人会使用MouseMotionListener来覆盖processMouseMotionEvent ,但那只是我。

你需要一些方法来告诉渲染器哪些行是“突出显示的”,我能想到的两个直接的方法就是……

  1. 创建一个自定义JList ,其中包含设置/获取突出显示的行的方法。 然后,您需要转换为此实现并询问相应的方法,并根据需要采取措施。
  2. 在列表数据中提供一个方法,将行标记为突出显示或不突出显示。 这将允许您直接询问数据。

第一种方法的优点是它将责任与视图分离,它确实属于它。 它确实有缺点,意味着您需要创建自定义JList 。 使用getClientPropertyputClientProperty方法可能更容易,这意味着您不需要自定义实现,也不需要在渲染器中强制转换列表,但缺点是对其他开发人员不明显。

第二种方法将显示和数据信息混合在一起,而不是我鼓励的,因为你真的希望将这种东西分开;)

实施了AFAIK好的RolloverSupportTest / Hightlighter

  • 物质L&F有hightlighter

  • @aephyr的RolloverSupportTest

这是我的方式(解决方案: http : //objectmix.com/java/73071-highlight-itemin-jlist-mouseenter-mouse-over.html ,第二条消息):

 private int mHoveredJListIndex = -1; ... mList.addMouseMotionListener(new MouseAdapter() { public void mouseMoved(MouseEvent me) { Point p = new Point(me.getX(),me.getY()); int index = mList.locationToIndex(p); if (index != mHoveredJListIndex) { mHoveredJListIndex = index; mList.repaint(); } } }); 

在你的渲染器中:

 public class CellRenderer extends JComponent implements ListCellRenderer { @Override public Component getListCellRendererComponent(JList aList, Object aValue, int aIndex, boolean aIsSelected, boolean aCellHasFocus) { Color backgroundColor = mHoveredJListIndex == aIndex ? Color.gray : Color.white; JPanel pane = new JPanel(new BorderLayout()); // add contents here pane.setBackground(backgroundColor); return pane; } }