2012-08-23 36 views
3

我想在JComboBox里放一个JButton。该按钮可让用户浏览文件。用户选择的文件被添加到JComboBox列表中。我该怎么做呢?我是否使用某种渲染器?谢谢。如何把JButton放在JComboBox里面

编辑: 阅读更多关于ListCellRenderer后,我尝试下面的代码:

JComboBox comboBox = new JComboBox(new String[]{"", "Item1", "Item2"}); 
ComboBoxRenderer renderer = new ComboBoxRenderer(); 
comboBox.setRenderer(renderer); 

class ComboBoxRenderer implements ListCellRenderer { 

    public Component getListCellRendererComponent(
      JList list, 
      Object value, 
      int index, 
      boolean isSelected, 
      boolean cellHasFocus) { 

     JButton jbutton = new JButton("Browse"); 

     return jbutton; 
    } 
} 

上述的问题是按钮“浏览”将添加3次,我希望它显示只有一次和下面显示Item1和Item2作为普通/常规组合框选择对象。

回答

3

我会避免JButton。在组合框内部获得JButton的图像是完全可能的,但它不会将其本身表现为按钮。你不能点击它,它永远不会被视觉上“压”或“释放”......。简而言之,您的组合框将包含您的用户不熟悉的项目。

原因是您在getListCellRendererComponent方法中返回的组件不包含在JCombobox中。它们只被用作邮票。这也解释了为什么您可以(也应该)重复使用该方法返回的Component,而不是一直创建新组件。这部分在JTable教程中关于Renderers and Editors(解释为JTable,但适用于所有其他使用渲染器和编辑器的Swing组件)中进行了说明。

如果你真的想在允许显示文件选择组合框的项目,我会选择类似于以下SSCCE东西:

import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import java.awt.EventQueue; 
import java.awt.event.ItemEvent; 
import java.awt.event.ItemListener; 

public class ComboboxTest { 

    public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
     JFrame frame = new JFrame("TestFrame"); 
     JComboBox<String> comboBox = new JComboBox<>(new String[]{"Item1", "Item2"}); 
     final String browse = "<<BROWSE>>"; 
     comboBox.addItem(browse); 
     comboBox.addItemListener(new ItemListener() { 
      @Override 
      public void itemStateChanged(ItemEvent e) { 
      if (e.getStateChange() == ItemEvent.SELECTED && 
       browse.equals(e.getItem())){ 
       System.out.println("Show filechooser"); 
      } 
      } 
     }); 
     frame.add(comboBox); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     frame.pack(); 
     } 
    }); 
    } 
} 
+0

谢谢你的详细解答罗宾。上面发布的示例显示了如何向浏览组件添加Event Listener,但它仍作为常规JList文本显示给用户。我已经看到ComboBoxes中的按钮应用程序,不管它们是用Java写的还是不是我都不确定。 – jadrijan

+0

@jadrijan当然,它看起来不像一个按钮。这就是我想说的......你可以使用'JButton',但它永远不会像一个。所以最好不要使用'JButton' imo – Robin

+0

我完全理解你的罗宾。 :)我只是想澄清一点,它不违反Java的“规则”去做我所做的事情。 – jadrijan

1

确实,您将不得不使用自定义渲染器,如http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html#renderer中所述。

+1

你会怎么按按钮,如果你只有一个渲染器? – Robin

+0

@Robin:你不会改变按钮的渲染器,只会改变JCombobox的渲染器。该按钮仍然可以像在组合框外部一样工作。 – Silox

+1

你真的尝试过吗?在渲染器中返回的组件不包含在'JComboBox'中,所以你将不能按下按钮 – Robin

1

根据您想要放置搜索按钮的位置,您可以查看xswingx Prompt/Buddy API。您可以使用它来与编辑器字段“伙伴”浏览按钮

或者您可以简单地在组合框旁边添加浏览按钮。

+0

谢谢,我真的想把按钮放在组合框旁边,而不是在它旁边。我原以为会有更简单的方法来做到这一点,而不是使用第三方API。 – jadrijan

+1

从内存来看,组合框的布局似乎是由UI委托(外观和感觉)完成的,我可能是错的,但这就是我似乎记得的 – MadProgrammer

1

尝试很多东西,我想我想通了答案后,我相信,当你看到它,它会显得很轻松:

 JComboBox comboBox = new JComboBox(new String[]{"Item1", "Item2"}); 
     ComboBoxRenderer renderer = new ComboBoxRenderer(); 
     comboBox.setRenderer(renderer); 
     comboBox.addItem("<<BROWSE>>"); 

class ComboBoxRenderer implements ListCellRenderer { 

     @Override 
     public Component getListCellRendererComponent(JList list, Object value, int index,   boolean isSelected, boolean cellHasFocus) { 
      if (value.equals("<<BROWSE>>")) { 
       JButton btn = new JButton("Browse"); 
       return btn; 
      } else { 
       JLabel lbl = new JLabel(value.toString()); 
       lbl.setOpaque(true); 
       return lbl; 
      } 
     } 
    } 

现在,您可以自定义按钮和标签你希望的任何方式。

+1

1.不要创建新组件,而要重新使用和调整现有组件在你的渲染器中2.你不能通过简单地使用渲染器来按下按钮。 – Robin