Pergunta

Qual seria a melhor maneira de ter uma lista de itens com uma caixa de seleção em Java Swing?

Ou sejauma JList com itens que possuem algum texto e uma caixa de seleção cada?

Foi útil?

Solução

Crie um personalizado ListCellRenderer e atribuí-lo ao JList.

Este costume ListCellRenderer deve devolver um JCheckbox na implementação de getListCellRendererComponent(...) método.

Mas isso JCheckbox não será editável, é uma simples pintura na tela fica a seu critério escolher quando isso JCheckbox deve estar 'marcado' ou não,

Por exemplo, mostre-o marcado quando a linha for selecionada (parâmetro isSelected), mas desta forma o status da verificação não será mantido caso a seleção seja alterada.É melhor mostrar verificado consultando os dados abaixo do ListModel, mas cabe a você implementar o método que altera o status de verificação dos dados e notificar a alteração ao JList para ser repintado.

Postarei um código de exemplo mais tarde, se você precisar

ListCellRenderer

Outras dicas

Uma resposta maravilhosa é esta CheckBoxList.Implementa a resposta da Telcontar (embora 3 anos antes :)...Estou usando em Java 1.6 sem problemas.Eu também adicionei um addCheckbox método como este (certamente poderia ser mais curto, não uso Java há algum tempo):

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

Eu experimentei a demo do Jidesoft, brincando com o CheckBoxList Encontrei alguns problemas (comportamentos que não funcionaram).Modificarei esta resposta se encontrar problemas com o CheckBoxList Eu vinculei a.

Eu provavelmente estaria procurando usar um JTable ao invés de um JList e como a renderização padrão de uma caixa de seleção é bastante feia, provavelmente eu gostaria de inserir uma caixa de seleção personalizada Modelo de tabela, CellRenderer e Editor de Célula para representar um valor booleano.Claro, imagino que isso já tenha sido feito um bilhão de vezes.Sol tem bons exemplos.

Basta implementar um 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 defina o renderizador

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

isso resultará em

CheckboxListCellRenderer example

Detalhes em Renderizadores de componentes swing personalizados.

PS:Se você quiser elementos de rádio, basta substituir extends JCheckbox com extends JRadioButton.

Melhor solução para Java 7 e mais recente

Me deparei com essa pergunta e percebi que algumas das respostas são bastante antigas e desatualizadas.Hoje em dia, JList é genérico e por isso existem soluções melhores.

Minha solução do JCheckBoxList genérico:

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

Para adicionar listas JCheckBox dinamicamente, você precisa criar seu próprio ListModel ou adicionar o DefaultListModel.

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

O Modelo de lista padrão são genéricos e, portanto, você pode usar métodos especificados pela API JAVA 7 aqui assim:

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

As chances são boas com Java de que alguém já tenha implementado o widget ou utilitário que você precisa.Parte dos benefícios de uma grande comunidade OSS.Não há necessidade de reinventar a roda, a menos que você realmente queira fazer isso sozinho.Neste caso seria um bom exercício de aprendizagem em CellRenderers e Editores.

Meu projeto teve grande sucesso com JIDE.O componente que você deseja, uma lista de caixas de seleção, está na camada comum JIDE (que é OSS e está hospedada em java.net).O material comercial também é bom, mas você não precisa dele.

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

Recomendo que você use um JPanel com GridLayout de 1 coluna.Adicione as checkBoxes ao JPanel e defina o JPanel como a fonte de dados de um JScrollPane.E para obter os CheckBoxes selecionados, basta chamar getComponents() do JPanel para obter os CheckBoxes.

Aqui está apenas uma pequena adição ao JCheckBoxList de Rawa.Isso adicionará a capacidade de selecionar usando a barra de espaço.Se vários itens forem selecionados, todos serão definidos com o valor invertido do primeiro 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();
                }
            }
        }
        });

Todos os componentes agregados no Swing – ou seja, componentes formados por outros componentes, como JTable, JTree ou JComboBox – podem ser altamente customizados.Por exemplo, um componente JTable normalmente exibe uma grade de componentes JLabel, mas também pode exibir JButtons, JTextFields ou até mesmo outras JTables.No entanto, fazer com que esses componentes agregados exibam objetos não padrão é a parte fácil.Fazê -los responder corretamente aos eventos de teclado e mouse é uma tarefa muito mais difícil, devido à separação de componentes de Swing em "Renderers" e "Editores". Essa separação foi (na minha opinião) uma má escolha de design e serve apenas para complicar as questões ao tentar estender os componentes de balanço.

Para entender o que quero dizer, tente aprimorar o componente JList do Swing para que ele exiba caixas de seleção em vez de rótulos.De acordo com a filosofia Swing, esta tarefa requer a implementação de duas interfaces:ListCellRenderer (para desenhar as caixas de seleção) e CellEditor (para manipular eventos de teclado e mouse nas caixas de seleção).Implementar a interface ListCellRenderer é bastante fácil, mas a interface CellEditor pode ser um tanto desajeitada e difícil de entender.Nesse caso específico, sugiro esquecer totalmente o CellEditor e lidar diretamente com os eventos de entrada, conforme mostrado no código a seguir.

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

Aqui, intercepto cliques do mouse na caixa de listagem e simulo um clique na caixa de seleção apropriada.O resultado é um componente "CheckBoxList" que é mais simples e menor que um componente equivalente usando a interface CellEditor.Para usar a classe, basta instanciá-la e, em seguida, passar para ela um array de objetos JCheckBox (ou subclasses de objetos JCheckBox) chamando setListData.Observe que as caixas de seleção neste componente não responderão ao pressionamento de teclas (ou seja,a barra de espaço), mas você sempre pode adicionar seu próprio ouvinte principal, se necessário.

Fonte: DevX.com

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top