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 对象时我有点紧张(我宁愿把这种事情留给如果)。如果有人有这样做的好例子,我很想看看。

所以然后我尝试了按钮方法......并认为我会与 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

进一步的网络研究表明,自称为“专业的 Java 和 Swing 组件提供商”的Jidesoft生产了一个名为JIDE Grids的包,其中包括AbstractComboBox - 其描述表明它会这样做。

但是,这是一个付费套餐,我还没有尝试过......如果有人使用过这个,他们可以评论一下体验吗?

于 2012-06-06T14:40:29.377 回答
0

您只需要扩展 BasicComboBoxUI 然后覆盖所需的方法,例如

public static ComponentUI createUI( JComponent c) 

protected ComboPopup createPopup()

创建自定义 ComboPopup 需要您在无法使用 BasicComboPopUp 的地方付出一些努力,因为它扩展了 JPopUpMenu

public class BasicComboPopup extends JPopupMenu implements ComboPopup

因此,在您的情况下,您可能希望扩展 JTree 并实现 ComboPopup。

我怀疑“改变它的问题是它需要为每个外观和感觉重新实现”部分。我不认为重新实施会有问题。

BasicComboPopup 在不同的外观和感觉上看起来不同,因为它是一个 JPopupMenu,而它又将具有 UI 委托。因此,如果您只是扩展 JTree,您应该不会遇到外观和感觉不同的问题。

于 2009-11-24T21:18:54.133 回答