javaswingjtableactionlistenerselectionmodel

ListSelectionModel - getMinSelectionIndex() falsely returns -1


I extracted a table from an Oracle database via a TableModel. Here is the source code:

package database;

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.Document;

import oracle.jdbc.internal.OracleResultSet;
import oracle.sql.CLOB;
import oracle.xdb.XMLType;

import java.sql.*;
import java.util.*;

/**
 * an immutable table model built from getting metadata about a table in a jdbc
 * database
 */
public class TestKonfigTableModel extends AbstractTableModel {
static Object[][] contents;
String[] columnNames;
Class[] columnClasses;

public TestKonfigTableModel(Connection conn, String tableName) throws SQLException {
    super();
    getTableContents(conn, tableName);

}

protected void getTableContents(Connection conn, String tableName) throws SQLException {

    // get metadata: what columns exist and what
    // types (classes) are they?
    DatabaseMetaData meta = conn.getMetaData();
    System.out.println("got meta = " + meta);
    ResultSet results = meta.getColumns(null, null, tableName, null);
    OracleResultSet orset = (OracleResultSet)results;
    System.out.println("got column results");
    ArrayList colNamesList = new ArrayList();
    ArrayList colClassesList = new ArrayList();

    while (results.next()) {
        colNamesList.add(results.getString("COLUMN_NAME"));
        System.out.println("name: " + results.getString("COLUMN_NAME"));
        int dbType = results.getInt("DATA_TYPE");
        switch (dbType) {
        case Types.INTEGER:
            colClassesList.add(Integer.class);
            break;
        case Types.FLOAT:
            colClassesList.add(Float.class);
            break;
        case Types.DOUBLE:
        case Types.REAL:
            colClassesList.add(Double.class);
            break;
        case Types.DATE:
        case Types.TIME:
        case Types.TIMESTAMP:
            colClassesList.add(java.sql.Timestamp.class);
            break;

        case Types.SQLXML:
            colClassesList.add(oracle.xdb.XMLType.class);

        default:
            colClassesList.add(String.class);
            break;
        }
        ;
        System.out.println("type: " + results.getInt("DATA_TYPE"));
    }

    columnNames = new String[colNamesList.size()];
    colNamesList.toArray(columnNames);
    columnClasses = new Class[colClassesList.size()];
    colClassesList.toArray(columnClasses);

    // get all data from table and put into
    // contents array

    Statement statement = conn.createStatement();
    results = statement.executeQuery("SELECT * FROM " + tableName + " ORDER BY 1");
    ArrayList rowList = new ArrayList();
    while (results.next()) {
        ArrayList cellList = new ArrayList();
        for (int i = 0; i < columnClasses.length - 1; i++) {
            Object cellValue = null;

            if (columnClasses[i] == String.class)
                cellValue = results.getString(columnNames[i]);
            else if (columnClasses[i] == Integer.class)
                cellValue = new Integer(results.getInt(columnNames[i]));
            else if (columnClasses[i] == Float.class)
                cellValue = new Float(results.getInt(columnNames[i]));
            else if (columnClasses[i] == Double.class)
                cellValue = new Double(results.getDouble(columnNames[i]));
            else if (columnClasses[i] == java.sql.Date.class)
                cellValue = results.getTimestamp(columnNames[i]);
            else if (columnClasses[i] == oracle.xdb.XMLType.class) {
                cellValue = results.getSQLXML(columnNames[i]);
            } else
                System.out.println("Can't assign " + columnNames[i]);
            cellList.add(cellValue);
        } // for
        Object[] cells = cellList.toArray();
        rowList.add(cells);

    } // while
        // finally create contents two-dim array
    contents = new Object[rowList.size()][];
    for (int i = 0; i < contents.length; i++)

        contents[i] = (Object[]) rowList.get(i);
    System.out.println("Created model with " + contents.length + " rows");

    // close stuff
    results.close();
    statement.close();

}

// AbstractTableModel methods
public int getRowCount() {
    return contents.length;
}

public int getColumnCount() {
    if (contents.length == 0)
        return 0;
    else
        return contents[0].length;
}

public Object getValueAt(int row, int column) {
    return contents[row][column];
}

// overrides methods for which AbstractTableModel
// has trivial implementations

public Class getColumnClass(int col) {
    return columnClasses[col];
}

public String getColumnName(int col) {
    return columnNames[col];
}
}

