在 JFrame 中显示 JTable

我想做什么:

我想列出数据库的一些记录.此列表应显示在 JFrame 弹出窗口中.

I want to list some records of a database. This list should be displayed in a JFrame popup.

说明:

我有 3 个课程:

  • Main.java(运行程序)
  • PeopleTableModel.java(保存数据,扩展 AbstractTableModel)
  • PeopleTable.java(保存逻辑,扩展 JTable)

为什么在将 JFrame 设置为可见时出现 ArrayIndexOutOfBoundsException?

Why I am getting an ArrayIndexOutOfBoundsException when setting my JFrame to visible?

更新:

似乎只有在我使用自己的 PeopleTable 类时才会出现此错误.当我将表分配给普通的 JTable 时,它​​可以工作.

It seems like this error only shows up, when I use my own PeopleTable class. When I assign the table to just a normal JTable, it works.

这是我得到的堆栈跟踪:

Here is my stack trace I am getting:

java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
    at java.util.Vector.elementAt(Vector.java:470)
    at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
    at javax.swing.JTable.getCellRect(JTable.java:2969)
    at javax.swing.plaf.basic.BasicTableUI.createTableSize(BasicTableUI.java:1694)
    at javax.swing.plaf.basic.BasicTableUI.getPreferredSize(BasicTableUI.java:1733)
    at javax.swing.JComponent.getPreferredSize(JComponent.java:1660)
    at javax.swing.ScrollPaneLayout.preferredLayoutSize(ScrollPaneLayout.java:495)
    at java.awt.Container.preferredSize(Container.java:1788)
    at java.awt.Container.getPreferredSize(Container.java:1773)
    at javax.swing.JComponent.getPreferredSize(JComponent.java:1662)
    at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:719)
    at java.awt.Container.preferredSize(Container.java:1788)
    at java.awt.Container.getPreferredSize(Container.java:1773)
    at javax.swing.JComponent.getPreferredSize(JComponent.java:1662)
    at javax.swing.JRootPane$RootLayout.preferredLayoutSize(JRootPane.java:917)
    at java.awt.Container.preferredSize(Container.java:1788)
    at java.awt.Container.getPreferredSize(Container.java:1773)
    at javax.swing.JComponent.getPreferredSize(JComponent.java:1662)
    at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:719)
    at java.awt.Container.preferredSize(Container.java:1788)
    at java.awt.Container.getPreferredSize(Container.java:1773)
    at java.awt.Window.pack(Window.java:809)
    at ch.bs.jsd.personen.Main.main(Main.java:67)

这是我的全部代码:

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.sql.ResultSet;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

public class Main {

