悬停时更改 JList 项目背景颜色
Posted
技术标签:
【中文标题】悬停时更改 JList 项目背景颜色【英文标题】:Change JList item background color on hover 【发布时间】:2012-12-12 07:40:54 【问题描述】:我正在尝试更改悬停在 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<String>
private LinkedList<YoutubeSearchResult> results;
private Object lock;
private Model()
results = new LinkedList<YoutubeSearchResult>();
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<String> list;
private JScrollPane scroll;
private Model model;
private Renderer renderer;
public SearchResultsList()
super(new BorderLayout());
list = new JList<String>()
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
方法并像那样更改背景,但这不起作用。
悬停部分确实有效(它确实获得了正确的索引)我只是不知道在第 95 行放什么。如果有人可以帮助我,将不胜感激。
【问题讨论】:
【参考方案1】:我个人会使用 MouseMotionListener
覆盖 processMouseMotionEvent
,但这只是我。
您需要一些方法来告诉渲染器“突出显示”哪些行,我能想到的两种直接方法是...
-
创建一个自定义
JList
,它具有设置/获取突出显示行的方法。然后,您需要转换到此实现并询问适当的方法,并根据需要采取行动。
在列表数据中提供一种方法,将行标记为突出显示或不突出显示。这将允许您直接查询数据。
第一种方法的优点是它将责任隔离到视图真正属于的地方。它确实具有您需要创建自定义JList
的缺点。改用 getClientProperty
和 putClientProperty
方法可能更容易,这意味着您不需要自定义实现,也不需要在渲染器中投射列表,但缺点是对其他开发人员不明显。
第二种方法将显示信息和数据信息混合在一起,我不鼓励这样做,因为您真的希望将这种东西分开;)
【讨论】:
我明白了,谢谢。实际上,我找到了一个更有效的替代方案。我只是使用带有 BoxLayout 的面板,然后只是将结果添加到面板中,它模拟了一个列表,但我不再需要添加该延迟。另外,它似乎也更有效率。不过谢谢,感谢您的回复。 实际上,您会发现随着“列表”中项目数量的增加,您的工作效率会大大降低。JList
(以及 JTable
和 JTree
)针对性能进行了高度优化,以便处理大型数据集(以及小型数据集)【参考方案2】:
AFAIK 好 RolloverSupportTest
/ Hightlighter
已实现
Substance L&F has hightlighter
RolloverSupportTest by @aephyr
【讨论】:
【参考方案3】:我是这样做的(解决方案: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;
【讨论】:
您还应该为 mouseExited 事件添加一个 MouseListener,以便在鼠标完全离开时重绘列表。 mList.addMouseListener(new MouseAdapter() @Override public void mouseExited(MouseEvent e) mHoveredJListIndex = -1; mList.repaint(); );以上是关于悬停时更改 JList 项目背景颜色的主要内容,如果未能解决你的问题,请参考以下文章