java - ¿Cómo personalizo un JComboBox para que el pop-up sea un JTree(en lugar de una lista)?
swing popup (5)
He intentado producir algo que haría algo como esto.
Al principio, traté de implementar algo en la línea sugerida por Varun, pero resultó ser un poco complicado, y me pongo un poco nervioso cuando empiezo a jugar con objetos ComponentUI (prefiero dejar ese tipo de cosas a la L y F). Si alguien tiene un buen ejemplo de hacer esto, me interesaría verlo.
Entonces probé el enfoque del botón ... y pensé que compartiría el código con la comunidad SO:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.plaf.basic.BasicInternalFrameUI;
import javax.swing.plaf.metal.MetalComboBoxIcon;
public class MockJComboBox extends JPanel {
private boolean _isPoppedUp = false;
public MockJComboBox(String label, final JComponent toShow) {
setLayout(new BorderLayout());
JLabel jLabel = new JLabel(label);
jLabel.setBackground(Color.WHITE);
add(jLabel, BorderLayout.CENTER);
Icon icon = new MetalComboBoxIcon();
final JInternalFrame popup = new JInternalFrame(null, false, false, false, false);
final JPanel panel = new JPanel(new BorderLayout());
panel.add(new JScrollPane(toShow), BorderLayout.CENTER);
if(!(System.getProperty("os.name").startsWith("Mac OS"))){
BasicInternalFrameUI ui = (BasicInternalFrameUI) popup.getUI();
ui.getNorthPane().setPreferredSize(new Dimension(0,0));
}
popup.setBorder(null);
popup.setContentPane(panel);
popup.pack();
popup.setVisible(true);
final JButton dropDownButton = new JButton(icon);
dropDownButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
_isPoppedUp = !_isPoppedUp;
Container parent = getParent();
if (_isPoppedUp) {
popup.setLocation(panel.getX(), panel.getY() + panel.getHeight());
popup.setSize(panel.getWidth(), toShow.getHeight());
parent.add(popup);
} else {
parent.remove(popup);
parent.repaint();
}
}
});
add(dropDownButton, BorderLayout.EAST);
}
public boolean isPoppedUp() {
return _isPoppedUp;
}
}
Si detecta algún error o tiene sugerencias sobre cómo mejorar este código, le agradecería sus comentarios.
Intento crear un cuadro combinado para poder poner el control que prefiera en la ventana emergente, en mi caso específico, un JTree. Echando un vistazo a cómo se implementa JComboBox, el menú emergente realmente lo crea el delegado de UI. El problema al cambiar eso es que tendría que volver a implementarse para cada apariencia, que es algo que no quiero hacer ...
Básicamente quiero un componente que tenga la apariencia de un JComboBox (en el aspecto y la sensación actuales) y el elemento emergente es un JTree (en el aspecto y la sensación actuales).
¿Cuál es la forma más fácil de hacer eso?
JComboBox en sí no puede hacer lo que quieras. Si está absolutamente casado con el concepto de hacer que actúe como un JComboBox, puede hacer que un JButton aparezca en un JPanel al hacer clic. Entonces el JPanel podría tener lo que quieras dentro (JTree, etcétera).
La respuesta para usar un botón que muestra un JPanel con un JTree es correcta. En respuesta al comentario de Carcassi, puede usar un TableCellRenderer personalizado para cambiarlo de modo que no se parezca al botón tradicional.
Solo necesita extender BasicComboBoxUI y luego anular los métodos requeridos como
public static ComponentUI createUI( JComponent c)
y
protected ComboPopup createPopup()
Crear un ComboPopup personalizado requeriría que haga un esfuerzo cuando no pueda usar el BasicComboPopUp porque extiende JPopUpMenu
public class BasicComboPopup extends JPopupMenu implements ComboPopup
Entonces, en su caso, es posible que desee extender JTree e implementar ComboPopup.
Tengo dudas sobre el tema "El problema al cambiar es que debería ser implementado nuevamente para cada aspecto". No creo que haya un problema de reimplantación.
El BasicComboPopup se ve de manera diferente en diferentes aspectos porque es un JPopupMenu que a su vez tendrá delegados de UI. Entonces, si simplemente extiendes un JTree, no deberías tener problemas con diferentes aspectos.
Una investigación web adicional reveló que Jidesoft , que se describe a sí mismo como "un proveedor de componentes Java y Swing profesional", produce un paquete llamado JIDE Grids , que incluye AbstractComboBox , cuya descripción sugiere que lo haría.
Sin embargo, es un paquete pago y no lo he probado ... Si alguien lo ha usado, ¿podrían comentar sobre la experiencia?