Come faccio a creare un elenco con le caselle di controllo in Java Swing?

Quale sarebbe il modo migliore per avere un elenco di elementi con una casella di controllo ciascuno in Java Swing?

Cioè una JList con elementi che hanno un testo e una casella di controllo ciascuno?

Creare un ListCellRenderer personalizzato e assegnarlo a JList .

Questo ListCellRenderer personalizzato deve restituire un JCheckbox nell’implementazione del getListCellRendererComponent(...) .

Ma questo JCheckbox non sarà modificabile, è una semplice vernice sullo schermo che devi scegliere quando questo JCheckbox deve essere ” JCheckbox ” o no,

Ad esempio, isSelected spuntato quando la riga è selezionata (parametro isSelected ), ma in questo modo lo stato di controllo non verrà mantenuto se la selezione cambia. È meglio mostrarlo controllato consultando i dati sotto il ListModel , ma poi spetta a te implementare il metodo che cambia lo stato di controllo dei dati e notificare la modifica a JList da ridipingere.

Inserirò il codice di esempio più tardi se ne hai bisogno

ListCellRenderer

Una risposta meravigliosa è questa CheckBoxList . Implementa la risposta di Telcontar (sebbene 3 anni prima:) … Lo sto usando in Java 1.6 senza problemi. Ho anche aggiunto un metodo addCheckbox come questo (sicuramente potrebbe essere più breve, non ho usato Java in un attimo):

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

Ho provato la demo per la roba di Jidesoft, giocando con la CheckBoxList ho riscontrato alcuni problemi (comportamenti che non funzionavano). Modificheremo questa risposta se trovo problemi con il CheckBoxList mi sono collegato.

Probabilmente cercherò di usare un JTable piuttosto che un JList e dato che il rendering predefinito di una casella di controllo è piuttosto brutto, probabilmente mi piacerebbe inserire un TableModel , CellRenderer e CellEditor personalizzati per rappresentare un valore booleano. Certo, immagino che questo sia già stato fatto un tempo di migliaia di migliaia. Sun ha dei buoni esempi .

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

e imposta il renderer

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

questo si tradurrà in

CheckboxListCellRenderer esempio

Dettagli sui renderizzatori di componenti di swing personalizzati .

PS: Se vuoi elementi radio basta sostituire extends JCheckbox con extends JRadioButton .

Soluzione migliore per Java 7 e versioni successive

Mi sono imbattuto in questa domanda e ho capito che alcune delle risposte sono piuttosto vecchie e obsolete. Oggigiorno, JList è generico e quindi ci sono soluzioni migliori.

La mia soluzione del JCheckBoxList generico:

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

Per aggiungere in modo dinamico gli elenchi JCheckBox è necessario creare il proprio ListModel o aggiungere il DefaultListModel.

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

DefaultListModel sono generici e quindi puoi utilizzare i metodi specificati dall’API di JAVA 7 in questo modo:

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

Le probabilità sono buone con Java che qualcuno abbia già implementato il widget o l’utilità di cui hai bisogno. Parte dei vantaggi di una grande comunità OSS. Non c’è bisogno di reinventare la ruota se non si vuole davvero farlo da soli. In questo caso sarebbe un buon esercizio di apprendimento in CellRenderers ed Editors.

Il mio progetto ha avuto un grande successo con JIDE. Il componente che desideri, un elenco di caselle di controllo, si trova nel livello comune JIDE (che è OSS e è ospitato su java.net). Anche il materiale commerciale è buono, ma non ne hai bisogno.

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

Ti consiglio di utilizzare un JPanel con un GridLayout di 1 colonna. Aggiungi i checkbox a JPanel e imposta JPanel come origine dati di un JScrollPane. E per ottenere i CheckBox selezionati, chiama i getComponents () di JPanel per ottenere i CheckBox.

Ecco solo una piccola aggiunta alla JCheckBoxList di Rawa. Questo aggiungerà la possibilità di selezionare usando la barra spaziatrice. Se sono selezionati più elementi, tutto verrà impostato sul valore invertito del primo 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(); } } } }); 

Tutti i componenti aggregati di Swing, ovvero componenti costituiti da altri componenti, come JTable, JTree o JComboBox, possono essere altamente personalizzati. Ad esempio, un componente JTable visualizza normalmente una griglia di componenti JLabel, ma può anche visualizzare JButtons, JTextFields o anche altre JTables. Ottenere questi componenti aggregati per visualizzare oggetti non predefiniti è comunque la parte facile. Rendere loro rispondere correttamente agli eventi di tastiera e mouse è un compito molto più difficile, a causa della separazione dei componenti di Swing in “renderer” e “editor”. Questa separazione è stata (secondo me) una scelta di progettazione scadente e serve solo a complicare le cose quando si cerca di estendere i componenti di Swing.

Per capire cosa intendo, prova a migliorare il componente JList di Swing in modo che visualizzi le caselle di controllo anziché le etichette. Secondo la filosofia di Swing, questa attività richiede l’implementazione di due interfacce: ListCellRenderer (per disegnare le caselle di controllo) e CellEditor (per gestire gli eventi di tastiera e mouse sulle caselle di controllo). L’implementazione dell’interfaccia ListCellRenderer è abbastanza semplice, ma l’interfaccia di CellEditor può essere piuttosto goffa e difficile da capire. In questo caso specifico, suggerirei di dimenticare completamente CellEditor e di gestire direttamente gli eventi di input, come mostrato nel seguente codice.

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

Qui, intercetto i clic del mouse dalla casella di riepilogo e simulo un clic sulla casella di controllo appropriata. Il risultato è un componente “CheckBoxList” che è sia più semplice che più piccolo di un componente equivalente tramite l’interfaccia CellEditor. Per usare la class, basta istanziarla, quindi passarla una serie di oggetti JCheckBox (o sottoclassi di oggetti JCheckBox) chiamando setListData. Si noti che le caselle di controllo in questo componente non risponderanno ai tasti premuti (es. La barra spaziatrice), ma è sempre ansible aggiungere il proprio ascoltatore di chiavi, se necessario.

Fonte: DevX.com