java 为什么在尝试删除JTable中的元素时会出现ArrayIndex越界异常?[已关闭]

6ie5vjzr  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(155)
    • 已关闭**。此问题需要超过focused。当前不接受答案。
    • 想要改进此问题吗?**更新此问题,使其仅关注editing this post的一个问题。

3小时前关门了。
Improve this question
我试图在Jswing上实现一个GUI员工管理器,其中数据存储在一个文本文件中,我将其视为数据库,并创建了一个GUI界面来与之交互。
打开程序后,我可以使用删除功能,它工作正常,但一旦我点击搜索按钮(表搜索值,只显示我搜索的值),然后当我试图删除一些东西时,它抛出下面的错误。
这是我在搜索时遇到的错误:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 2 >= 2
    at java.base/java.util.Vector.elementAt(Vector.java:466)
    at java.desktop/javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:660)
    at java.desktop/javax.swing.JTable.getValueAt(JTable.java:2763)
    at java.desktop/javax.swing.JTable.prepareRenderer(JTable.java:5780)
    at java.desktop/javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2210)
    at java.desktop/javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2112)
    at java.desktop/javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1908)
    at java.desktop/javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
    at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:842)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1119)
    at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5311)
    at java.desktop/javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:246)
    at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1337)
    at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5259)
    at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5069)
    at
  • --------------编辑------------
    下面是我的最小可复制代码:
import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.util.*;
    import javax.swing.JTable;
    import java.io.IOException;  // Import the IOException class to handle errors
    import java.io.File;  // Import the File class
    import java.io.FileNotFoundException;  // Import this class to handle errors
    import javax.swing.table.DefaultTableModel;
    import java.io.FileWriter;
    import javax.swing.event.*;
    import javax.swing.table.*;
class UserManager extends JFrame implements ActionListener {
  // Initializing class variables
  private JTextField firstNameField, lastNameField, salaryField, textField;
  private JButton addButton, removeButton, sortButton, button;
  private JList<Employee> userList;
  private ArrayList<Employee> users;
  private JTable j;
  private DefaultTableModel model;
  private JTextField searchField;

  /*****************************************
  /*Name: UserManager (constructor)
  /*Method Description: Constructor class that runs once upon creation of the object. Creates the frame of the GUI app. Pulls from the database and displays it on the GUI interface.
  /*Method Inputs/Outputs: Outputs the GUI frame of the app.
  ******************************************/
  public UserManager() {
    setTitle("Employee Manager");
    setSize(400, 400);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    // Initializing and binding action items
    firstNameField = new JTextField(20);
    lastNameField = new JTextField(20);
    salaryField = new JTextField(20);
    searchField = new JTextField(20);
    addButton = new JButton("Add");
    addButton.addActionListener(this);
    removeButton = new JButton("Remove");
    removeButton.addActionListener(this);
    sortButton = new JButton("Sort Salary");
    sortButton.addActionListener(this);

    // Pulling data from text file database upon start up
    ArrayList<ArrayList<String>> databaseData = ReadFile();

    users = new ArrayList<Employee>();

    // Adding existing databaseData to users
    try {
      if (databaseData.size() > 0) {
        for (int i = 0; i < databaseData.size(); i++) {
          Employee user = new Employee(databaseData.get(i).get(0), databaseData.get(i).get(1), Integer.valueOf(databaseData.get(i).get(2)));
          users.add(user);
        }
      }
    }
    catch (NumberFormatException nfe) {
      nfe.printStackTrace();
      JOptionPane.showMessageDialog(this, "Internal System Error", "Error", JOptionPane.ERROR_MESSAGE);
    }

    // Creating the list of users
    userList = new JList<Employee>(users.toArray(new Employee[0]));

    // Setting up the JPanels
    JPanel firstNamePanel = new JPanel();
    firstNamePanel.add(new JLabel("First Name:"));
    firstNamePanel.add(firstNameField);

    JPanel lastNamePanel = new JPanel();
    lastNamePanel.add(new JLabel("Last Name:"));
    lastNamePanel.add(lastNameField);

    JPanel salaryPanel = new JPanel();
    salaryPanel.add(new JLabel("Salary:"));
    salaryPanel.add(salaryField);

    JPanel buttonPanel = new JPanel();
    buttonPanel.add(addButton);
    buttonPanel.add(removeButton);
    buttonPanel.add(sortButton);

    JPanel searchPanel = new JPanel();

    
    // Converting 2D arraylist to normal 2D array for JTable
    String[][] data = databaseData.stream().map(u -> u.toArray(new String[0])).toArray(String[][]::new);

    // Initializing column names of JTable
    String[] columnNames = { "FName", "LName", "Salary" };

    // Initialize the JTable and TableModel
    model = new DefaultTableModel(data, columnNames);
    j = new JTable(model);
    j.setBounds(1000, 1000, 900, 900);

    // adding it to JScrollPane
    JScrollPane table = new JScrollPane(j);

    
    JLabel label = new JLabel("Search: ");
    textField = new JTextField(20);
    button = new JButton("Go");
    searchPanel.add(label);
    searchPanel.add(textField);
    searchPanel.add(button);
    button.addActionListener(this);

    // Creating main panel and adding JPanels to it
    JPanel mainPanel = new JPanel(new GridLayout(6, 2));
    mainPanel.add(firstNamePanel);
    mainPanel.add(lastNamePanel);
    mainPanel.add(salaryPanel);
    mainPanel.add(buttonPanel);
    mainPanel.add(searchPanel);
    mainPanel.add(table);
    add(mainPanel);

  }

