Context Sensitive JTable

Posted by Geertjan on Oracle Blogs See other posts from Oracle Blogs or by Geertjan
Published on Sat, 19 Nov 2011 10:12:09 -0600 Indexed on 2011/11/19 18:02 UTC
Read the original article Hit count: 388

Filed under:

Here's a plain old JTable on the NetBeans Platform. Whenever the toolbar button is clicked, information about the currently selected row is displayed in the status bar:

Normally, the above would be achieved in NetBeans Platform applications via Nodes publishing their underlying business object when the selection changes. In this case, there are no Nodes at all. There's only a JTable and a DefaultTableModel, i.e., all pure Java Swing.

So, how does it work? To follow the logic, it makes sense to create the example yourself, starting with the Stock object:

public class Stock {
 
    String name;
    String desc;

    public Stock() {
    }

    public Stock(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }

    public String getName() {
        return name;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Next, create a new Window Component via the wizard and then rewrite the constructor as follows:

public final class MyWindowTopComponent extends TopComponent {

    private final InstanceContent ic = new InstanceContent();

    public MyWindowTopComponent() {

        initComponents();

        //Statically create a few stocks,
        //in reality these would come from a data source
        //of some kind:
        List<Stock> list = new ArrayList();
        list.add(new Stock("AMZN", "Amazon"));
        list.add(new Stock("BOUT", "About.com"));
        list.add(new Stock("Something", "Something.com"));

        //Create a JTable, passing the List above
        //to a DefaultTableModel:
        final JTable table = new JTable(StockTableModel (list));
 
        //Whenever the mouse is clicked on the table,
        //somehow construct a new Stock object 
        //(or get it from the List above) and publish it:
        table.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                int selectedColumn = table.getSelectedColumn();
                int selectedRow = table.getSelectedRow();
                Stock s = new Stock();
                if (selectedColumn == 0) {
                    s.setName(table.getModel().getValueAt(selectedRow, 0).toString());
                    s.setDesc(table.getModel().getValueAt(selectedRow, 1).toString());
                } else {
                    s.setName(table.getModel().getValueAt(selectedRow, 1).toString());
                    s.setDesc(table.getModel().getValueAt(selectedRow, 0).toString());
                }
                ic.set(Collections.singleton(s), null);
            }
        });

        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane, BorderLayout.CENTER);

        //Put the dynamic InstanceContent into the Lookup:
        associateLookup(new AbstractLookup(ic));

    }

    private DefaultTableModel StockTableModel (List<Stock> stockList) {
 
        DefaultTableModel stockTableModel = new DefaultTableModel() {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
 
        Object[] columnNames = new Object[2];
        columnNames[0] = "Symbol";
        columnNames[1] = "Name";
        stockTableModel.setColumnIdentifiers(columnNames);
 
        Object[] rows = new Object[2];
        ListIterator<Stock> stockListIterator = stockList.listIterator();
        while (stockListIterator.hasNext()) {
            Stock nextStock = stockListIterator.next();
            rows[0] = nextStock.getName();
            rows[1] = nextStock.getDesc();
            stockTableModel.addRow(rows);
        }
 
        return stockTableModel;
 
    }
 
    ...
    ...
    ...

And now, since you're publishing a new Stock object whenever the user clicks in the table, you can create loosely coupled Actions, like this:

@ActionID(category = "Edit",
id = "org.my.ui.ShowStockAction")
@ActionRegistration(iconBase = "org/my/ui/Datasource.gif",
displayName = "#CTL_ShowStockAction")
@ActionReferences({
    @ActionReference(path = "Menu/File", position = 1300),
    @ActionReference(path = "Toolbars/File", position = 300)
})
@Messages("CTL_ShowStockAction=Show Stock")
public final class ShowStockAction implements ActionListener {

    private final Stock context;

    public ShowStockAction(Stock context) {
        this.context = context;
    }

    @Override
    public void actionPerformed(ActionEvent ev) {
        StatusDisplayer.getDefault().setStatusText(context.getName() + " / " + context.getDesc());
    }
 
}

© Oracle Blogs or respective owner

Related posts about /NetBeans IDE