1

好的,所以我认为我的问题源于对 JList实际在做什么缺乏基本的理解。

我有一个简单的示例类MyList

package test;

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;

public class MyList extends JList<String> {
    public MyList(Vector<String> myStrings){
        super(myStrings);
        this.setCellRenderer(new ListCellRenderer<String>(){
            @Override
            public Component getListCellRendererComponent(
                    JList<? extends String> list, String value, int index,
                    boolean isSelected, boolean cellHasFocus) {
                String myString = value.toString();
                return new JLabel(myString+" (idx "+index+")");
            }

        });

        this.addMouseListener(new MouseAdapter(){
            @Override
            public void mousePressed(MouseEvent e) {
                MyList p = (MyList) e.getSource();
                Component c = p.findComponentAt(e.getX(), e.getY());
                System.out.println("am clicking on "+c.getClass()+" in "+p.getClass());
            }
        });
    }

    public static void main(String[] args){
        Vector<String> myStrings = new Vector<String>();
        myStrings.addAll(Arrays.asList("str 1","str 2","str 3"));
        MyList mine = new MyList(myStrings);
        JFrame myFrame = new JFrame();
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myFrame.setSize(500, 500);
        myFrame.add(mine);
        myFrame.setVisible(true);
    }
}

单击JLabel列表中的任何内容的输出是相同的:

am clicking on class test.MyList in class test.MyList

我期望它是:

am clicking on class javax.swing.JLabel in class test.MyList

我认为这与 ListCellRenderer 的工作方式有关,但我不确定。p.findComponentAt(e.getX(), e.getY());为什么我没有从JLabel中取回组件?这里发生了什么?

4

1 回答 1

2

为什么我从 p.findComponentAt(e.getX(), e.getY()); 得到的组件不是 一个JLabel?这里发生了什么?

JLists 和 JTables 付出了额外的努力来有效地显示大量信息,同时最大限度地减少这样做的开销。他们这样做的一种方法是通过渲染器显示信息。您在 JList 中看到的不是真正的 JLabels,而是 JLabels 的图像(或任何用作渲染器的组件)。JList 使用相同的渲染器为列中的每个元素创建图像。因此,假设您有一个包含 1000 个项目的 JList,而不是创建 1000 个 JLabel,JList 只创建一个,使用它来创建 JLabel 图像,然后显示图像。所以你点击的是真正的 JList 而不是 JLabel。

要进一步测试这一点,请尝试使用 JTextField 作为渲染器,您会很快发现该单元格的行为不像 JTextField 并且您无法编辑它显示的信息。

于 2014-03-09T12:51:49.837 回答