  /*****************************************
  /*Method Name: actionPerformed
  /*Method Description: Performs functions depending on what action is called. Adds users to the table and db if add button is clicked and removes users from the table and db if remove button is clicked.
  /*Method Inputs/Outputs: Refreshes the table and outputs the new array with the updates.
  ******************************************/
  public void actionPerformed(ActionEvent e) {
    // "Add" button is clicked
    if (e.getSource() == addButton) {
      // Initializing and setting variables
      String firstName = firstNameField.getText();
      String lastName = lastNameField.getText();
      int salary = 0;

      // Checks to see if salary entered is an integer
      try {
          salary = Integer.parseInt(salaryField.getText());
      } 
      catch (NumberFormatException nfe) {
        JOptionPane.showMessageDialog(this, "Please enter a valid salary", "Error", JOptionPane.ERROR_MESSAGE);
        return;
      }

      // Error check to see if full name and age is entered
      if (!firstName.equals("") && !lastName.equals("")) {
        Employee user = new Employee(firstName, lastName, salary);

        // Add the user to the arraylist
        users.add(user);

        // Creating new array with new information
        String[] newEmployeeArr = {firstName, lastName, String.valueOf(salary)};

        // Add new user to GUI
        model.addRow(newEmployeeArr);

        // Update user list
        updateList(users);

        // Resetting input fields
        firstNameField.setText("");
        lastNameField.setText("");
        salaryField.setText("");
      }
      else {
        JOptionPane.showMessageDialog(this, "Please enter a valid full name", "Error", JOptionPane.ERROR_MESSAGE);
      }

    } 

    // "Remove" button is clicked
    else if (e.getSource() == removeButton) {
      try {
        if(j.getSelectedRow() != -1) {
          // remove selected row from the model
          String value = j.getValueAt(j.getSelectedRow(), 0).toString();
          String value1 = j.getValueAt(j.getSelectedRow(), 1).toString();
          String value2 = j.getValueAt(j.getSelectedRow(), 2).toString();

          System.out.println(j.getSelectedRow() + " " + value + value1 + value2);

          // Accounting for if the table was sorted and looking to see where the removed var is in the model
          model.removeRow(removeUserFromTable(value, value1));

          
          // finds the index of the user to remove
          int selectedIndex = removeUser(value, value1, Integer.valueOf(value2));

          // Error checks to see if valid user
          if (selectedIndex != -1) {
            // Remove the selected employee from the users arraylist
            users.remove(selectedIndex);
            JOptionPane.showMessageDialog(null, "Selected row deleted successfully");
            
            // Update the list
            updateList(users);
    
            // Clear inputs
            firstNameField.setText("");
            lastNameField.setText("");
            salaryField.setText("");
          }
        }
        else {
          JOptionPane.showMessageDialog(this, "Employee not selected.", "Error", JOptionPane.ERROR_MESSAGE);
        }
      }
      catch (NumberFormatException nfe) {
        JOptionPane.showMessageDialog(this, "Select a valid row.", "Error", JOptionPane.ERROR_MESSAGE);
      }
    }

    // "Sort" button is clicked
    else if (e.getSource() == sortButton) {
      BubbleSort();
    }

      // "Go" button is clicked to search
    else if (e.getSource() == button) {
      // Creating a searching tool
      TableRowSorter<TableModel> sorter = new TableRowSorter<>(model);
      j.setRowSorter(sorter);
      String text = textField.getText();
      if (text.length() == 0) {
        sorter.setRowFilter(null);
      } else {
        sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text));
      }
    }
  }

  /*****************************************
  /*Method Name: updateList
  /*Method Description: Performs the update depending on what operation was made. Updates all lists inside the class and saves the change to the database.
  /*Method Inputs/Outputs: The new list with the updated list is inputted and an updated database text file is the output.
  ******************************************/
  private void updateList(ArrayList<Employee> u) {
    userList.setListData(u.toArray(new Employee[0]));

    // Log update to console
    System.out.println("Updating Database");

    // Overwriting db.txt file with new information
    try {
      // Making changes to the existed db.txt file
      FileWriter fw = new FileWriter("db.txt", false);

      // Loop through each student and write to the text file
      for (int i = 0; i < u.size(); i++) {
        // Re-writing the database file with the updates list
        fw.write(toString(u.get(i).getFirstName(), u.get(i).getLastName(), u.get(i).getSalary()));
      }
      fw.close();
    }
    catch (IOException io) {
      JOptionPane.showMessageDialog(this, "Internal System Error", "Error", JOptionPane.ERROR_MESSAGE);
      return;
    }
  }

  
  /*****************************************
  /*Method Name: removeUser
  /*Method Description: Searches for the selected user in the users arraylist and finds the index if the user exists
  /*Method Inputs/Outputs: The users arraylist and inputted user information is inputted and then outputs where the user is located in the array.
  ******************************************/
  private int removeUser(String firstName, String lastName, int salary) {
    // Loops through users arraylist
    for (int i = 0; i <  users.size(); i++) {
      // If the user exists in the database, remove them
      if (users.get(i).getFirstName().equals(firstName) && users.get(i).getLastName().equals(lastName) && users.get(i).getSalary() == salary) {
        return i;
      }
    }
    // No user by the name and salary was found
    return -1;
  }

  /*****************************************
  /*Method Name: removeUserFromTable
  /*Method Description: Searches for the selected user in the table model and finds the index if the user exists
  /*Method Inputs/Outputs: The user information is inputted and then outputs where the user is located in the model that controls the GUI table.
  ******************************************/
  private int removeUserFromTable(String firstName, String lastName) {
    int ind = 0;
    for (int i = 0; i < model.getRowCount(); i++){
      if (model.getValueAt(i, 0).toString().equals(firstName) && model.getValueAt(i, 1).toString().equals(lastName)) {
          ind = i;
          break;
      }
    }  
    return ind;
  }

  /*****************************************
  /*Method Name: toString
  /*Method Description: Converts three variables into one long string varaible
  /*Method Inputs/Outputs: The user information is inputted and the string that contains all three variables is outputted.
  ******************************************/
  public String toString(String firstName, String lastName, int salary) {
      return firstName + ", " + lastName + ", " + salary + "\n";
  }

  /*****************************************
  /*Method Name: BubbleSort
  /*Method Description: Performs bubble sort on the employees by salary and then updates the jtable
  /*Method Inputs/Outputs: No inputs or outputs, the JTable is updated
  ******************************************/
  public void BubbleSort() {
    try {
      // Array to hold a copy of the users list
      ArrayList<Employee> tempUsers = new ArrayList<Employee>();
    
      // Adding all the initial users to the new array to perform bubble sort
      for (int i =0; i < users.size(); i++) {
        tempUsers.add(users.get(i));
      }
    
      // Performing bubble sort
      for (int i = 0; i < users.size() - 1; i++) {
        // Looping through indexes
        for (int j = 0; j < users.size() - 1; j++) {
          // Comapare the salaries of each indiviual and see if the previous is bigger than the next
          if (users.get(j).getSalary() > users.get(j+1).getSalary()) {
            // Initializing a temp employee to hold value before switching
            Employee temp = users.get(j);
    
            // Swap the employees
            users.set(j, users.get(j+1));
            users.set(j+1,temp);
          }
        }
      }

      int[] selection = j.getSelectedRows();
      System.out.println(Arrays.toString(j.getSelectedRows()));
       for (int i = 0; i < selection.length; i++) {
         selection[i] = j.convertRowIndexToModel(selection[i]);
         System.out.println(selection[i]);
       }

      // Setting the jtable model to the sorted model
      j.setModel(model);
    }
    catch (NumberFormatException nfe) {
      JOptionPane.showMessageDialog(this, "Not Enough Users", "Error", JOptionPane.ERROR_MESSAGE);
      return;
    }
  }
  

  /*****************************************
  /*Method Name: ReadFile
  /*Method Description: Reads the db textfile and stores the values in a 2d arraylist for manipulation.
  /*Method Inputs/Outputs: The 2d arraylist with all the db information is outputted
  ******************************************/
  public static ArrayList<ArrayList<String>> ReadFile() {
    try {
      // Choose db.txt file to look at
      File myObj = new File("db.txt");

      // Create scanner object
      Scanner myReader = new Scanner(myObj);

      // Create 2d list array to hold all the single list arrays of single information
      ArrayList<ArrayList<String>> combinedArr = new ArrayList<ArrayList<String>>();
    
      // While the file reader is still reading lines in the text
      while (myReader.hasNextLine()) {
        // Read strings of text in txt file
        String data = myReader.nextLine();

        // Get user information into an array
        ArrayList<String> temp = GetInfo(data); 

        // Add the person and their salary to the combined array that holds everyones
        combinedArr.add(temp);
      }

      // Close file once there are no more lines to read
      myReader.close();

      return combinedArr;
    } 
    catch (FileNotFoundException e) {
      System.out.println("An error occurred.");
      e.printStackTrace();
    }

    // Return invalid list string with nothing if error
    ArrayList<ArrayList<String>> Invalid = new ArrayList<ArrayList<String>>();
    return Invalid;
  }

  /*****************************************
  /*Method Name: GetInfo
  /*Method Description: Takes in a string of data and parses the three variables in it which are separated by commas
  /*Method Inputs/Outputs: The data string that needs to be parsed is inputted and arraylist containuing the data from the string is outputted.
  ******************************************/
  public static ArrayList<String> GetInfo(String data) {
    String first = "";
    String last = "";
    String sal = "";
    // System.out.println(data[0])
    for (int i = 0; i < data.length(); i++) {
      if (data.charAt(i) == ',') {
        // Start from 2 indexes after the first occurance of the comma
        for (int j = i+2; j < data.length(); j++) {
          if (data.charAt(j) == ',') {
            // Start from 2 indexes after the occurance of the comma
            for (int n = j+2; n < data.length(); n++) {
              sal += data.charAt(n);
            }
            break;
          }
          last += data.charAt(j);
        }
        break;
      }
      first += data.charAt(i);
    }

    // Initializing package array to send all values
    ArrayList<String> arr = new ArrayList<String>();
    arr.add(first);
    arr.add(last);
    arr.add(sal);
    
    return arr;
  }

  /*****************************************
  /*Method Name: main
  /*Method Description: Runs the GUI frame
  /*Method Inputs/Outputs: Ouputs the GUI 
  ******************************************/
  public static void main(String[] args) {
      UserManager frame = new UserManager();
      frame.setVisible(true);
  }
}

