1

我在 JList 的 JLayeredPane 中有一个按钮,因此我可以在鼠标悬停时在每一行上覆盖图标按钮。但是,这些按钮不接受鼠标点击。代码如下。单击任何内容时都不会输出任何内容。如果我向 JList 添加一个鼠标侦听器,它将被调用。

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JList;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;


public class TestListLayered
{
    public static class LayeredListCellRenderer extends DefaultListCellRenderer
    {
        @Override
        public Component getListCellRendererComponent(final JList list, final Object value, final int index,
                final boolean isSelected, final boolean cellHasFocus)
        {
            final JLayeredPane pane = new JLayeredPane();
            final JLabel label = (JLabel) super.getListCellRendererComponent(list, value.toString(), index, isSelected,
                    cellHasFocus);
            label.setHorizontalAlignment(SwingConstants.RIGHT);
            label.setBounds(0, 0, 100, 20);
            pane.add(label, JLayeredPane.DEFAULT_LAYER);

            final JButton edit = new JButton("e");
            final FontMetrics fontMetrics = edit.getFontMetrics(edit.getFont());
            final int height2 = (int) (1.5 * fontMetrics.getHeight());
            edit.setBounds(0, 0, (int) (1.5 * fontMetrics.stringWidth("e")), height2);
            edit.addActionListener(new ActionListener()
            {
                @Override
                public void actionPerformed(final ActionEvent e)
                {
                    System.out.println("button");
                }
            });
            pane.addMouseListener(new MouseAdapter()
            {
                @Override
                public void mouseClicked(final MouseEvent e)
                {
                    System.out.println("layeredpane");
                }
            });
            pane.add(edit, JLayeredPane.PALETTE_LAYER);

            pane.setPreferredSize(new Dimension(-1, height2));
            pane.setBorder(new LineBorder(Color.blue));
            return pane;
        }
    }

    public static void main(final String[] args)
    {
        final JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JList<String> l = new JList<String>(new String[] { "item 1", "item 2" });
        l.setCellRenderer(new LayeredListCellRenderer());
        f.add(l);

        f.pack();
        f.setVisible(true);
    }
}
4

2 回答 2

2

首先,我只想说,这很奇怪……

基本上,您应该MouseListenerJList. 单击它时,您需要找到所选行的单元格边界,将鼠标点转换为单元格渲染器的本地上下文,然后测试鼠标是否在按钮的边界内单击...

之后你做什么取决于你。

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class TestListLayered {

    public static class LayeredListCellRenderer extends DefaultListCellRenderer {

        private JButton edit = new JButton("e");

        @Override
        public Component getListCellRendererComponent(final JList list, final Object value, final int index,
                final boolean isSelected, final boolean cellHasFocus) {
            final JLayeredPane pane = new JLayeredPane();
            final JLabel label = (JLabel) super.getListCellRendererComponent(list, value.toString(), index, isSelected,
                    cellHasFocus);
            label.setHorizontalAlignment(SwingConstants.RIGHT);
            label.setBounds(0, 0, 100, 20);
            pane.add(label, JLayeredPane.DEFAULT_LAYER);

            final FontMetrics fontMetrics = edit.getFontMetrics(edit.getFont());
            final int height2 = (int) (1.5 * fontMetrics.getHeight());
            edit.setBounds(0, 0, (int) (1.5 * fontMetrics.stringWidth("e")), height2);
            pane.add(edit, JLayeredPane.PALETTE_LAYER);

            pane.setPreferredSize(new Dimension(-1, height2));
            pane.setBorder(new LineBorder(Color.blue));
            return pane;
        }

        protected void buttonClicked(Point p) {
            System.out.println(edit.contains(p));
        }
    }

    public static void main(final String[] args) {
        new TestListLayered();
    }

    public TestListLayered() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                final JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final JList<String> l = new JList<String>(new String[]{"item 1", "item 2"});
                l.setCellRenderer(new LayeredListCellRenderer());
                f.add(new JScrollPane(l));

                l.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        int index = l.locationToIndex(e.getPoint());
                        if (index > -1) {

                            Rectangle bounds = l.getCellBounds(index, index);
                            LayeredListCellRenderer cellRenderer = (LayeredListCellRenderer) l.getCellRenderer();
                            Component renderComp = cellRenderer.getListCellRendererComponent(l, l.getModel().getElementAt(index), index, false, false);
                            renderComp.setBounds(bounds);

                            Point local = new Point(e.getPoint());
                            local.x -= bounds.x;
                            local.y -= bounds.y;

                            cellRenderer.buttonClicked(local);

                        }
                    }
                });

                f.pack();
                f.setVisible(true);
            }
        });
    }
}

我只想说,我同意camickr,最好使用2列JTable......

于 2013-04-17T00:25:43.520 回答
2

渲染器不是真正的组件。它只是一个组件的绘画。所以按钮不会响应点击。

不确定我是否理解您要执行的操作,但也许您可以使用两列 JTable。因为表格支持编辑器,所以它会响应鼠标点击。 表格按钮列可以在这里为您提供帮助。

于 2013-04-16T21:57:19.617 回答