4

コンボ ボックスを作成して、好みのコントロールをポップアップ内に配置できるようにしようとしています。私の特定のケースでは JTree です。JComboBox の実装方法を見ると、ポップアップは実際には UI デリゲートによって作成されます。それを変更する際の問題は、ルックアンドフィールごとに再実装する必要があることです。これは私がやりたくないことです...

私は基本的に、(現在のルック アンド フィールで) JComboBox のルック アンド フィールを持ち、ポップアップが (現在のルック アンド フィールで) JTree であるコンポーネントが必要です。

それを行う最も簡単な方法は何ですか?

4

5 に答える 5

2

JComboBox 自体は、あなたが望むことはできません。JComboBox のように動作させるという概念に完全に固執している場合は、JButton をクリックすると JPanel がポップアップするようにすることができます。次に、JPanel には、必要なもの (JTree など) を含めることができます。

于 2009-11-24T18:38:11.777 に答える
1

私はこのようなことをする何かを作ることに挑戦しました。

最初は、Varunによって提案された方針に沿って何かを実装しようとしましたが、それは少し厄介であることがわかり、ComponentUIオブジェクトで遊び始めると、少し緊張します(そのようなことは、 L&F)。誰かがこれを行う良い例を持っているなら、私はそれを見たいと思います。

それで私はボタンアプローチを試しました...そして私はコードをSOコミュニティと共有すると思いました:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.plaf.basic.BasicInternalFrameUI;
import javax.swing.plaf.metal.MetalComboBoxIcon;

public class MockJComboBox extends JPanel  {

  private boolean _isPoppedUp = false;

  public MockJComboBox(String label, final JComponent toShow) {
    setLayout(new BorderLayout());
    JLabel jLabel = new JLabel(label);
    jLabel.setBackground(Color.WHITE);
    add(jLabel, BorderLayout.CENTER);
    Icon icon = new MetalComboBoxIcon();

    final JInternalFrame popup = new JInternalFrame(null, false, false, false, false);
    final JPanel panel = new JPanel(new BorderLayout());
    panel.add(new JScrollPane(toShow), BorderLayout.CENTER);
    if(!(System.getProperty("os.name").startsWith("Mac OS"))){
      BasicInternalFrameUI ui = (BasicInternalFrameUI) popup.getUI();
      ui.getNorthPane().setPreferredSize(new Dimension(0,0));
    }
    popup.setBorder(null);
    popup.setContentPane(panel);
    popup.pack();
    popup.setVisible(true);

    final JButton dropDownButton = new JButton(icon);
    dropDownButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        _isPoppedUp = !_isPoppedUp;
        Container parent = getParent();
        if (_isPoppedUp) {
          popup.setLocation(panel.getX(), panel.getY() + panel.getHeight());
          popup.setSize(panel.getWidth(), toShow.getHeight());
          parent.add(popup);
        } else {
          parent.remove(popup);
          parent.repaint();
        }
      }
    });
    add(dropDownButton, BorderLayout.EAST);
  }

  public boolean isPoppedUp() {
    return _isPoppedUp;
  }
}

バグを見つけたり、このコードを改善する方法について提案があれば、コメントをいただければ幸いです。

于 2011-11-11T14:58:11.733 に答える
0

JTree で JPanel をポップアップするボタンを使用するという答えは正しいです。Carcassi のコメントに応えて、カスタムの TableCellRenderer を使用して、従来のボタンのように見えないように変更できます。

于 2009-12-03T18:09:12.910 に答える
0

BasicComboBoxUI を拡張して、次のような必要なメソッドをオーバーライドするだけです。

public static ComponentUI createUI( JComponent c) 

protected ComboPopup createPopup()

カスタム ComboPopup を作成するには、JPopUpMenu を拡張するため、BasicComboPopUp を使用できない場合にいくらかの努力が必要になります。

public class BasicComboPopup extends JPopupMenu implements ComboPopup

したがって、あなたの場合、JTree を拡張して ComboPopup を実装することができます。

「変更する際の問題は、ルックアンドフィールごとに再実装する必要があることです」という部分には疑問があります。再実装の問題はないと思います。

BasicComboPopup は、UI デリゲートを持つ JPopupMenu であるため、別のルック アンド フィールでは異なって見えます。したがって、単に JTree を拡張するだけであれば、異なるルック アンド フィールで問題が発生することはありません。

于 2009-11-24T21:18:54.133 に答える