Question

Quelle serait la meilleure façon d'avoir une liste d'éléments avec chacun une case à cocher dans Java Swing ?

C'est à dire.une JList avec des éléments contenant chacun du texte et une case à cocher ?

Était-ce utile?

La solution

Créer une coutume ListCellRenderer et l'attribuer au JList.

Cette coutume ListCellRenderer doit retourner un JCheckbox dans la mise en œuvre de getListCellRendererComponent(...) méthode.

Mais ça JCheckbox ne sera pas modifiable, c'est une simple peinture à l'écran, c'est à vous de choisir quand cela JCheckbox doit être 'coché' ou non,

Par exemple, montrez-le coché lorsque la ligne est sélectionnée (paramètre isSelected), mais de cette façon, le statut de vérification ne sera pas conservé si la sélection change.Il est préférable de le montrer vérifié en consultant les données ci-dessous. ListModel, mais c'est ensuite à vous d'implémenter la méthode qui modifie le statut de contrôle des données, et de notifier le changement au JList à repeindre.

Je publierai un exemple de code plus tard si vous en avez besoin

ListCellRenderer

Autres conseils

Une merveilleuse réponse est la suivante CheckBoxList.Il implémente la réponse de Telcontar (bien que 3 ans avant :)...Je l'utilise en Java 1.6 sans problème.J'ai également ajouté un addCheckbox méthode comme celle-ci (pourrait sûrement être plus courte, je n'ai pas utilisé Java depuis un moment):

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

J'ai essayé la démo des trucs Jidesoft, en jouant avec le CheckBoxList J'ai rencontré quelques problèmes (comportements qui ne fonctionnaient pas).Je modifierai cette réponse si je trouve des problèmes avec le CheckBoxList J'ai mis un lien vers.

Je chercherais probablement à utiliser un JTable Plutôt qu'un JListe et comme le rendu par défaut d'une case à cocher est plutôt moche, je chercherais probablement à ajouter un fichier personnalisé Modèle de table, Rendu de cellules et Éditeur de cellules pour représenter une valeur booléenne.Bien sûr, j’imagine que cela a déjà été fait des milliards de fois.Le soleil a bons exemples.

Il suffit de mettre en œuvre 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;
    }
}

et définissez le moteur de rendu

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

cela entraînera

CheckboxListCellRenderer example

Détails sur Rendus de composants swing personnalisés.

PS :Si vous voulez des éléments radio, remplacez-les simplement extends JCheckbox avec extends JRadioButton.

Meilleure solution pour Java 7 et versions ultérieures

Je suis tombé sur cette question et j'ai réalisé que certaines réponses étaient assez anciennes et obsolètes.De nos jours, JList est générique et il existe donc de meilleures solutions.

Ma solution du JCheckBoxList générique :

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

Pour ajouter dynamiquement des listes JCheckBox, vous devez créer votre propre ListModel ou ajouter le DefaultListModel.

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

Le Modèle de liste par défaut sont génériques et vous pouvez donc utiliser les méthodes spécifiées par l'API JAVA 7 ici comme ça:

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

Avec Java, il y a de fortes chances que quelqu'un ait déjà implémenté le widget ou l'utilitaire dont vous avez besoin.Une partie des avantages d’une grande communauté OSS.Pas besoin de réinventer la roue, sauf si vous voulez vraiment le faire vous-même.Dans ce cas, ce serait un bon exercice d'apprentissage dans CellRenderers et Editors.

Mon projet a eu un grand succès avec JIDE.Le composant souhaité, une liste de cases à cocher, se trouve dans la couche commune JIDE (qui est OSS et hébergée sur java.net).Les éléments commerciaux sont également bons, mais vous n'en avez pas besoin.

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

Je vous recommande d'utiliser un JPanel avec un GridLayout de 1 colonne.Ajoutez les cases à cocher au JPanel et définissez le JPanel comme source de données d'un JScrollPane.Et pour obtenir les CheckBoxes sélectionnées, appelez simplement getComponents() du JPanel pour obtenir les CheckBoxes.

Voici juste un petit ajout à la JCheckBoxList de Rawa.Cela ajoutera la possibilité de sélectionner à l'aide de la barre d'espace.Si plusieurs éléments sont sélectionnés, tous seront définis sur la valeur inversée du premier élément.

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

Tous les composants agrégés de Swing (c'est-à-dire les composants constitués d'autres composants, tels que JTable, JTree ou JComboBox) peuvent être hautement personnalisés.Par exemple, un composant JTable affiche normalement une grille de composants JLabel, mais il peut également afficher des JButtons, des JTextFields ou même d'autres JTables.Cependant, faire en sorte que ces composants agrégés affichent des objets autres que ceux par défaut est la partie la plus facile.Les faire répondre correctement aux événements du clavier et de la souris est une tâche beaucoup plus difficile, en raison de la séparation des composants par Swing en "rendements" et "éditeurs". Cette séparation était (à mon avis) un mauvais choix de conception et ne sert à compliquer les choses que lorsque vous essayez d'étendre les composants de swing.

Pour voir ce que je veux dire, essayez d'améliorer le composant JList de Swing afin qu'il affiche des cases à cocher au lieu d'étiquettes.Selon la philosophie Swing, cette tâche nécessite la mise en œuvre de deux interfaces :ListCellRenderer (pour dessiner les cases à cocher) et CellEditor (pour gérer les événements de clavier et de souris sur les cases à cocher).L'implémentation de l'interface ListCellRenderer est assez simple, mais l'interface CellEditor peut être plutôt maladroite et difficile à comprendre.Dans ce cas particulier, je suggérerais d'oublier complètement CellEditor et de gérer directement les événements d'entrée, comme indiqué dans le code suivant.

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

Ici, j'intercepte les clics de souris depuis la listbox et simule un clic sur la case à cocher appropriée.Le résultat est un composant "CheckBoxList" à la fois plus simple et plus petit qu'un composant équivalent utilisant l'interface CellEditor.Pour utiliser la classe, instanciez-la simplement, puis transmettez-lui un tableau d'objets JCheckBox (ou des sous-classes d'objets JCheckBox) en appelant setListData.Notez que les cases à cocher de ce composant ne répondront pas aux pressions sur les touches (c'est-à-direla barre d'espace), mais vous pouvez toujours ajouter votre propre écouteur de clé si nécessaire.

Source: DevX.com

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top