3

What i want to do:

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

Description:

I have 3 classes:

  • Main.java (runs program)
  • PeopleTableModel.java (holds data, extends AbstractTableModel)
  • PeopleTable.java (holds logic, extends JTable)

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

Update:

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)

And this is my whole code:

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?

shidizzle
  • 55
  • 1
  • 1
  • 10
  • 1
    It is impossible to say anything without the complete code of `PeopleTableModel` and `PeopleTable`. Please try to provide a [SSCCE](http://pscode.org/sscce.html). – Howard Nov 09 '12 at 12:07
  • Can you show us the stack trace? I'm afraid either `PeopleTableModel` or `PeopleTable` is to blame. – John Dvorak Nov 09 '12 at 12:08
  • change (in XxxTablModel) declarations from Vector to String :-) – mKorbel Nov 09 '12 at 12:08
  • it's actually not a vector, the title and data variables are already string arrays (where data is obviously a 2 dimensional array). Here are the other classes: [PeopleTableModel.java](http://pastebin.com/sNaVRPvU), [PeopleTable.java](http://pastebin.com/cKBytnrw). Stack trace added! – shidizzle Nov 09 '12 at 12:12
  • @Jan Dvorak . please read Oracles JTable tutorial, if is XxxTableModel based on Vector then isn't possible to put String[] and vice versa .... – mKorbel Nov 09 '12 at 12:17
  • this line is interesting: `at ch.bs.jsd.personen.PeopleTable.getPreferredSize(PeopleTable.java:113)` but `PeopleTable.java` does not show this method there. I suspect a version mismatch between the code we see and the code you run. – John Dvorak Nov 09 '12 at 12:18
  • Why is your code namespaced at the Department of Justice and Security in Basel, Switzerland? – John Dvorak Nov 09 '12 at 12:24
  • @Jan Dvorak yes, you are right. I just right after deleted the function getPreferredSize() in the PeopleTable class when printing my stack trace. nothing to consider about that. – shidizzle Nov 09 '12 at 12:27
  • 1
    (not running you code) at begining to move all methods starting with isCellEditable to the model, in the case that exceptions will be raised again edit your post with runnable code (contains main methods) , btw you can to put all classes to one – mKorbel Nov 09 '12 at 12:28
  • @JanDvorak: Because I work here as external. – shidizzle Nov 09 '12 at 12:28
  • 1
    for why reason is there KeyListener, remove that and update this thread with next question about getColumnClass – mKorbel Nov 09 '12 at 12:30
  • @mKorbel: Because I need it, why should i remove it? – shidizzle Nov 09 '12 at 12:33
  • I leaving this thread, much luck .... – mKorbel Nov 09 '12 at 12:34
  • Here is the [runnable code](http://pastebin.com/xra8Qvx2), of course without my SQLConnection class due to security reasons. – shidizzle Nov 09 '12 at 12:36
  • `frame.setSize(table.getPreferredSize());` This does not account for frame decorations, fortunately it is wiped out by `frame.pack();` on the next line (so it merely become redundant). – Andrew Thompson Nov 09 '12 at 12:54
  • ok good to know thank you! you know, I'm pretty new to this, so every even little tip makes me happy and helps me getting better :) unfortunately I am still struggling with this error. any idea? – shidizzle Nov 09 '12 at 13:07
  • 1
    And what is the instance variable `table` inside your class `PeopleTable` for? You really should remove it. – Howard Nov 09 '12 at 14:26
  • haha right! thanks ;) still struggling though (look up at my update from my initial post).. – shidizzle Nov 09 '12 at 14:40

2 Answers2

4

can start with

enter image description here

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);
            }
        });
    }
}
Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • you are right, my AbstractTableModel really doesn't hold anything special which for i would need it. it still does not work though. as you can read from my update, I figured out that the problem comes from my PeopleTable class, though I am clueless what it may be :/ – shidizzle Nov 09 '12 at 14:36
  • sorry, don't continue to developt your code, will be road to the throubles – mKorbel Nov 09 '12 at 14:38
  • 1
    very bad, really against natural rulles :-) 1. don't, never to create GUI inside JDBC connection, 2. ResultSet.close() in finally block, otherwise increasing JVM memory 3. add elements directly into Object[], recreate this object in loop before taking value from next fow from Database, and rest descibed everything in my comments, replace Keylistener with filtering in JTable (never will be works, nor stable) change ColumnClass, then there you can put Icon, Double, String, Boolean directly (see link in my answer about abstractTable ...) and another :-) sorry – mKorbel Nov 09 '12 at 14:54
  • ugh.. seems like there is a long way to go.. :-) I am pretty new to this (just finished my apprenticeship as software developer), there is a lot to discover. I hope, I don't disturb others here. may the codereview site of stackoverflow a better place for me for now? – shidizzle Nov 09 '12 at 15:13
  • maybe good idea, click flag button describe the ask for moving to another forum – mKorbel Nov 09 '12 at 15:16
0

You do not need to write so many lines of code to display a file. Just download the jar file rs2xml and add it to your project library.

Note: This will be useful if you are using netbeans

How to use it?

  • Create the table in backend
  • Download rs2xml jar file
  • Add it to the project library
  • Drag the JTable from the swing controls to your JFrame
  • Now write the following code as follows:

Write your query:

    ps=con.prepareStatement("select * from register");       
    ResultSet r=ps.executeQuery();
    jTable1.setModel(DbUtils.resultSetToTableModel(r)); //display the register
Rubydesic
  • 3,386
  • 12
  • 27
javababy
  • 17
  • 10