class Employee {
  // Initalizing variables
  private String firstName;
  private String lastName;
  private int salary;

  public Employee(String firstName, String lastName, int salary) {
      this.firstName = firstName;
      this.lastName = lastName;
      this.salary = salary;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public int getSalary() {
    return salary;
  }
}
pbwdgjma

pbwdgjma1#

不要试图将数据和模型视为两个独立的东西,您应该将模型 Package 在数据周围,并允许管理它,例如...

public class EmployeeTableModel extends AbstractTableModel {

    private List<Employee> employees;
    private String[] columnNames = {"FName", "LName", "Salary"};
    private Class[] columnClasses = {String.class, String.class, Integer.class};

    public EmployeeTableModel(List<Employee> employees) {
        this.employees = employees;
    }

    public List<Employee> getEmployees() {
        return employees;
    }

    public String[] getColumnNames() {
        return columnNames;
    }

    public Class[] getColumnClasses() {
        return columnClasses;
    }

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

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

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

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return getColumnClasses()[columnIndex];
    }

    public void sortBySalary() {
        BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                // This is decending...
                return o2.getSalary() - o1.getSalary();
                // This is acending
                //return o1.getSalary() - o2.getSalary();
            }
        });
        // You could use
        //fireTableRowsUpdated(0, getRowCount() - 1);
        // But this will work just fine and will force a complete 
        // redraw of the table
        fireTableDataChanged();
    }

    public void sortByFirstName() {
        BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                return o1.getFirstName().compareTo(o2.getFirstName());
            }
        });
        fireTableDataChanged();
    }

    public void sortByLastName() {
        BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                return o1.getLastName().compareTo(o2.getLastName());
            }
        });
        fireTableDataChanged();
    }

    public void add(Employee employee) {
        int rowCount = getRowCount();
        getEmployees().add(employee);
        fireTableRowsInserted(rowCount, rowCount);
    }

    public void delete(Employee employee) {
        List<Employee> employees = getEmployees();
        for (int index = 0; index < employees.size(); index++) {
            if (employees.get(index).equals(employee)) {
                employees.remove(index);
                fireTableRowsDeleted(index, index);
                break;
            }
        }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Employee employee = getEmployees().get(rowIndex);
        switch (columnIndex) {
            case 0:
                return employee.getFirstName();
            case 1:
                return employee.getLastName();
            case 2:
                return employee.getSalary();
        }
        throw new ArrayIndexOutOfBoundsException(rowIndex + "x" + columnIndex + " is out of bounds");
    }
}

