Domanda

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 del testo e una casella di controllo ciascuno?

È stato utile?

Soluzione

Crea una personalizzazione ListCellRenderer e assegnarlo al JList.

Questa usanza ListCellRenderer deve restituire a JCheckbox nell'attuazione di getListCellRendererComponent(...) metodo.

Ma questo JCheckbox non sarà modificabile, è un semplice disegno sullo schermo e sta a te scegliere quando farlo JCheckbox deve essere "selezionato" o meno,

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

Pubblicherò il codice di esempio più tardi se ne avrai bisogno

ListCellRenderer

Altri suggerimenti

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

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 il materiale Jidesoft, giocando con il file CheckBoxList Ho riscontrato alcuni problemi (comportamenti che non hanno funzionato).Modificherò questa risposta se riscontro problemi con il file CheckBoxList Mi sono collegato a.

Probabilmente cercherò di usare a JTable piuttosto che a JList e poiché il rendering predefinito di una casella di controllo è piuttosto brutto, probabilmente cercherei di inserirne uno personalizzato Modello di tabella, CellRenderer E Editor di celle per rappresentare un valore booleano.Naturalmente, immagino che questo sia già stato fatto un miliardo di volte.Il sole ha buoni esempi.

Basta implementare a 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 impostare il renderer

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

questo risulterà

CheckboxListCellRenderer example

Dettagli a Renderer di componenti swing personalizzati.

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

Soluzione migliore per Java 7 e versioni successive

Mi sono imbattuto in questa domanda e mi sono reso conto che alcune delle risposte sono piuttosto vecchie e obsolete.Al giorno d'oggi, JList è generico e quindi esistono soluzioni migliori.

La mia soluzione del generico JCheckBoxList:

import java.awt.Component;

import javax.swing.*;
import javax.swing.border.*;

import java.awt.event.*;

@SuppressWarnings("serial")
public class JCheckBoxList extends JList<JCheckBox> {
  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<JCheckBox> model){
    this();
    setModel(model);
  }

  protected class CellRenderer implements ListCellRenderer<JCheckBox> {
    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 dinamicamente gli elenchi JCheckBox è necessario creare il proprio ListModel o aggiungere il DefaultListModel.

DefaultListModel<JCheckBox> model = new DefaultListModel<JCheckBox>();
JCheckBoxList checkBoxList = new JCheckBoxList(model);

IL Modello elenco predefinito sono generici e quindi è possibile utilizzare i metodi specificati dall'API JAVA 7 Qui come questo:

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

Ci sono buone probabilità 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 a meno che tu non voglia davvero farlo da solo.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 desiderato, 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 le caselle di controllo a JPanel e imposta JPanel come origine dati di JScrollPane.E per ottenere i CheckBox selezionati, basta chiamare getComponents() del JPanel per ottenere i CheckBox.

Ecco solo una piccola aggiunta a JCheckBoxList di Rawa.Ciò aggiungerà la possibilità di selezionare utilizzando la barra spaziatrice.Se vengono selezionati più elementi, tutti verranno impostati 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 in Swing, ovvero i componenti costituiti da altri componenti, come JTable, JTree o JComboBox, possono essere altamente personalizzati.Ad esempio, un componente JTable normalmente visualizza una griglia di componenti JLabel, ma può anche visualizzare JButton, JTextField o anche altri JTable.Tuttavia, far sì che questi componenti aggregati visualizzino oggetti non predefiniti sia la parte facile.Farli rispondere correttamente agli eventi della tastiera e del mouse è un compito molto più difficile, a causa della separazione dei componenti di Swing in "rendering" e "editori". Questa separazione è stata (secondo me) una scelta di progettazione scarsa e serve solo a complicare le questioni quando si cerca di estendere i componenti swing.

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

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 è allo stesso tempo più semplice e più piccolo di un componente equivalente che utilizza l'interfaccia CellEditor.Per utilizzare la classe, è sufficiente istanziarla, quindi passarle un array di oggetti JCheckBox (o sottoclassi di oggetti JCheckBox) chiamando setListData.Tieni presente che le caselle di controllo in questo componente non risponderanno alla pressione dei tasti (ad es.la barra spaziatrice), ma puoi sempre aggiungere il tuo ascoltatore chiave, se necessario.

Fonte: DevX.com

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top