¿Cómo hago una lista con casillas de verificación en Java Swing?

¿Cuál sería la mejor manera de tener una lista de elementos con una checkbox cada uno en Java Swing?

Es decir, una Lista J con elementos que tienen algo de texto y una checkbox cada uno.

Cree un ListCellRenderer personalizado y asígnelo a la JList .

Este ListCellRenderer personalizado debe devolver un JCheckbox en la implementación del getListCellRendererComponent(...) .

Pero esta JCheckbox no será editable, es una simple pintura en la pantalla depende de usted elegir cuándo esta JCheckbox debe estar ‘marcada’ o no,

Por ejemplo, muéstrela marcada cuando se selecciona la fila (el parámetro está isSelected ), pero de esta forma el estado de verificación no se mantendrá si la selección cambia. Es mejor mostrar que verificó consultando los datos debajo del ListModel , pero depende de usted implementar el método que cambia el estado de verificación de los datos, y notificar el cambio a la JList para volver a pintar.

Publicaré el código de muestra más tarde si lo necesitas

ListCellRenderer

Una respuesta maravillosa es esta CheckBoxList . Implementa la respuesta de Telcontar (aunque 3 años antes:) … Lo estoy usando en Java 1.6 sin problemas. También agregué un método addCheckbox como este (seguramente podría ser más corto, no he usado Java desde hace tiempo):

 public void addCheckbox(JCheckBox checkBox) { ListModel currentList = this.getModel(); JCheckBox[] newList = new JCheckBox[currentList.getSize() + 1]; for (int i = 0; i < currentList.getSize(); i++) { newList[i] = (JCheckBox) currentList.getElementAt(i); } newList[newList.length - 1] = checkBox; setListData(newList); } 

Probé la demostración para las cosas de Jidesoft, jugando con CheckBoxList encontré algunos problemas (comportamientos que no funcionaron). Modificare esta respuesta si encuentro problemas con la CheckBoxList me he vinculado.

Probablemente esté buscando usar una JTable en lugar de una JList y dado que la representación predeterminada de una checkbox es bastante fea, probablemente buscaría incluir un TableModel , CellRenderer y CellEditor personalizados para representar un valor booleano. Por supuesto, me imagino que esto ya se ha hecho miles de millones de veces. Sun tiene buenos ejemplos .

Solo implemente un ListCellRenderer

 public class CheckboxListCellRenderer extends JCheckBox implements ListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setComponentOrientation(list.getComponentOrientation()); setFont(list.getFont()); setBackground(list.getBackground()); setForeground(list.getForeground()); setSelected(isSelected); setEnabled(list.isEnabled()); setText(value == null ? "" : value.toString()); return this; } } 

y establecer el renderizador

 JList list = new JList(); list.setCellRenderer(new CheckboxListCellRenderer()); 

esto dará como resultado

Ejemplo de CheckboxListCellRenderer

Detalles en los renderizadores de componentes personalizados .

PD: si quieres elementos de radio simplemente reemplaza extends JCheckbox con extends JRadioButton .

Mejor solución para Java 7 y más reciente

Me encontré con esta pregunta y me di cuenta de que algunas de las respuestas son bastante antiguas y obsoletas. Hoy en día, JList es genérico y, por lo tanto, hay mejores soluciones.

