How to change a cell icon of JList in run time

2020-05-06 13:44发布

How can I change a JLabel icon of only one JList cell(for example: clicking in JList)? I tried to access the JLabel getting with listCellRender but it don't works:

    @Override
    public void valueChanged(ListSelectionEvent e) {
        if (!e.getValueIsAdjusting()) {
             ListCellRenderer r = list.getCellRenderer();
             JLabel comp = (JLabel) r.getListCellRendererComponent(list, list.getSelectedValue(), list.getSelectedIndex(), false, false);
             comp.setIcon(UIManager.getIcon("Tree.leafIcon"));
    }

Can anyone give some idea? Thanks in advance!

My code:

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

/**
 * @see http://stackoverflow.com/questions/7620579
 * @see http://stackoverflow.com/questions/4176343
 */
public class ListPanel extends JPanel {

    private static final long serialVersionUID = -5558761237888601952L;
    private static final int N = 5;
    private DefaultListModel dlm = new DefaultListModel();
    private JList list = new JList(dlm);
    private ListRenderer myRender;
    // http://stackoverflow.com/questions/13752188/chat-client-emoticons-window-java
    // http://docs.oracle.com/javase/tutorial/uiswing/components/icon.html VER

    public ListPanel() {
        super(new GridLayout());

        for (int i = 0; i < N * N; i++) {
            String name = "Cell: " + i;//String.format("%02d", i);
            dlm.addElement(name);
        }
        //dlm.getElementAt(0)
        list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        //list.getCellRenderer().getListCellRendererComponent(list, value, index, isSelected, cellHasFocus)
        list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
        list.setVisibleRowCount(N);
        myRender = new ListRenderer();
        list.setCellRenderer(myRender);
        list.addListSelectionListener(new SelectionHandler());
        JScrollPane pane = new JScrollPane(list);
        this.add(pane, BorderLayout.CENTER);
    }

    private class ListRenderer extends DefaultListCellRenderer {


        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            JLabel label =  (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            //System.out.println(">> " + index);
            label.setBorder(BorderFactory.createEmptyBorder(N, N, N, N));
            label.setIcon(UIManager.getIcon("html.pendingImage"));
            label.setHorizontalTextPosition(JLabel.CENTER);
            label.setVerticalTextPosition(JLabel.BOTTOM);
            return label;
        }
    }

    private class SelectionHandler implements ListSelectionListener {

        @Override
        public void valueChanged(ListSelectionEvent e) {
            if (!e.getValueIsAdjusting()) {
                System.out.println(list.getSelectedValue());
            }
        }
    }

    private void display() {
        JFrame f = new JFrame("ListPanel");
        //f.setPreferredSize(new Dimension(400, 400));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ListPanel().display();
            }
        });
    }
}

3条回答
小情绪 Triste *
2楼-- · 2020-05-06 14:01

You're doing it backwards. The cell renderer should simply use the isSelected argument and set the icon you want if this argument is true, and no icon if it's false.

No need for a selection listener. The renderer will automatically be invoked when the selection changes.

查看更多
兄弟一词,经得起流年.
3楼-- · 2020-05-06 14:08
  • I think that there is easier method as public void valueChanged(ListSelectionEvent e) { from ListSelectionListener

  • see getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { there you can to override isSelected, for multisleection in SelectionModel is better cellHasFocus

查看更多
够拽才男人
4楼-- · 2020-05-06 14:09

Is there any way to change the icons after rendered?

You can dynamically choose the icon based on criteria such as index or value at the time of rendering. Using the example cited here, the following renderer produces the image shown. You can always update an icon and repaint().

list panel icons

private class ListRenderer extends DefaultListCellRenderer {

    Icon icon1 = UIManager.getIcon("html.pendingImage");
    Icon icon2 = UIManager.getIcon("html.missingImage");

    public ListRenderer() {
        this.setBorder(BorderFactory.createLineBorder(Color.red));
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object
            value, int index, boolean isSelected, boolean cellHasFocus) {
        JLabel label = (JLabel) super.getListCellRendererComponent(
            list, value, index, isSelected, cellHasFocus);
        label.setBorder(BorderFactory.createEmptyBorder(N, N, N, N));
        label.setIcon(icon1);
        if (index % 2 == 0) {
            label.setIcon(icon2);
        }
        label.setHorizontalTextPosition(JLabel.CENTER);
        label.setVerticalTextPosition(JLabel.BOTTOM);
        return label;
    }
}
查看更多
登录 后发表回答