6

列の1つとしてチェックボックスを持つJTableがあります。また、ヘッダーにすべてをチェック/チェック解除するためのチェックボックスがあります。私の知る限り、JTableのデフォルトの動作は、新しい行を選択すると、以前に選択されていたすべての行を選択解除することです。しかし、チェックボックスを使用してCTRLクリックのような動作を実現できますか。以前に選択した行を保持します。私が直面している主な問題は、チェックボックスを使用して JTable 行を複数選択できるようにすることです。

期待される出力

最初の行がチェックされている場合は最初の行が選択され、3 番目の行がチェックされている場合は最初の行と一緒に 3 番目の行が選択されます (既にチェックされて選択されています)。

実際の出力

最初の行がチェックされて選択されている場合、3 番目の行を選択すると、以前に選択されていたすべての行が選択解除され、3 番目の行のみが選択されます。

Add Another Oneボタンと同じように達成したいシナリオをシミュレートするサンプルコードがありますが、チェックボックスを選択します。

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableColumn;
import javax.swing.event.CellEditorListener;

public class JTableRowSelectProgramatically extends JPanel {

final JTable table = new JTable(new MyTableModel());

public JTableRowSelectProgramatically() {
    initializePanel();
}

private void initializePanel() {
    setLayout(new BorderLayout());
    setPreferredSize(new Dimension(475, 150));


    table.setFillsViewportHeight(true);
    JScrollPane pane = new JScrollPane(table);

    JLabel label2 = new JLabel("Row: ");
    final JTextField field2 = new JTextField(3);
    JButton add = new JButton("Select");

    table.setRowSelectionAllowed(true);
    table.setColumnSelectionAllowed(false);
    table.getSelectionModel().addListSelectionListener(new ListSelectionListenerImpl());
    TableColumn tc = table.getColumnModel().getColumn(3);
    tc.setCellEditor(table.getDefaultEditor(Boolean.class));
    tc.setCellRenderer(table.getDefaultRenderer(Boolean.class));
    ((JComponent) table.getDefaultRenderer(Boolean.class)).setOpaque(true);
    tc.getCellEditor().addCellEditorListener(new CellEditorListenerImpl());

    add.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent event) {
            int index2 = 0;
            try {
                index2 = Integer.valueOf(field2.getText());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
            table.addRowSelectionInterval(index2, index2);
            field2.setText(String.valueOf(index2));
        }
    });

    JPanel command = new JPanel(new FlowLayout());
    command.add(label2);
    command.add(field2);
    command.add(add);

    add(pane, BorderLayout.CENTER);
    add(command, BorderLayout.SOUTH);
}

public static void showFrame() {
    JPanel panel = new JTableRowSelectProgramatically();
    panel.setOpaque(true);

    JFrame frame = new JFrame("JTable Row Selection");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setContentPane(panel);
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        public void run() {
            JTableRowSelectProgramatically.showFrame();
        }
    });
}

public class MyTableModel extends AbstractTableModel {

    private String[] columns = {"ID", "NAME", "AGE", "A STUDENT?"};
    private Object[][] data = {
        {1, "Alice", 20, new Boolean(false)},
        {2, "Bob", 10, new Boolean(false)},
        {3, "Carol", 15, new Boolean(false)},
        {4, "Mallory", 25, new Boolean(false)}
    };

    public int getRowCount() {
        return data.length;
    }

    public int getColumnCount() {
        return columns.length;
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        return data[rowIndex][columnIndex];
    }

    @Override
    public String getColumnName(int column) {
        return columns[column];
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex == 3;
    }

    //
    // This method is used by the JTable to define the default
    // renderer or editor for each cell. For example if you have
    // a boolean data it will be rendered as a check box. A
    // number value is right aligned.
    //
    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return data[0][columnIndex].getClass();
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        if (columnIndex == 3) {
            data[rowIndex][columnIndex] = aValue;
            fireTableCellUpdated(rowIndex, columnIndex);
        }
    }
}

class ListSelectionListenerImpl implements ListSelectionListener {

    public void valueChanged(ListSelectionEvent lse) {
        ListSelectionModel lsm = (ListSelectionModel) lse.getSource();
        int row = table.getRowCount();
        if (lsm.isSelectionEmpty()) {
        } else {
//                If any column is clicked other than checkbox then do normal selection
//                i.e select the click row and deselects the previous selection
            if (table.getSelectedColumn() != 3) {
                for (int i = 0; i < row; i++) {
                    if (lsm.isSelectedIndex(i)) {
                        table.setValueAt(true, i, 3);
                    } else {
                        table.setValueAt(false, i, 3);
                    }
                }

            }
        }
    }
  }
public class CellEditorListenerImpl implements CellEditorListener{

    public void editingStopped(ChangeEvent e) {
        for(int i=0; i<table.getRowCount();i++){
            if((Boolean)table.getValueAt(i, 3)){
                table.addRowSelectionInterval(i, i);
            }
            else{
                table.removeRowSelectionInterval(i, i);
            }
        }
    }

    public void editingCanceled(ChangeEvent e) {
        System.out.println("do nothing");
    }

}
}
4

2 に答える 2

4

TableModelこれらのメソッドを実装するsetValueAt()と、チェックボックスの状態と選択モデルの同期を維持するために、必要に応じてボタン リスナーで使用してモデルを調整できます。ここに関連する例があります。

@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
    return columnIndex == 3;
}

@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    if (columnIndex == 3) {
        data[rowIndex][columnIndex] = aValue;
        fireTableCellUpdated(rowIndex, columnIndex);
    }
}

補遺: 具体的な例として、リスナーは次のようなclearメソッドを呼び出す可能性があります。TableModelclearChecks()

MyTableModel model = (MyTableModel) table.getModel();
model.clearChecks();
...
private void clearChecks() {
    for (int i = 0; i < data.length; i++) {
        data[i][3] = false;
    }
    fireTableRowsUpdated(0, data.length);
}
于 2012-05-21T04:57:17.553 に答える
0

大まかに言うと、キー リスナーを呼び出して、選択リスナー内で VK_CTRL にフラグが設定されているかどうかを確認します。これは、ロジック ブロックの問題またはリスナーの競合のように聞こえます。

それを除けば、JList ボックスでは複数選択が可能です。

于 2012-05-21T04:21:00.630 に答える