Mi solución del genérico JCheckBoxList:

 import java.awt.Component; import javax.swing.*; import javax.swing.border.*; import java.awt.event.*; @SuppressWarnings("serial") public class JCheckBoxList extends JList { protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); public JCheckBoxList() { setCellRenderer(new CellRenderer()); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { int index = locationToIndex(e.getPoint()); if (index != -1) { JCheckBox checkbox = (JCheckBox) getModel().getElementAt(index); checkbox.setSelected(!checkbox.isSelected()); repaint(); } } }); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } public JCheckBoxList(ListModel model){ this(); setModel(model); } protected class CellRenderer implements ListCellRenderer { public Component getListCellRendererComponent( JList< ? extends JCheckBox> list, JCheckBox value, int index, boolean isSelected, boolean cellHasFocus) { JCheckBox checkbox = value; //Drawing checkbox, change the appearance here checkbox.setBackground(isSelected ? getSelectionBackground() : getBackground()); checkbox.setForeground(isSelected ? getSelectionForeground() : getForeground()); checkbox.setEnabled(isEnabled()); checkbox.setFont(getFont()); checkbox.setFocusPainted(false); checkbox.setBorderPainted(true); checkbox.setBorder(isSelected ? UIManager .getBorder("List.focusCellHighlightBorder") : noFocusBorder); return checkbox; } } } 

Para agregar dinámicamente listas JCheckBox, necesita crear su propio ListModel o agregar DefaultListModel.

 DefaultListModel model = new DefaultListModel(); JCheckBoxList checkBoxList = new JCheckBoxList(model); 

DefaultListModel es genérico y por lo tanto puede usar los métodos especificados por JAVA 7 API aquí de esta manera:

 model.addElement(new JCheckBox("Checkbox1")); model.addElement(new JCheckBox("Checkbox2")); model.addElement(new JCheckBox("Checkbox3")); 

Las probabilidades son buenas con Java de que alguien ya haya implementado el widget o la utilidad que necesita. Parte de los beneficios de una gran comunidad de OSS. No es necesario reinventar la rueda a menos que realmente quieras hacerlo tú mismo. En este caso, sería un buen ejercicio de aprendizaje en CellRenderers and Editors.

Mi proyecto ha tenido un gran éxito con JIDE. El componente que desea, una Lista de casillas de verificación, está en la capa común de JIDE (que es OSS y está alojado en java.net). El material comercial también es bueno, pero no lo necesitas.

http://www.jidesoft.com/products/oss.htm https://jide-oss.dev.java.net/

Te recomiendo que uses un JPanel con una columna GridLayout de 1. Agregue checkBoxes al JPanel y configure el JPanel como fuente de datos de JScrollPane. Y para obtener CheckBoxes seleccionados, solo llame a getComponents () de JPanel para obtener CheckBoxes.

Aquí hay solo una pequeña adición a la JCheckBoxList de Rawa. Esto agregará la capacidad de seleccionar usando la barra espaciadora. Si se seleccionan varios elementos, todos se establecerán en el valor invertido del primer elemento.

  addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { int index = getSelectedIndex(); if (index != -1 && e.getKeyCode() == KeyEvent.VK_SPACE) { boolean newVal = !((JCheckBox) (getModel() .getElementAt(index))).isSelected(); for (int i : getSelectedIndices()) { JCheckBox checkbox = (JCheckBox) getModel() .getElementAt(i); checkbox.setSelected(newVal); repaint(); } } } }); 

Todos los componentes agregados en Swing, es decir, los componentes formados por otros componentes, como JTable, JTree o JComboBox, se pueden personalizar en gran medida. Por ejemplo, un componente JTable normalmente muestra una grilla de componentes JLabel, pero también puede mostrar JButtons, JTextFields o incluso otras JTables. Sin embargo, conseguir que estos componentes agregados muestren objetos no predeterminados es la parte más fácil. Hacer que respondan adecuadamente a los eventos de teclado y mouse es una tarea mucho más difícil, debido a la separación de componentes de Swing en “renderizadores” y “editores”. Esta separación fue (en mi opinión) una opción de diseño deficiente y solo sirve para complicar las cosas al tratar de extender los componentes de Swing.

Para ver lo que quiero decir, intente mejorar el componente JList de Swing para que muestre casillas de verificación en lugar de tags. Según la filosofía de Swing, esta tarea requiere implementar dos interfaces: ListCellRenderer (para dibujar las casillas de verificación) y CellEditor (para manejar los eventos de teclado y mouse en las casillas de verificación). Implementar la interfaz de ListCellRenderer es bastante fácil, pero la interfaz de CellEditor puede ser bastante torpe y difícil de entender. En este caso particular, sugeriría olvidar por completo el CellEditor y manejar los eventos de entrada directamente, como se muestra en el siguiente código.

 import javax.swing.*; import javax.swing.border.*; import java.awt.*; import java.awt.event.*; public class CheckBoxList extends JList { protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); public CheckBoxList() { setCellRenderer(new CellRenderer()); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { int index = locationToIndex(e.getPoint()); if (index != -1) { JCheckBox checkbox = (JCheckBox) getModel().getElementAt(index); checkbox.setSelected( !checkbox.isSelected()); repaint(); } } } ); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } protected class CellRenderer implements ListCellRenderer { public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { JCheckBox checkbox = (JCheckBox) value; checkbox.setBackground(isSelected ? getSelectionBackground() : getBackground()); checkbox.setForeground(isSelected ? getSelectionForeground() : getForeground()); checkbox.setEnabled(isEnabled()); checkbox.setFont(getFont()); checkbox.setFocusPainted(false); checkbox.setBorderPainted(true); checkbox.setBorder(isSelected ? UIManager.getBorder( "List.focusCellHighlightBorder") : noFocusBorder); return checkbox; } } } 

Aquí, intercepto clics del mouse del cuadro de lista y simulo un clic en la casilla correspondiente. El resultado es un componente “CheckBoxList” que es tanto más simple como más pequeño que un componente equivalente utilizando la interfaz de CellEditor. Para usar la clase, basta con crear una instancia y luego pasarle una matriz de objetos JCheckBox (o subclases de objetos JCheckBox) llamando a setListData. Tenga en cuenta que las casillas de verificación de este componente no responderán a las pulsaciones de tecla (es decir, la barra espaciadora), pero siempre podría agregar su propia escucha de clave si fuera necesario.

Fuente: DevX.com