7

私は現在、オーディオ プレイリストとして使用している JComboBox を持っています。実現したいのは、各アイテムの右側にある小さな「削除」ボタンです。これを使用して、基礎となるモデルからアイテムを削除できます。サークルは次のとおりです。

これを達成する最良の方法は何ですか?

JComboBox 内のすべての項目で同じボタンを使用したいと考えています。

デモのスクリーンショット

4

1 に答える 1

7

これは興味深い質問です(少し前に+1)。

で目的の結果を達成するのがどれほど難しいかを自分ですばやく確認する必要がありましたJComboBox。私が得た結論は(@trashgodが上記のコメントで述べているように)、このオブジェクトは他のコンポーネントを持つように設計されたことがないか、少なくとも私にはこのように感じられるというものでした。

以下はあなたが望むことをするサンプルです。JComboBoxあなたはそれを出発点として使うことができます、しかし正直に言うとあなたはこの問題のためにを使うことを忘れるべきです。

以下のサンプルは、問題に取り組む正しい方法を示しているわけではありません。それは単に問題にアプローチしようとした私の試みの結果を示しています。以下のコードは、プレゼンテーションと機能を組み合わせた(レンダラーが要素を削除する)など、優れたプラクティスルールを保持していません。これは実際には単なるハックであり、実際の解決策ではありません。

import java.awt.*;
import java.awt.event.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class ButtonCombo {

    private JPanel getContent() throws MalformedURLException {
        String[] ids = {"north", "west", "south", "east"};
        JComboBox combo = new JComboBox(ids);
        Icon removeIcon = new ImageIcon(new URL("http://filesharefreak.org/images/red_x.png"));
        combo.setRenderer(new ButtonComboRenderer(removeIcon, combo));
        JPanel panel = new JPanel();
        panel.add(combo);
        return panel;
    }

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

            @Override
            public void run() {
                try {
                    JFrame f = new JFrame();
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    JPanel panel = new JPanel();
                    panel.add(new ButtonCombo().getContent());
                    JButton button = new JButton("OKOKO");
                    panel.add(button);
                    f.setContentPane(panel);
                    f.setSize(300, 160);
                    f.setLocation(200, 200);
                    f.setVisible(true);
                } catch (MalformedURLException ex) {
                    Logger.getLogger(ButtonCombo.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }
}

class ButtonComboRenderer implements ListCellRenderer {
    Icon icon;
    JPanel panel;
    JLabel label;
    JButton button;

    public ButtonComboRenderer(Icon removeIcon, final JComboBox combo) {
        icon = removeIcon;
        label = new JLabel();
        button = new JButton(icon);
        button.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
        panel = new JPanel(new BorderLayout());
        panel.add(label);
        panel.add(button, BorderLayout.EAST);
        panel.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                if (button.getX() < e.getX()) {
                    System.out.println("button contains the click remove the item");
                    combo.removeItem(label.getText());
                }
            }
        });
    }
    //so we will install the mouse listener once
    boolean isFirst = true;

    @Override
    public Component getListCellRendererComponent(JList list,
            Object value,
            int index,
            boolean isSelected,
            boolean cellHasFocus) {
        if (isFirst) {
            isFirst = false;
            list.addMouseListener(new MouseAdapter() {

                @Override
                public void mousePressed(MouseEvent e) {
                    panel.dispatchEvent(e);
                    e.consume();
                }
            });
        }
        String text = (String) value;
        label.setText(text);
        if(text == null)
            button.setIcon(null);
        else if(button.getIcon() == null)
            button.setIcon(icon);
        panel.setBackground(isSelected ? Color.red : Color.white);
        panel.setForeground(isSelected ? Color.white : Color.black);
        return panel;
    }
}

私の最後の推奨事項とそれを行う方法は次のとおり です。独自のコンポーネントを構築します。トリガーとプレゼンテーションから分離することで、拡張可能で変更可能にします。どちらもJComponent、レンダラーを使用するのとは反対にsを使用します。JListこのようにして、この場合のようにすべてのイベントがレンダリングに使用されることによってキャプチャされるのではなく、コンポーネントでイベントをキャプチャして提供することができます。

以下は、始めるのに役立つサンプルです。これは最終的な解決策ではありませんが、そのようなコンポーネントの作成に関連する多くの重要な問題を提示します。提示された機能を使用し、それに応じてすべてを単一のコンポーネントにラップする必要があります。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;

public class MockJComboBox {

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

            @Override
            public void run() {
                final JPanel popupContent = new JPanel(new GridLayout(0, 1));
                popupContent.setBackground(Color.GREEN);
                popupContent.add(new JLabel("Content of popupContent panel"));
                popupContent.add(new JLabel("Content of popupContent panel"));
                popupContent.add(new JLabel("Content of popupContent panel"));
                popupContent.add(new JLabel("Content of popupContent panel"));
                popupContent.add(new JLabel("Content of popupContent panel"));
                popupContent.add(new JComboBox(new Object[]{"Content of popupContent panel"}));
                final JButton popupCloseButton = new JButton("X");
                popupContent.add(popupCloseButton);

                final JScrollPane s = new JScrollPane(popupContent);
                s.setPreferredSize(new Dimension(popupContent.getPreferredSize().width + s.getVerticalScrollBar().getPreferredSize().width
                        + s.getBorder().getBorderInsets(s).left
                        + s.getBorder().getBorderInsets(s).right, 100));

                JPanel panel = new JPanel();
                panel.setPreferredSize(new Dimension(200, 200));
                final JButton popupOpenButton = new JButton();
                panel.add(popupOpenButton);
                final JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setContentPane(panel);
                final PopupFactory popupFactory = PopupFactory.getSharedInstance();
                popupOpenButton.setAction(new AbstractAction("Open") {
                    private Popup popup;
                    private boolean isShown = false;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (isShown) {
                            popup.hide();
                        } else {
                            popup = popupFactory.getPopup(popupOpenButton, s,
                                    popupOpenButton.getLocationOnScreen().x, popupOpenButton.getLocationOnScreen().y + popupOpenButton.getHeight());
                            popupCloseButton.setAction(new AbstractAction(popupCloseButton.getText()) {

                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    isShown = false;
                                    popup.hide();
                                }
                            });
                            popup.show();
                        }
                        isShown = !isShown;
                    }
                });
                f.pack();
                f.setVisible(true);
            }
        });
    }
}
于 2012-06-19T08:48:23.507 に答える