Сортировать JTable, кроме последней строки

java swing jtable tablerowsorter

2181 просмотра

5 ответа

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

Есть ли простой способ реализовать это с TableRowSorter?

Автор: Tom Tucker Источник Размещён: 12.11.2019 09:23

Ответы (5)


2 плюса

Решение

Следующее решение работало для меня ....

В вашей табличной модели обновите getRowCount()член, чтобы он возвращал на 1 строку меньше, чем требуется.

Затем измените индекс и количество строк, сообщаемых вашим сортировщиком, следующим образом ...

TableRowSorter<TableModel> sorter =
    new DefaultTableRowSorter<TableModel>(this.getModel()) 
{
    public int convertRowIndexToModel(int index)
    {
        int maxRow = super.getViewRowCount();
        if (index >= maxRow)
            return index;
        return super.convertRowIndexToModel(index);
    }

    public int convertRowIndexToView(int index) 
    {
        int maxRow = super.getModelRowCount();
        if (index > maxRow)
            return index;
        return super.convertRowIndexToView(index);
    }

    public int getViewRowCount() 
    {
        return super.getViewRowCount() + 1;
    }
};

myTable.setRowSorter(sorter);
Автор: Das Размещён: 13.06.2013 05:03

5 плюса

Лично я бы создал однорядную 2-ую таблицу с удаленным заголовком и поместил бы ее непосредственно под основной таблицей, чтобы создать иллюзию последней строки.

Помимо решения вашей проблемы с сортировкой, она также будет сохраняться, пока пользователь прокручивает эту основную таблицу, что, вероятно, хорошо, так как это строка «итогов».

Вы даже можете добавить ColumnModelListenerк основной таблице, TableColumnModelчтобы синхронизировать изменение размера столбца.

РЕДАКТИРОВАТЬ : Вот общая идея:

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class TestFrame implements Runnable
{
  JTable mainTable;
  JTable fixedTable;

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new TestFrame());
  }

  public void run()
  {
    mainTable = new JTable(8, 3);
    mainTable.getTableHeader().setReorderingAllowed(false);
    mainTable.setAutoCreateRowSorter(true);

    for (int r = 0; r < 8; r++)
    {
      for (int c = 0; c < 3; c++)
      {
        mainTable.setValueAt((int)(Math.random()*100), r, c);
      }
    }

    mainTable.getColumnModel().addColumnModelListener(
      new TableColumnModelListener()
      {
        public void columnAdded(TableColumnModelEvent e) {}
        public void columnRemoved(TableColumnModelEvent e) {}
        public void columnMoved(TableColumnModelEvent e) {}
        public void columnSelectionChanged(ListSelectionEvent e) {}

        public void columnMarginChanged(ChangeEvent e)
        {
          synchColumnSizes();
        }
      });

    setVisibleRowCount(mainTable, 5);

    JScrollPane scroll = new JScrollPane(mainTable);
    scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

    fixedTable = new JTable(1, 3);
    fixedTable.setValueAt("will not sort or", 0, 0);
    fixedTable.setValueAt("scroll but will",  0, 1);
    fixedTable.setValueAt("resize with main", 0, 2);

    JPanel p = new JPanel(new GridBagLayout());
    p.setBorder(BorderFactory.createTitledBorder("Fixed Last Row"));
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.WEST;
    p.add(scroll, gbc);
    gbc.gridy = 1;
    p.add(fixedTable, gbc);

    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().add(p, BorderLayout.CENTER);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }

  private void synchColumnSizes()
  {
    TableColumnModel tcmMain = mainTable.getColumnModel();
    TableColumnModel tcmFixed = fixedTable.getColumnModel();

    for (int i = 0; i < tcmMain.getColumnCount(); i++)
    {
      int width = tcmMain.getColumn(i).getWidth();
      tcmFixed.getColumn(i).setPreferredWidth(width);
    }
  }

  public static void setVisibleRowCount(JTable table, int rows)
  {
    table.setPreferredScrollableViewportSize(new Dimension( 
            table.getPreferredScrollableViewportSize().width, 
            rows * table.getRowHeight())); 
  }
}
Автор: splungebob Размещён: 21.05.2013 04:35

2 плюса

Есть ли простой способ реализовать это с помощью TableRowSorter?

Автор: mKorbel Размещён: 21.05.2013 03:17

1 плюс

@Das: возможно, эта версия лучше, так как вам не нужно переопределять getRowCount (), который может использоваться и может вызывать проблемы с другими функциями

public class TableRowSorterTotal<MyTableModel extends TableModel> extends TableRowSorter<TableModel>
{   

    TableRowSorterTotal(MyTableModel model)
    {
        super(model);
    }

    public int convertRowIndexToModel(int index)
    {
        int maxRow = super.getViewRowCount();
        int currModel = super.convertRowIndexToModel(index);
        int maxModel = super.convertRowIndexToModel(maxRow-1);

        if(currModel == maxModel)
            return maxRow - 1;

        if(currModel > maxModel)
            return currModel- 1;

        return currModel;
    }

    public int convertRowIndexToView(int index) 
    {
        int maxRow = super.getModelRowCount();
        int currView= super.convertRowIndexToView(index);
        int maxView = super.convertRowIndexToView(maxRow-1);

        if(currView == maxView)
            return maxRow - 1;

        if(currView > maxView)
            return currView- 1;

        return currView;
    }
}
Автор: guest123 Размещён: 06.06.2014 08:26

1 плюс

На основе этого примера приведенный ниже пример полного примера иллюстрирует подход в принятом ответе . В частности,

  • Реализация getRowCount()в TableModelвозвращает size()из List<Employee>, который является одним меньше , чем число строк отображаются в таблице.

  • Реализация getValueAt()в TableModelиллюстрирует вызов sum()в COLUMN_SALARYнекоторых из возможных вариантов отображения для остальных столбцов в дополнительной строке в нижней части.

  • Реализация getViewRowCount()in TableRowSorterпозволяет отображать дополнительную строку, но исключает разумную фильтрацию .

