2012-06-16 18 views
6

Actualmente tengo un JComboBox que estoy usando como lista de reproducción de audio, lo que me gustaría lograr es un pequeño botón "quitar" en el lado derecho de cada elemento que pueda usar para eliminarlo del modelo subyacente, donde el círculo es:Botones de pantalla en elementos de JComboBox

¿Cuál sería la mejor manera de lograr esto?

Me gustaría que el botón sea el mismo para todos los elementos en el JComboBox.

demo screenshot

+0

son desea '1)' poner JLabel y con JButton a la de un artículo, '2)' para todos los artículos del JComboBox o no – mKorbel

+0

@mKorbel ¿No está seguro de lo que quiere decir con su primer punto? Pero para el segundo punto, sí. – berry120

+0

veo un problema importante, JComboBox drop_down desaparece después de cualquier mouse_click al elemento (Java1.4 y superior), ¿está de acuerdo y acepta que – mKorbel

Respuesta

8

Empezaré diciendo que esto es una pregunta interesante (hace 1 un tiempo).

Tuve que probar rápidamente y ver por mí mismo lo difícil que es lograr el resultado deseado con JComboBox. La conclusión que obtuve (como dice @trashgod en el comentario anterior) fue que este objeto nunca fue diseñado para tener otros componentes o al menos me parece así.

A continuación se muestra una muestra que hace lo que usted quiere. Puede usarlo como inicio, pero para ser honesto, debe olvidarse de usar el JComboBox para este problema.

De ninguna manera el ejemplo siguiente presenta la forma correcta de abordar el problema. Simplemente muestra el resultado de mis intentos de abordar el problema. El siguiente código no conserva las reglas de buenas prácticas, p. mezcla la presentación con la funcionalidad (el renderizador elimina los elementos). Esto es, de hecho, solo un truco, no una solución real.

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; 
    } 
} 

Mi recomendación final y la forma en que lo haría es: construir su propio componente. Haz que sea extensible y modificable al separarlo del activador y la presentación, donde ambos usan JComponent s, ya que se oponen al uso de un renderizador. De esta forma, podría capturar y servir eventos en los componentes en lugar de en este caso todos los eventos son capturados por el JList utilizado para la representación.

A continuación hay una muestra que debería ayudarlo a comenzar. No es la solución final, pero presenta muchas de las cuestiones importantes involucradas en la creación de dicho componente. Se debe utilizar la funcionalidad presentada y envolverlo todo en consecuencia en un solo componente:

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, excelente respuesta, gracias! – berry120