X

Geertjan's Blog

  • November 19, 2011

Context Sensitive JTable (Part 1)

Geertjan Wielenga
Product Manager

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 = "Stock",
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());
    }
}

Continue to part 2...

Join the discussion

Comments ( 4 )
  • guest Sunday, May 5, 2013

    Wish we could download a working example of this code because the concept is cool but even with part 2, this is not working. Missing pieces.


  • Geertjan Sunday, May 5, 2013

    Can you give a very small clue what missing pieces are you talking about?


  • Marcel Snoeck Friday, June 14, 2013

    I am Busy with creating an Context Sensitive Table in an Form.

    This Form I have Build with NetBeans.

    I am Using JDK7 and NetBeans 7.3.

    I am not an Specialist in Java, and I am Learning at the Moment.

    My Question is when I add the following Code:

    private DefaultTableModel StockTableModel (List<Stock> stockList) {.....

    Then I get the message "type List does not take parameters"

    An other question is, does Stock, mentioned in this code List<Stock> , I and reference to Stock Class earlier defined.

    Thanks for your reply and support


  • Rob Egan Tuesday, November 26, 2013

    Geertjan, how can one display the data in the selected row within the Properties viewer?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.