简体   繁体   English

如何在JList中的JLayeredPane中单击按钮

[英]How to get clicks on a button in a JLayeredPane in a JList

I have a button in a JLayeredPane in a JList so I can overlay icon buttons on each row on mouse over. 我在JList中的JLayeredPane中有一个按钮,所以我可以在鼠标上的每一行上叠加图标按钮。 However, the buttons are not accepting mouse clicks. 但是,按钮不接受鼠标单击。 The code is below. 代码如下。 Nothing is output when clicking on anything. 单击任何内容时都不会输出任何内容。 If I add a mouse listener to the JList, that will be called. 如果我向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);
    }
}

A renderer is not a real component. 渲染器不是真正的组件。 It is just a painting of a component. 它只是一个组件的绘画。 So the button will not respond to clicks. 因此按钮不会响应点击。

Not sure I understand what you are trying to do, but maybe you can use a two column JTable. 不确定我理解你想要做什么,但也许你可以使用两列JTable。 Because a table supports an editor it does respond to mouse clicks. 因为表支持编辑器,所以它确实响应鼠标点击。 Table Button Column can help you here. 表按钮列可以在这里帮助您。

First, I just want to say, this is very weird... 首先,我只是想说,这很奇怪......

Basically, you should add a MouseListener to the JList . 基本上,您应该将一个MouseListener添加到JList When it's clicked, you need to find the cell bounds of the selected row, convert the mouse point into a local context for the cell renderer and then test to see if the mouse clicked within the bounds of the button... 单击它时,您需要找到所选行的单元格边界,将鼠标点转换为单元格渲染器的本地上下文,然后测试鼠标是否在按钮的边界内单击...

What you do after that is up to you. 你做了什么取决于你。

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

I'd just like to say, I agree with camickr, it would be better to use a 2 column JTable ... 我只想说,我同意camickr,最好使用2列JTable ......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM