Как выбрать столбец JTable при выборе заголовка в Java

Я нашел код для выбора столбца по щелчку заголовка JTable, применив слушатель мыши к заголовку. Но, к сожалению, при щелчке ячейки таблицы выбирается целый столбец JTable, и стратегия выбора не меняется на прежнюю. Вместо этого он выделяет целый столбец при выделении ячейки.

Код:-

import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;

public class HeaderLocation {  
    private JTable getTable() {  
        int rows = 32, cols = 4;  
        String[] colIds = { "column 1", "column 2", "column 3", "column 4" };  
        Object[][] data = new Object[rows][cols];  
        for(int row = 0; row < rows; row++) {  
            for(int col = 0; col < cols; col++) {  
                data[row][col] = "item " + (row*cols+col+1);  
            }  
        }  
        DefaultTableModel model = new DefaultTableModel(data, colIds);  
        final JTable table = new JTable(model);  
        final JTableHeader header = table.getTableHeader();  
        table.setCellEditor(new CustomCellEditor());
        header.setReorderingAllowed(false);  
        header.addMouseListener(new MouseAdapter() {  
            public void mouseClicked(MouseEvent e) {  
                int col = header.columnAtPoint(e.getPoint());  
                System.out.printf("click cursor = %d%n",  
                                   header.getCursor().getType());  
                if(header.getCursor().getType() == Cursor.E_RESIZE_CURSOR)  
                    e.consume();  
                else {  
                    //System.out.printf("sorting column %d%n", col); 
                    table.setColumnSelectionAllowed(true);
                    table.setRowSelectionAllowed(false);
                    table.clearSelection();
                    table.setColumnSelectionInterval(col,col);
                    //tableModel[selectedTab].sortArrayList(col);  
                }  
            }  
        });  


        return table;  
    }  

    private JMenuBar getMenuBar() {  
        final JMenu view = new JMenu("view");  
        ActionListener l = new ActionListener() {  
            public void actionPerformed(ActionEvent e) {  
                JMenuItem item = (JMenuItem)e.getSource();  
                String className = item.getActionCommand();  
                changePLAF(className, view.getTopLevelAncestor());  
            }  
        };  
        UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();  
        for(int j = 0; j < info.length; j++) {  
            JMenuItem item = new JMenuItem(info[j].getName());  
            item.setActionCommand(info[j].getClassName());  
            item.addActionListener(l);  
            view.add(item);  
        }  
        JMenuBar menuBar = new JMenuBar();  
        menuBar.add(view);  
        return menuBar;  
    }  

    private void changePLAF(String className, Component c) {  
        try {  
            UIManager.setLookAndFeel(className);  
        } catch(ClassNotFoundException cnfe) {  
            System.err.println("class not found: " + cnfe.getMessage());  
        } catch(InstantiationException ie) {  
            System.err.println("instantiation: " + ie.getMessage());  
        } catch(IllegalAccessException iae) {  
            System.err.println("illegal access: " + iae.getMessage());  
        } catch(UnsupportedLookAndFeelException ulafe) {  
            System.err.println("unsupported laf: " + ulafe.getMessage());  
        }  
        SwingUtilities.updateComponentTreeUI(c);  
    }  

    public static void main(String[] args) {  
        HeaderLocation test = new HeaderLocation();  
        JFrame f = new JFrame();  
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        f.setJMenuBar(test.getMenuBar());  
        f.getContentPane().add(new JScrollPane(test.getTable()));  
        f.pack();  
        f.setLocation(200,200);  
        f.setVisible(true);  
    }  
}

CustomCellEditor.java

import java.awt.Component;

import javax.swing.DefaultCellEditor;
import javax.swing.JTable;
import javax.swing.JTextField;

public class CustomCellEditor extends DefaultCellEditor {

    public CustomCellEditor() {
        super(new JTextField());
        // TODO Auto-generated constructor stub
    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        table.clearSelection();
        table.setColumnSelectionAllowed(false);
        table.setRowSelectionAllowed(true);
        return super.getTableCellEditorComponent(table, value, isSelected, row, column);
        }

}  

Из приведенного выше кода: -

1.) При щелчке заголовок столбец выбран правильно. 2.) Но при нажатии на ячейку целого столбца выделяется не только одна ячейка, как ожидалось. Я пытался инвертировать выделение столбца, но он не работает, как ожидалось.

Любая помощь, связанная с этим, будет принята с благодарностью.

Спасибо

5 ответов