    public static void main(String[] args) {
        ArrayList<String[]> result = new ArrayList<String[]>();
        SQLConnection sql = new SQLConnection();
        String OBNr = "";
        String firstName = "";
        String lastName = "";
        String qry = "SELECT loginid,ctitle as Grad,"
                + "name+' '+firstname as SachB,"
                + "cposition as Tour,Ressort,"
                + "left(location,2) as FNr "
                + "FROM dbo.abf_muPostenAdressen "
                + "WHERE loginid LIKE '%" + OBNr + "%'"
                + "AND name LIKE '%" + lastName + "%'"
                + "AND firstname LIKE '%" + firstName + "%'";
        try {
            ResultSet rs = sql.getConnection().prepareStatement(qry).executeQuery();
            while (rs.next()) {
                result.add(new String[]{
                            Integer.toString(rs.getRow()),
                            rs.getString("loginid"),
                            rs.getString("Grad"),
                            rs.getString("SachB"),
                            rs.getString("Tour"),
                            rs.getString("Ressort"),
                            rs.getString("FNr")
                        });
            }
            if (result.size() != 0) {
                String[] selectedData = null;
                if (result.size() > 1) {
                    String[] title = {"#", "loginid", "Grad", "SachB", "Tour",
                        "Ressort", "FNr"};
                    TableModel model = new PeopleTableModel(title, parse_2d_array(result));
                    JTable table = new PeopleTable(model);
                    JFrame frame = new JFrame();
                    frame.getContentPane().add(new JScrollPane(table));
                    frame.setVisible(true);
                    while (table.getSelectedRow() != -1) {
                    }
                    selectedData = result.get(table.getSelectedRow());
                    frame.dispose();
                } else {
                    selectedData = result.get(0);
                }
                System.out.println(join(selectedData, ", "));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        sql.closeConnection();
    }

    private static String join(String[] s, String delimiter) {
        if (s.length == 0) {
            return null;
        }
        StringBuilder out = new StringBuilder();
        out.append(s[0]);
        for (int i = 1; i < s.length; ++i) {
            out.append(delimiter).append(s[i]);
        }
        return out.toString();
    }

    private static String[][] parse_2d_array(ArrayList<String[]> al) {
        String[][] data = new String[al.size()][6];
        for (int i = 0; i < al.size(); i++) {
            data[i] = al.get(i);
        }
        return data;
    }
}

class PeopleTableModel extends AbstractTableModel {

    private static final long serialVersionUID = -1080095595481949205L;
    private String[] title;
    private Object[][] data;

    public PeopleTableModel(String[] title, Object[][] data) {
        this.title = title;
        this.data = data;
    }

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

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

    @Override
    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

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

class PeopleTable extends JTable {

    private static final long serialVersionUID = -1080095595481949205L;
    private JTable table;
    private int selectedRow = -1;
    private StringBuilder pressedKeys = new StringBuilder();
    private long now = 0;
    private long last = 0;

    public PeopleTable(TableModel model) {
        table = new JTable(model);

        table.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseClicked(java.awt.event.MouseEvent e) {
                if (e.getClickCount() == 2) {
                    setSelectedRow(table.rowAtPoint(e.getPoint()));
                }
            }
        });
        table.addKeyListener(new KeyAdapter() {

            @Override
            public void keyTyped(KeyEvent evt) {
            }

            @Override
            public void keyReleased(KeyEvent evt) {
            }

            @Override
            public void keyPressed(KeyEvent evt) {
                int key = evt.getKeyCode();

                // add only numbers
                if ((key > 47 && key < 58) || (key > 95 && key < 106)) {
                    last = now == 0 ? 0 : now;
                    now = evt.getWhen();

                    if (now - last > 700) {
                        pressedKeys = new StringBuilder();
                    }
                    pressedKeys.append(evt.getKeyChar());
                    int row = Integer.parseInt(pressedKeys.toString()) - 1;
                    table.setRowSelectionInterval(row, row);
                    table.scrollRectToVisible(table.getCellRect(row, 0, true));
                } else if (key == KeyEvent.VK_ENTER) {
                    if (pressedKeys.length() == 0) {
                        pressedKeys.append(1);
                    }
                    setSelectedRow(Integer.parseInt(pressedKeys.toString()) - 1);
                }
            }
        });
    }

    public JTable getTable() {
        return table;
    }

    private void setSelectedRow(int i) {
        selectedRow = i;
    }

    @Override
    public int getSelectedRow() {
        return selectedRow;
    }

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

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

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

    @Override
    public Object getValueAt(int row, int col) {
        return table.getValueAt(row, col);
    }
}

附加问题:有没有更好的方法来实现我的目标,或者这可以说是最佳实践?

Additional question: Is there a better way to achieve my goal or could this be stated as best practise?

推荐答案

  • 查看 JTable 教程,那里都有描述

    我看不出有使用 AbstractTableModel 的理由,不知道为什么要麻烦 JTable 包含实数行列(最多 500/1000 & 20/50),以 DefaultTableModel 而不是

    I can't see there reason to use AbstractTableModel, no idea why bothering for JTable contains a real number of rows & columns (up to 500/1000 & 20/50), start with DefaultTableModel instead

    或用这个AbstractTableModel

    可以开始

    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.*;
    import javax.swing.UIManager.LookAndFeelInfo;
    import javax.swing.border.LineBorder;
    import javax.swing.event.ListSelectionEvent;
    import javax.swing.event.ListSelectionListener;
    import javax.swing.table.*;
    
    public class RemoveAddRows extends JFrame {
    
