X

Geertjan's Blog

  • November 20, 2011

Context Sensitive JTable (Part 2)

Geertjan Wielenga
Product Manager

Now, having completed part 1, let's add a popup menu to the JTable. However, the menu item in the popup menu should invoke the same Action as invoked from the toolbar button created yesterday.

Add this to the constructor created yesterday:

Collection<? extends Action> stockActions =
        Lookups.forPath("Actions/Stock").lookupAll(Action.class);
for (Action action : stockActions) {
    popupMenu.add(new JMenuItem(action));
}
MouseListener popupListener = new PopupListener();
// Add the listener to the JTable:
table.addMouseListener(popupListener);
// Add the listener specifically to the header:
table.getTableHeader().addMouseListener(popupListener);

And here's the standard popup enablement code:

private JPopupMenu popupMenu = new JPopupMenu();
class PopupListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
showPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
private void showPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
}

Join the discussion

Comments ( 7 )
  • Jesse Glick Monday, November 21, 2011

    This is wrong. You should use Utilities.actionsForPath then Utilities.actionsToPopup, which is simpler than the above code yet correctly handles Presenter.Popup, separators, and so on.

    More subtly, the above code fails to check for ContextAwareAction. (The proxy for ShowStockAction would implement this interface.) It may happen to work if as a side effect of right-clicking the table you also happen to (first) select the TopComponent containing the table and activate its row, thus activating its corresponding nodes, and said TC contains just this one table with a possible selection: the Action with no specified context will generally fall back to using actionsGlobalContext. But that involves a number of assumptions about the contents of the window, the behavior of the native window manager and focus system, the order of delivery of selection events, etc. Such assumptions are not acceptable for any explorer-like view displaying a popup menu.

    By contrast, actionsToPopup looks for a selection on the actual component being right-clicked, regardless of what the application's global selection might be. You can explicitly pass in a Lookup context if that is convenient; but you may also pass in the Component being clicked if it or an ancestor is a Lookup.Provider, which MyWindowTopComponent would be in this case.

    (In case you had multiple tables with independent selections in the same TC, you would want each to implement L.P or be wrapped in a panel which did, so that aTP given the specific JTable would pay attention just to the selection in that table, regardless of which table was currently considered "active" by the TC.)


  • metator Wednesday, November 30, 2011

    I have to thank you for this cool example. This may have some problems as pointed out by Jesse, but the idea behind all this is awesome. And i don't see why you couldn't do it for other components, like JTrees or JLists for instance. It should also ease the task of migrating a Swing application to a Netbeans application.

    Regards


  • Willy De Keyser Saturday, December 3, 2011

    Thanks for the cool example.

    Is it possible to disable the action when the table is empty and enabled when the table is not empty?


  • Geertjan Saturday, December 3, 2011

    Hi Willy. That's already the case. The Action is context-sensitive, so if there is no Stock object selected, i.e., the table is empty, the Action will be disabled.


  • Willy De Keyser Sunday, December 4, 2011

    I think I have found it.

    i have to put a : 'content.set(Collections.EMPTY_LIST, null);'

    in the 'resultChanged(LookupEvent lookupEvent)' from my 'EditorTopComponent' where i view the jTabel.

    This is the right way?


  • Osho Thursday, December 27, 2012

    @ Jesse,

    You say Utilities.actionsToPopup "correctly handles Presenter.Popup" but in my experience, using Utilities.actionsToPopup does not get the icons (16x16) associated with the actions to show up in the resulting popup menu - or am I missing something? I believe this defect is related to http://netbeans.org/bugzilla/show_bug.cgi?id=208081. Using Geertjan's approach, you can get the icons to show in the popup, but I agree you will have to do a little bit extra to handle things like separators etc.


  • guest Tuesday, September 27, 2016

    if its's the same popup for each row, it's clearly not context sensitive


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