这是定制TableModel的一个非常基本的概念,它接受Employee s的List,提供TableModel的核心实现,但也提供了一些帮助方法,如adddelete,它们将触发适当的事件以允许JTable更新自己。
你可以很容易地用一个“数据库管理器”来支持它,这样排序/删除/添加/更新操作都可以委托给它,这些更新也可以对值的“数据库”进行,但是我打算让你自己去弄清楚。
现在,我将您的BubbleSort分离成它自己的、自包含的和可重用的类...

public class BubbleSort {
    public static <T> void sort(List<T> list, Comparator<? super T> comparator) {
        // Performing bubble sort
        for (int i = 0; i < list.size() - 1; i++) {
            // Looping through indexes
            for (int j = 0; j < list.size() - 1; j++) {
                // Comapare the salaries of each indiviual and see if the previous is bigger than the next
                if (comparator.compare(list.get(j), list.get(j + 1)) > 0) {
                    // Initializing a temp employee to hold value before switching
                    T temp = list.get(j);

                    // Swap the employees
                    list.set(j, list.get(j + 1));
                    list.set(j + 1, temp);
                }
            }
        }
    }
}

唯一的限制是您需要传入一个Comparator,它用于比较两个值,以确定它们是否应该交换。“但是为什么要这样做呢?”我听到您问,因为它是自包含的和可重用的。
所以,你想按工资排序吗?你想按升序排序吗...

BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.getSalary() - o2.getSalary();
    }
});

还是降序

BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o2.getSalary() - o1.getSalary();
    }
});

令人惊讶的是,你现在可以同时做这两件事,不需要太多的努力。但是等等,如果你想按名字排序呢?!

BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.getFirstName().compareTo(o2.getFirstName());
    }
});

还是姓!

BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o1.getLastName().compareTo(o2.getLastName());
    }
});

看,可重复使用。
你甚至可以把名字和薪水结合起来,当然,可行的,只要写一个新的Comparator。想排序其他类型的值,当然,只要你提供一个兼容的Comparator,没有问题。

可运行示例

我没有为您的“数据库”而烦恼,因为它真的不是问题的一部分,相反,我集中精力让表模型和排序一起工作(以及删除,因为您知道为什么不这样做)。

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import javax.swing.*;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import javax.swing.border.EmptyBorder;
import javax.swing.table.*;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new MainPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MainPane extends JPanel {

        private EmployeeTableModel employeeTableModel;
        private JTable table;

        public MainPane() {
            Random rnd = new Random();
            List<Employee> employees = new ArrayList<>(
                    Arrays.asList(
                            new Employee[]{
                                new Employee("Alesha", "Golden", rnd.nextInt(999) + 1),
                                new Employee("Gerald", "Guerrero", rnd.nextInt(999) + 1),
                                new Employee("Georgina", "Delacruz", rnd.nextInt(999) + 1),
                                new Employee("Michael", "Delgado", rnd.nextInt(999) + 1),
                                new Employee("Aysha", "Zimmerman", rnd.nextInt(999) + 1),
                                new Employee("Yahya", "Moreno", rnd.nextInt(999) + 1),
                                new Employee("Max", "Reyes", rnd.nextInt(999) + 1),
                                new Employee("Julia", "Salinas", rnd.nextInt(999) + 1),
                                new Employee("Aleeza", "Flores", rnd.nextInt(999) + 1),
                                new Employee("Milton", "Frye", rnd.nextInt(999) + 1),}
                    )
            );
            employeeTableModel = new EmployeeTableModel(employees);
            table = new JTable(employeeTableModel);

            setLayout(new BorderLayout());
            add(new JScrollPane(table));

            JButton sortBySalaryButton = new JButton("Sort by Salary");
            sortBySalaryButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    employeeTableModel.sortBySalary();
                }
            });
            JButton sortByFirstNameButton = new JButton("Sort by First name");
            sortByFirstNameButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    employeeTableModel.sortByFirstName();
                }
            });
            JButton sortLastNameButton = new JButton("Sort by Last name");
            sortLastNameButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    employeeTableModel.sortByLastName();
                }
            });
            // I'd normally use a SelectionListener to monitor
            // changes to the table in order to enable/disable this
            // button, but that's beyond the scope
            JButton deleteButton = new JButton("Delete");
            deleteButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int selectedRow = table.getSelectedRow();
                    if (selectedRow < 0) {
                        return;
                    }
                    Employee employee = employeeTableModel.getEmployeeAt(selectedRow);
                    employeeTableModel.delete(employee);
                }
            });

            JPanel actionPane = new JPanel(new GridBagLayout());
            actionPane.setBorder(new EmptyBorder(8, 8, 8, 8));
            actionPane.add(sortBySalaryButton);
            actionPane.add(sortByFirstNameButton);
            actionPane.add(sortLastNameButton);
            actionPane.add(deleteButton);
            add(actionPane, BorderLayout.SOUTH);
        }

    }

    class Employee {
        // Initalizing variables
        private String firstName;
        private String lastName;
        private int salary;

        public Employee(String firstName, String lastName, int salary) {
            this.firstName = firstName;
            this.lastName = lastName;
            this.salary = salary;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public int getSalary() {
            return salary;
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 59 * hash + Objects.hashCode(this.firstName);
            hash = 59 * hash + Objects.hashCode(this.lastName);
            hash = 59 * hash + this.salary;
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof Employee)) {
                return false;
            }
            Employee other = (Employee) obj;
            return getFirstName().equals(other.getFirstName())
                    && getLastName().equals(other.getLastName())
                    && getSalary() == other.getSalary();
        }
    }

    public class EmployeeTableModel extends AbstractTableModel {

        private List<Employee> employees;
        private String[] columnNames = {"FName", "LName", "Salary"};
        private Class[] columnClasses = {String.class, String.class, Integer.class};

        public EmployeeTableModel(List<Employee> employees) {
            this.employees = employees;
        }

        public List<Employee> getEmployees() {
            return employees;
        }

        public String[] getColumnNames() {
            return columnNames;
        }

        public Class[] getColumnClasses() {
            return columnClasses;
        }

        public Employee getEmployeeAt(int row) {
            return getEmployees().get(row);
        }

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

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

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

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return getColumnClasses()[columnIndex];
        }

        public void sortBySalary() {
            BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
                @Override
                public int compare(Employee o1, Employee o2) {
                    // This is decending...
                    return o2.getSalary() - o1.getSalary();
                    // This is acending
                    //return o1.getSalary() - o2.getSalary();
                }
            });
            // You could use
            //fireTableRowsUpdated(0, getRowCount() - 1);
            // But this will work just fine and will force a complete 
            // redraw of the table
            fireTableDataChanged();
        }

        public void sortByFirstName() {
            BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
                @Override
                public int compare(Employee o1, Employee o2) {
                    return o1.getFirstName().compareTo(o2.getFirstName());
                }
            });
            fireTableDataChanged();
        }

        public void sortByLastName() {
            BubbleSort.sort(getEmployees(), new Comparator<Employee>() {
                @Override
                public int compare(Employee o1, Employee o2) {
                    return o1.getLastName().compareTo(o2.getLastName());
                }
            });
            fireTableDataChanged();
        }

        public void add(Employee employee) {
            int rowCount = getRowCount();
            getEmployees().add(employee);
            fireTableRowsInserted(rowCount, rowCount);
        }

        public void delete(Employee employee) {
            List<Employee> employees = getEmployees();
            for (int index = 0; index < employees.size(); index++) {
                if (employees.get(index).equals(employee)) {
                    employees.remove(index);
                    fireTableRowsDeleted(index, index);
                    break;
                }
            }
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Employee employee = getEmployees().get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return employee.getFirstName();
                case 1:
                    return employee.getLastName();
                case 2:
                    return employee.getSalary();
            }
            throw new ArrayIndexOutOfBoundsException(rowIndex + "x" + columnIndex + " is out of bounds");
        }
    }

    public class BubbleSort {
        public static <T> void sort(List<T> list, Comparator<? super T> comparator) {
            // Performing bubble sort
            for (int i = 0; i < list.size() - 1; i++) {
                // Looping through indexes
                for (int j = 0; j < list.size() - 1; j++) {
                    // Comapare the salaries of each indiviual and see if the previous is bigger than the next
                    if (comparator.compare(list.get(j), list.get(j + 1)) > 0) {
                        // Initializing a temp employee to hold value before switching
                        T temp = list.get(j);

                        // Swap the employees
                        list.set(j, list.get(j + 1));
                        list.set(j + 1, temp);
                    }
                }
            }
        }
    }
}

相关问题