2012-06-16 68 views
6

我目前有一個JComboBox,我用它作爲音頻播放列表 - 我想要實現的是每個項目右側的一個小「刪除」按鈕,我可以使用它將其從底層模型中刪除,其中圓圈是:JComboBox項目中的顯示按鈕

實現此目的的最佳方法是什麼?

我希望按鈕對於JComboBox中的所有項目都是相同的。

demo screenshot

+0

是要'1)'把JLabel的,並與一個JButton的一個項目,'2)'在JComboBox中的所有項目或不是 – mKorbel

+0

@mKorbel不確定你的意思是你的第一點?但是對於第二點,是的。 – berry120

+0

那裏,我看到一個重要的問題,JComboBox的DROP_DOWN任何Mouse_click到項目(Java1.4和更高版本)後自行消失,你同意並接受 – mKorbel

回答

8

讓我說,這是一個有趣的問題(+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,因爲它們反對使用渲染器。通過這種方式,您將能夠捕獲和處理組件上的事件,而不是像這樣所有事件都被用於渲染的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); 
      } 
     }); 
    } 
} 
+1

+1,很好的答案,謝謝! – berry120