Вам нужно будет повернуть строки кода, объявленные внутри header.addMouseListener(new MouseAdapter() { назад

от

table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(false);

в

table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(true);

в 1-м mouse events вне JTableHeader

Добавьте адаптер мыши к вашему JTable в основной функции:

tableSet.getTableHeader().addMouseListener(getTableHeaderMouseAdapter(tableSet));

Адаптер мыши может быть:

protected static MouseAdapter getTableHeaderMouseAdapter(final JTable tableSet) {return new MouseAdapter(){
        public void mouseClicked(MouseEvent e) {
            int c = tableSet.columnAtPoint(e.getPoint());
            tableSet.setColumnSelectionInterval(c, c);
            if(tableSet.getRowCount() > 0){
                tableSet.setRowSelectionInterval(0, tableSet.getRowCount()-1);
            }
        }
    };
}

Ваш выбор переключения между столбцами и строками работает. Ваша проблема в том, что вы не устанавливаете свой редактор на столбцы таблицы, потому что setCellEditor() метод JTable делай другое, читай об этом.

Для добавления вашего редактора в столбцы необходимо заменить table.setCellEditor(new CustomCellEditor()); с:

    Enumeration<TableColumn> columns = table.getColumnModel().getColumns();
    while(columns.hasMoreElements()){
        columns.nextElement().setCellEditor(new CustomCellEditor());
    }

РЕДАКТИРОВАТЬ:

Теперь selectionMode переключается, когда вы выбираете заголовок или начинаете редактировать ячейку таблицы. Вы можете добавить mouseListenr в свою таблицу или изменить количество кликов, чтобы начать редактирование ячейки, для переключения каждый раз:

  table.addMouseListener(new MouseAdapter() {
          public void mouseClicked(MouseEvent e) {  
              table.setColumnSelectionAllowed(false);
              table.setRowSelectionAllowed(true);
          }  
    });

setClickCountToStart()

Используйте это простое решение. Я думаю, это то, что вы ищете.

table.getTableHeader().addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
        int clickedIndex = table.convertColumnIndexToModel(table.columnAtPoint(e.getPoint()));
        table.setColumnSelectionInterval(clickedIndex, clickedIndex); //selects which column will have all its rows selected
        table.setRowSelectionInterval(0, table.getRowCount() - 1); //once column has been selected, select all rows from 0 to the end of that column
    }
});

Я создал метод setColumnSelect, имеющий параметр - JTable.
Этот метод добавляет addMouseListener к JTable и JTableHeader.
Если щелкнуть заголовок первого столбца, будут выбраны все ячейки таблицы.
Если щелкнуть любой другой заголовок столбца, будет выбран весь столбец.
Если щелкнуть любую ячейку, то будет выбрана только эта ячейка.
Если щелкнуть / дважды щелкнуть любую ячейку первого столбца, то будет выбрана только эта строка.
После выбора всего столбца и перетаскивания мышью над ячейками других столбцов эти столбцы будут полностью выделены.
После выбора одной строки и перетаскивания мышью по строкам, все остальные строки будут выделены полностью

public void setColumnSelect(JTable table) {
    final JTable finalTable = table;
    final JTableHeader columnHeader = finalTable.getTableHeader();

    //For Row Selection

    finalTable.addMouseListener(new MouseAdapter() {

        public void mouseClicked(MouseEvent mouseEvent) {
            finalTable.setColumnSelectionAllowed(true);
            finalTable.setRowSelectionAllowed(true);

            if (finalTable.isCellSelected(finalTable.getSelectedRow(), 0)) {
                finalTable.setColumnSelectionAllowed(false);
                finalTable.setRowSelectionAllowed(true);                    
            }

        }
    });

    //For Column Selection

    columnHeader.addMouseListener(new MouseAdapter() {

        public void mouseClicked(MouseEvent mouseEvent) {
            columnPoint =  columnHeader.columnAtPoint(mouseEvent.getPoint());

            columnCursorType = columnHeader.getCursor().getType();

            if (columnCursorType == Cursor.E_RESIZE_CURSOR)
                mouseEvent.consume();
            else {

                if (columnPoint == 0) //the very first column header
                    finalTable.selectAll(); //will select all table cells
                else {
                    finalTable.setColumnSelectionAllowed(true);
                    finalTable.setRowSelectionAllowed(false);
                    finalTable.clearSelection();
                    finalTable.setColumnSelectionInterval(columnPoint, columnPoint);
                }

            }
        }
    });

}
Другие вопросы по тегам