2012-08-23 37 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