悬停时更改JList项目背景颜色 [英] Change JList item background color on hover

查看:121
本文介绍了悬停时更改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<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行放置什么.如果有人可以帮助我,将不胜感激.

解决方案

我个人会使用MouseMotionListener覆盖processMouseMotionEvent,但这仅是我.

您需要某种方式来告诉渲染器哪些行被突出显示",我可以想到的两种直接方法是...

  1. 创建一个自定义JList,该自定义JList具有用于设置/获取突出显示的行的方法.然后,您需要转换为该实现并询问适当的方法,并根据需要采取措施.
  2. 在列表数据中提供将行标记为突出显示或不突出显示的方法.这将使您可以直接查询数据.

第一种方法的优点是,它将视图的责任隔离到它真正所属的视图中.它确实具有意味着您需要创建自定义JList的缺点.相反,使用getClientPropertyputClientProperty方法可能会更容易,这意味着您不需要自定义实现,也无需在渲染器中强制转换列表,但缺点是对于其他开发人员而言并不明显./p>

第二种方法将显示信息和数据信息混合在一起,这不是我所鼓励的,因为您确实希望将这种信息分开;)

I'm trying to change the background color of a JList cell when it is being hovered over, but I'm not sure how to do it. Here is what I currently have:

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;
    }
}

The problem is on line 95; I don't know what to put there. I tried multiple approaches, one being calling the getListCellRendererComponent method through my renderer and changing the background like that, but that didn't work.

The hovering portion does work (it does get the correct indexes) I just don't know what to put on line 95. If anyone could help me, it would be very much appreciated.

解决方案

I, personally, would use a MouseMotionListener over overriding the processMouseMotionEvent, but that's just me.

You need some way to tell the renderer which rows are "highlighted", the two immediate ways I can think of achieving this is to ...

  1. Create a custom JList which has methods to set/get the highlighted row. You would then need to cast to this implementation and interrogate the appropriate method, taking action as required.
  2. Provide a method within the list data that mark the row as highlighted or not. This would allow you to interrogate the data directly.

The advantage of the first approach is that it isolates the responsibility to the view, where it really belongs. It does have the disadvantage of meaning you need to create a custom JList. It might be easier to use the getClientProperty and putClientProperty methods instead, this would mean you wouldn't need a custom implementation nor cast the list in the renderer, but is has the disadvantage of not being obvious to other developers.

The second approach mixes display and data information together, not something I would encourage as you really want to keep this kind of stuff separated ;)

这篇关于悬停时更改JList项目背景颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