【问题标题】:JComboBox(JList) - Clickable Image for each cellJComboBox(JList) - 每个单元格的可点击图像
【发布时间】:2016-12-30 08:59:42
【问题描述】:

我正在尝试编辑 JComboBox,使其在每个单元格中都有一个“删除”按钮(图像/图标)来删除特定条目。 我已经尝试创建自定义 CellRenderer,我能够添加图像但不能对鼠标点击做出反应(至少我不知道点击了哪个图像/单元格),我只能获得 X 和 Y 位置。但我不知道图像的位置。

如果有人对如何做到这一点有任何想法,我将不胜感激,我已经尝试过 google,但我没有找到任何像样的东西。

【问题讨论】:

  • 很难做到,因为弹出窗口是另一个通过组合框 UI 显示的窗口,并且与原始组合框组件没有任何直接联系。此外,实现细节可能会因您使用的外观而异。作为一个衷心的建议:找到另一个解决方案。如果您不愿意接受此建议,请阅读一些有关编写自己的外观组件的基础知识,并参考 BasicComboBoxUI。
  • @mtj 自己的外观和感觉不是一个选项,它是一个使用系统外观和感觉的商业应用程序,我猜这就是它应该保持的方式。无论如何,为此制作自己的外观和感觉是不值得的功能
  • 有一个带有JTable的ComboBoxEditor(带有不需要的列数),那么很容易也可以用AbstractButton将布尔值存储在XxxTableModel中,也许直接未修饰的JToggleButton,有一个问题,你可以' t 存储一些 JCcomponents 和 Icon 而不使用 JButtons 组件,否则需要付出巨大的努力
  • @mKorbel 需要详细说明吗?我发现的关于 ComboBoxEditor 和 JTable 的唯一参考是关于使用组合框作为表格单元格编辑器。
  • 显示 JTable 而不是 JList(API 中的默认实现),不要使用 mouseEvents 和 JList,因为弹出窗口消失,立即隐藏

标签: java image swing icons clickable


【解决方案1】:

使用面板构建您的 UI。构建一个包含标签和按钮的面板(您可以添加图像作为背景)。将此面板作为项目添加到组合框中。

http://www.codejava.net/java-se/swing/create-custom-gui-for-jcombobox

【讨论】:

  • 已经考虑过了,但我认为这是一种肮脏的方式,这将是我最后的手段。
【解决方案2】:

这可能(?)给你一些想法。

它使用 JLayer 类来装饰 JList 并绘制关闭图标(在示例中是一个简单的“X”字符)。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import javax.swing.plaf.basic.*;

class LayerList extends JPanel
{
    LayerList()
    {
        LayerUI<JComponent> layerUI = new LayerUI<JComponent>()
        {
            public void paint(Graphics g, JComponent c)
            {
                super.paint(g, c);

                JLayer layer = (JLayer)c;
                JList list = (JList)layer.getView();
                int selected = list.getSelectedIndex();

                if (selected == -1 ) return;

                Rectangle area = list.getCellBounds(selected, selected);

                g.drawString("X", area.width - 15, area.y + area.height - 3);
            }

            public void installUI(JComponent c)
            {
                super.installUI(c);

                JLayer jlayer = (JLayer)c;
                jlayer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
            }

            public void uninstallUI(JComponent c)
            {
                super.uninstallUI(c);

                // reset the layer event mask
                ((JLayer) c).setLayerEventMask(0);
            }

            @Override
            protected void processMouseEvent(MouseEvent e, JLayer l)
            {
//              e.consume();

                if (e.getID() == MouseEvent.MOUSE_RELEASED)
                {
                    JList list = (JList)e.getComponent();
                    int selected = list.getSelectedIndex();
                    Rectangle area = list.getCellBounds(selected, selected);

                    if (e.getX() >= area.width - 15)
                    {
                        e.consume();
                        DefaultComboBoxModel model = (DefaultComboBoxModel)list.getModel();
                        model.removeElementAt( selected );
                        list.setSelectedIndex(selected);
                    }
                }
            }
        };

        String[] data = { "a", "b", "c", "d", "e", "f" };

        JComboBox<String> comboBox = new JComboBox<String>(data);

        Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
        BasicComboPopup popup = (BasicComboPopup)child;
        JList list = (JList)popup.getList();
        Container c = SwingUtilities.getAncestorOfClass(JScrollPane.class, list);
        JScrollPane scrollPane = (JScrollPane)c;
        scrollPane.setViewportView( new JLayer<JComponent>(list, layerUI) );


        setLayout( new BorderLayout() );
        add( comboBox );
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Layer List");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new LayerList() );
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

阅读 How to Decorate Components with the JLayer Class 上的 Swing 教程部分,了解更多信息和使用 JLayer 类的示例。

【讨论】:

  • 这看起来很有前途,明天去测试,谢谢。
猜你喜欢
  • 2012-11-07
  • 2012-06-26
  • 2012-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 2021-01-08
相关资源
最近更新 更多