title: Displaying JTable in JFrame
body: <p><strong>What i want to do:</strong></p>
  
  <p>I want to list some records of a database. This list should be displayed in a JFrame popup.</p>
  
  <p><strong>Description:</strong></p>
  
  <p>I have 3 classes: </p>
  
  <ul>
  <li>Main.java (runs program)</li>
  <li>PeopleTableModel.java (holds data, extends AbstractTableModel)</li>
  <li>PeopleTable.java (holds logic, extends JTable)</li>
  </ul>
  
  <p>Why I am getting an ArrayIndexOutOfBoundsException when setting my JFrame to visible?</p>
  
  <p><strong>Update:</strong></p>
  
  <p>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.</p>
  
  <p>Here is my stack trace I am getting:</p>
  
  <pre><code>java.lang.ArrayIndexOutOfBoundsException: 0 &gt;= 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)
  </code></pre>
  
  <p>And this is my whole code:</p>
  
  <pre><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&lt;String[]&gt; result = new ArrayList&lt;String[]&gt;();
          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() &gt; 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 &lt; s.length; ++i) {
              out.append(delimiter).append(s[i]);
          }
          return out.toString();
      }
  
      private static String[][] parse_2d_array(ArrayList&lt;String[]&gt; al) {
          String[][] data = new String[al.size()][6];
          for (int i = 0; i &lt; 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 &gt; 47 &amp;&amp; key &lt; 58) || (key &gt; 95 &amp;&amp; key &lt; 106)) {
                      last = now == 0 ? 0 : now;
                      now = evt.getWhen();
  
                      if (now - last &gt; 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);
      }
  }
  </code></pre>
  
  <p>Additional question: Is there a better way to achieve my goal or could this be stated as best practise?</p>