2012-06-16 69 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