        private static final long serialVersionUID = 1L;
        private Object[] columnNames = {"Type", "Company", "Shares", "Price"};
        private Object[][] data = {
            {"Buy", "IBM", new Integer(1000), new Double(80.50)},
            {"Sell", "MicroSoft", new Integer(2000), new Double(6.25)},
            {"Sell", "Apple", new Integer(3000), new Double(7.35)},
            {"Buy", "Nortel", new Integer(4000), new Double(20.00)}
        };
        private JTable table;
        private DefaultTableModel model;
        private javax.swing.Timer timer = null;
    
        public RemoveAddRows() {
            model = new DefaultTableModel(data, columnNames) {
    
                private static final long serialVersionUID = 1L;
    
                @Override
                public Class getColumnClass(int column) {
                    return getValueAt(0, column).getClass();
                }
            };
            table = new JTable(model) {
    
                private static final long serialVersionUID = 1L;
    
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                    Component c = super.prepareRenderer(renderer, row, column);
                    if (isRowSelected(row) && isColumnSelected(column)) {
                        ((JComponent) c).setBorder(new LineBorder(Color.red));
                    }
                    return c;
                }
            };
            ListSelectionModel rowSelMod = table.getSelectionModel();
            rowSelMod.addListSelectionListener(new ListSelectionListener() {
    
                public void valueChanged(ListSelectionEvent e) {
                    int row = table.getSelectedRow();
                    int col = table.getSelectedColumn();
                    String str = "Selected Row(s): ";
                    int[] rows = table.getSelectedRows();
                    for (int i = 0; i < rows.length; i++) {
                        str += rows[i] + " ";
                    }
                    str += "Selected Column(s): ";
                    int[] cols = table.getSelectedColumns();
                    for (int i = 0; i < cols.length; i++) {
                        str += cols[i] + " ";
                    }
                    str += "Selected Cell: " + table.getSelectedRow() + ", " + table.getSelectedColumn();
                    System.out.println(str);
                    Object value = table.getValueAt(row, col);
                    System.out.println(String.valueOf(value));
                }
            });
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            JScrollPane scrollPane = new JScrollPane(table);
            add(scrollPane);
            JButton button1 = new JButton("Remove all rows");
            button1.addActionListener(new ActionListener() {
    
                public void actionPerformed(ActionEvent arg0) {
                    if (model.getRowCount() > 0) {
                        for (int i = model.getRowCount() - 1; i > -1; i--) {
                            model.removeRow(i);
                        }
                    }
                    System.out.println("model.getRowCount() --->" + model.getRowCount());
                }
            });
            JButton button2 = new JButton("Add new rows");
            button2.addActionListener(new ActionListener() {
    
                public void actionPerformed(ActionEvent arg0) {
                    start();
                }
            });
            JPanel southPanel = new JPanel();
            southPanel.add(button1);
            southPanel.add(button2);
            add(southPanel, BorderLayout.SOUTH);
        }
    
        private void start() {
            timer = new javax.swing.Timer(2500, updateCol());
            timer.start();
        }
    
        public Action updateCol() {
            return new AbstractAction("text load action") {
    
                private static final long serialVersionUID = 1L;
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    DefaultTableModel model = (DefaultTableModel) table.getModel();
                    Object[] data0 = {"Buy", "IBM", new Integer(1000), new Double(80.50)};
                    model.addRow(data0);
                    Object[] data1 = {"Sell", "MicroSoft", new Integer(2000), new Double(6.25)};
                    model.addRow(data1);
                    Object[] data2 = {"Sell", "Apple", new Integer(3000), new Double(7.35)};
                    model.addRow(data2);
                    Object[] data3 = {"Buy", "Nortel", new Integer(4000), new Double(20.00)};
                    model.addRow(data3);
                    System.out.println("model.getRowCount() --->" + model.getRowCount());
                    timer.stop();
                    int rowIndex = table.getRowCount() - 1;
                    table.changeSelection(rowIndex, 0, false, false);
                }
            };
        }
    
        public static void main(String[] args) {
            try {
                for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                    System.out.println(info.getName());
                    if ("Nimbus".equals(info.getName())) {
                        UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            } catch (UnsupportedLookAndFeelException e) {
                // handle exception
            } catch (ClassNotFoundException e) {
                // handle exception
            } catch (InstantiationException e) {
                // handle exception
            } catch (IllegalAccessException e) {
                // handle exception
            }
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    RemoveAddRows frame = new RemoveAddRows();
                    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }
    

相关文章