Everything worked fine, my table is shown exactly like I wanted it to. Now, however, I want to add an Action Listener to the table rows, so that on a double click, the number of the row is returned. This now always Returns -1. According to the API description this means, no row is selected. But I DID select and double click some rows and it keeps returning -1. For testing reasons I wrote all of this in a main method, so excuse the poor style:

package database;

import javax.swing.*;
import javax.swing.table.*;

import oracle.jdbc.pool.OracleDataSource;

import java.sql.*;
import java.util.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;

public class GUIAutoTest {
public static void main(String[] args) {
    try {

        /*
         * driver, url, user, and pass can be passed in as system properties
         * "jdbctable.driver", "jdbctable.url", "jdbctable.user", and
         * "jdbctable.pass", or specified in a file called
         * "jdbctable.properties" in current directory
         */
        Properties testProps = new Properties();
        String ddriver = System.getProperty("jdbctable.driver");
        String durl = System.getProperty("jdbctable.url");
        String duser = System.getProperty("jdbctable.user");
        String dpass = System.getProperty("jdbctable.pass");
        ListSelectionModel testSelectionModel;

        if (ddriver != null)
            testProps.setProperty("jdbctable.driver", ddriver);
        if (durl != null)
            testProps.setProperty("jdbctable.url", durl);
        if (duser != null)
            testProps.setProperty("jdbctable.user", duser);
        if (dpass != null)
            testProps.setProperty("jdbctable.pass", dpass);
        try {
            testProps.load(new FileInputStream(new File("jdbctable.properties")));
        } catch (Exception e) {
        } // ignore FNF, etc.

        System.out.println("Test Properties:");
        testProps.list(System.out);
        // now get a connection
        // note care to replace nulls with empty strings
        OracleDataSource ods = new OracleDataSource();
        ods.setDriverType("thin");
        ods.setNetworkProtocol("tcp");
        ods.setDatabaseName("***");
        ods.setServerName("***");
        ods.setPortNumber(1521);
        ods.setUser("***");
        ods.setPassword("***");
        Connection conn = ods.getConnection();
        // create db table to use
        String tableName = createSampleTable(conn);

        // get a model for this db table and add to a JTable
        TableModel mod = new TestKonfigTableModel(conn, tableName);
        JTable jtable = new JTable(mod);

        testSelectionModel = jtable.getSelectionModel();
        testSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        int testKonfig = testSelectionModel.getMinSelectionIndex();

        jtable.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent event) {
                if (event.getClickCount() == 2) {
                    System.out.println(testKonfig);
                }
            }
        });


        JScrollPane scroller = new JScrollPane(jtable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        JFrame frame = new JFrame("JDBCTableModel demo");
        frame.getContentPane().add(scroller);
        frame.pack();
        frame.setVisible(true);

        conn.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static String createSampleTable(Connection conn) throws SQLException {
    return "TEST_KONFIG";
}

}

Where is my mistake?


Solution

  •     int testKonfig = testSelectionModel.getMinSelectionIndex();
    
        jtable.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent event) {
                if (event.getClickCount() == 2) {
                    System.out.println(testKonfig);
                }
            }
        });
    

    You set the value of "testDonfig" before the user has a change to click on a row.

    the code should be:

        //int testKonfig = testSelectionModel.getMinSelectionIndex();
    
        jtable.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent event) {
                if (event.getClickCount() == 2) {
                    int testKonfig = testSelectionModel.getMinSelectionIndex();
                    System.out.println(testKonfig);
                }
            }
        });