образ

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

/**
 * @see https://stackoverflow.com/a/37913520/230513
 * @see https://stackoverflow.com/a/37892395/230513
 */
public class JTableColumnTotalExample {

    public static void main(String[] args) {
        EventQueue.invokeLater(JTableColumnTotalExample::display);
    }

    public static void display() {
        JFrame f = new JFrame("JTable Sorting Example");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        List<Employee> listEmployees = createListEmployees();
        TableModel model = new EmployeeTableModel(listEmployees);
        JTable table = new JTable(model) {
            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return new Dimension(500, getRowCount() * getRowHeight());
            }
        };
        table.getColumnModel().getColumn(3).setCellRenderer(new CurrencyFormatter());
        TableRowSorter sorter = new TableRowSorter<TableModel>(model) {
            @Override
            public int convertRowIndexToModel(int index) {
                int maxRow = super.getViewRowCount();
                if (index >= maxRow) {
                    return index;
                }
                return super.convertRowIndexToModel(index);
            }

            @Override
            public int convertRowIndexToView(int index) {
                int maxRow = super.getModelRowCount();
                if (index > maxRow) {
                    return index;
                }
                return super.convertRowIndexToView(index);
            }

            @Override
            public int getViewRowCount() {
                return super.getViewRowCount() + 1;
            }
        };
        table.setRowSorter(sorter);
        f.add(new JScrollPane(table), BorderLayout.CENTER);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static List<Employee> createListEmployees() {
        List<Employee> listEmployees = new ArrayList<>();
        listEmployees.add(new Employee("Peter", "Manager", 40000));
        listEmployees.add(new Employee("Paul", "Programmer", 25000));
        listEmployees.add(new Employee("Mary", "Designer", 25000));
        listEmployees.add(new Employee("Donald", "Leader", 30000));
        listEmployees.add(new Employee("Tom", "Designer", 28000));
        listEmployees.add(new Employee("Samantha", "Analyst", 50000));
        listEmployees.add(new Employee("Jerome", "Programmer", 32000));
        listEmployees.add(new Employee("Jonathon", "Developer", 29000));
        listEmployees.add(new Employee("Kevin", "Programmer", 23000));
        listEmployees.add(new Employee("Anthony", "Programmer", 23000));
        listEmployees.add(new Employee("John", "Designer", 33000));
        listEmployees.add(new Employee("David", "Developer", 28000));
        listEmployees.add(new Employee("Harry", "Designer", 31000));
        listEmployees.add(new Employee("Charles", "Programmer", 26000));
        listEmployees.add(new Employee("Joseph", "Manager", 40000));
        return listEmployees;
    }

    private static class EmployeeTableModel extends AbstractTableModel {

        private static final int COLUMN_NUM = 0;
        private static final int COLUMN_NAME = 1;
        private static final int COLUMN_JOB = 2;
        private static final int COLUMN_SALARY = 3;

        private final String[] columnNames = {"No", "Name", "Job", "Salary"};
        private final List<Employee> listEmployees;

        public EmployeeTableModel(List<Employee> listEmployees) {
            this.listEmployees = listEmployees;
            int indexCount = 1;
            for (Employee employee : listEmployees) {
                employee.setIndex(indexCount++);
            }
        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public int getRowCount() {
            return listEmployees.size();
        }

        @Override
        public String getColumnName(int columnIndex) {
            return columnNames[columnIndex];
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return getValueAt(0, columnIndex).getClass();
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            if (rowIndex == getRowCount()) {
                switch (columnIndex) {
                    case COLUMN_NUM:
                        return 999_999_999;
                    case COLUMN_NAME:
                        return "Total";
                    case COLUMN_JOB:
                        return "Salary";
                    case COLUMN_SALARY:
                        return sum();
                }
            }
            Employee employee = listEmployees.get(rowIndex);
            switch (columnIndex) {
                case COLUMN_NUM:
                    return employee.getIndex();
                case COLUMN_NAME:
                    return employee.getName();
                case COLUMN_JOB:
                    return employee.getJob();
                case COLUMN_SALARY:
                    return employee.getSalary();
                default:
                    throw new IllegalArgumentException("Invalid column index");
            }
        }

        private int sum() {
            int sum = 0;
            for (int r = 0; r < getRowCount(); r++) {
                sum += (int) getValueAt(r, COLUMN_SALARY);
            }
            return sum;
        }
    }

    private static class Employee {

        private int index;
        private String name;
        private String job;
        private int salary;

        public Employee(String name, String job, int salary) {
            this.name = name;
            this.job = job;
            this.salary = salary;
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getJob() {
            return job;
        }

        public void setJob(String job) {
            this.job = job;
        }

        public int getSalary() {
            return salary;
        }

        public void setSalary(int age) {
            this.salary = age;
        }
    }

    private static class CurrencyFormatter extends DefaultTableCellRenderer {

        private NumberFormat numberFormat = NumberFormat.getCurrencyInstance();

        @Override
        public Component getTableCellRendererComponent(JTable jTable, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
            Component c = super.getTableCellRendererComponent(jTable, value,
                isSelected, hasFocus, row, column);
            if (c instanceof JLabel && value instanceof Number) {
                JLabel label = (JLabel) c;
                label.setHorizontalAlignment(JLabel.RIGHT);
                Number num = (Number) value;
                String text = numberFormat.format(num);
                label.setText(text);
            }
            return c;
        }
    }
}
Автор: trashgod Размещён: 20.06.2016 01:25
Вопросы из категории :
32x32