Comment faire une liste avec des cases à cocher dans Java Swing?
quelle serait la meilleure façon d'avoir une liste d'éléments avec une case à cocher chacun dans Java Swing?
<!-C'est-à-dire: une liste avec des éléments qui ont du texte et une case à cocher chacun?9 réponses
Créer un custom ListCellRenderer
et assigner à l' JList
.
cette coutume ListCellRenderer
doit retourner un JCheckbox
dans le implementantion de getListCellRendererComponent(...)
méthode.
Mais ce JCheckbox
ne sera pas modifiable, est une simple peinture à l'écran est à vous de choisir lors de cette JCheckbox
doit être cochée ou pas,
Par exemple, montrent une légère lorsque la ligne est sélectionnée (paramètre isSelected
), mais de cette façon le statut de contrôle ne sera pas maintenu si la sélection changement. Il est préférable de montrer vérifié en consultant les données en dessous de la ListModel
, mais c'est alors à vous de mettre en œuvre la méthode qui modifie l'état de vérification des données, et de notifier le changement à la JList
pour être repeint.
je Vais poster un exemple de code plus tard, si vous en avez besoin
Une merveilleuse réponse est CheckBoxList
. Il implémente la réponse de Telcontar (bien que 3 ans auparavant :)... Je l'utilise en Java 1.6 sans problème. J'ai aussi ajouté un addCheckbox
méthode comme celle-ci (sûrement 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 pour le truc de Jidesoft, en jouant avec le CheckBoxList
j'ai rencontré quelques problèmes (comportements qui n'ont pas fonctionné). Je modifierai cette réponse si je trouve des problèmes avec le CheckBoxList
j'ai fait un lien de.
je cherche probablement à utiliser un JTable plutôt que JList et puisque le rendu par défaut d'une case à cocher est plutôt laid, je serais probablement à la recherche de laisser tomber un custom TableModel, CellRenderer et CellEditor pour représenter une valeur booléenne. Bien sûr, j'imagine que cela a déjà été fait des millions de fois. Soleil a bons exemples.
il suffit d'implémenter 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());
résultat
Détails composante sur mesure renderers.
PS: Si vous voulez des éléments radio, remplacez extends JCheckbox
extends JRadioButton
.
meilleure solution pour Java 7 et les versions plus récentes
je suis tombé sur cette question et a réalisé que certaines réponses sont assez vieux et dépassé. Aujourd'hui, JList est générique et il y a donc de meilleures solutions.
Ma solution du générique 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;
}
}
}
pour ajouter dynamiquement des listes JCheckBox, vous devez créer votre propre ListModel ou ajouter le Defaullistmodel.
DefaultListModel<JCheckBox> model = new DefaultListModel<JCheckBox>();
JCheckBoxList checkBoxList = new JCheckBoxList(model);
Defaullistmodel sont génériques et ainsi, vous pouvez utiliser les méthodes spécifiées par L'API JAVA 7 ici comme ceci:
model.addElement(new JCheckBox("Checkbox1"));
model.addElement(new JCheckBox("Checkbox2"));
model.addElement(new JCheckBox("Checkbox3"));
les chances sont bonnes w / Java que quelqu'un a déjà mis en œuvre le widget ou l'utilitaire dont vous avez besoin. Une partie des avantages d'une grande communauté de logiciels libres. Pas besoin de réinventer la roue si vous voulez vraiment le faire vous-même. Dans ce cas, ce serait un bon exercice d'apprentissage chez les violoncellistes et les rédacteurs en chef.
mon projet a eu beaucoup de succès avec JIDE. Le composant que vous voulez, une liste de cases à cocher, est dans la couche commune JIDE (qui est OSS et hébergé sur java.net). La pub est bonne. trop, 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 la source de données d'un JScrollPane. Et pour obtenir les cases à cocher sélectionnées, il suffit d'appeler les getComponents() du JPanel pour obtenir les cases à cocher.
Voici juste un petit ajout à la JCheckBoxList de Rawa. Cela ajoutera la capacité de sélectionner en utilisant la barre d'espace. Si plusieurs items sont sélectionnés, tous seront définis à la valeur inversée du premier item.
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();
}
}
}
});
toutes les composantes globales dans Swing--c'est-à-dire, les composantes composées d'autres composantes, telles que JTable, JTree, ou JComboBox--peuvent être fortement personnalisées. Par exemple, un composant JTable affiche normalement une grille de composants JLabel, mais il peut aussi afficher des JButtons, JTextFields, ou même d'autres JTables. Obtenir ces composants agrégés pour afficher des objets non-par défaut est la partie facile, cependant. Leur faire répondre correctement aux évènements clavier et souris est une tâche beaucoup plus difficile, en raison de Swing la séparation des composants dans des "convertisseurs" et "des éditeurs."Cette séparation était (à mon avis) Un mauvais choix de conception et ne sert qu'à compliquer les choses lorsque l'on essaie d'étendre les composants Swing.
pour voir ce que je veux dire, essayez d'améliorer le composant JList de Swing pour qu'il affiche des cases à cocher au lieu des étiquettes. Selon la philosophie Swing, cette tâche nécessite l'implémentation de deux interfaces: ListCellRenderer (pour dessiner les cases à cocher) et CellEditor (pour gérer les évènements clavier et souris). sur les cases à cocher). Mettre en œuvre L'interface ListCellRenderer est assez facile, mais L'interface CellEditor peut être plutôt maladroit et difficile à comprendre. Dans ce cas précis, je suggérerais d'oublier entièrement CellEditor et de gérer les événements d'entrée directement, comme le montre 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 de la liste et simule un clic sur la case à cocher appropriée. Le résultat est un composant "CheckBoxList" à la fois plus simple et plus petit que un composant équivalent utilisant L'interface CellEditor. Pour utiliser la classe, instanciez-la simplement, puis passez-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 touches (c'est-à-dire la barre d'espacement), mais vous pouvez toujours ajouter votre propre écouteur de touches si nécessaire.
Source:DevX.com