javaswingpiccolo

PSelectionEventHandler does not trigger callback


I am using Piccolo2D library for drawing nodes on canvas. I've setup PSelectionEventHandler like in Piccolo2D's example at:SelectionExample.java and then I set breakpoint in

private void nodeSelected(final PNotification n)
{
}   // nodeSelected

but when I selected node, callback is not invoked. Why?

EDIT: (taken from OP's answer)

Ok, here is the code:

In main JFrame:

this.panelMain().panelWorkspace().canvas().addInputEventListener(
this.handlerCanvasSelection());
this.panelMain().panelWorkspace().canvas().getRoot().getDefaultInputManager().
     setKeyboardFocus(this.handlerCanvasSelection());

PNotificationCenter.defaultCenter().addListener(this, "nodeSelected",
                PSelectionEventHandler.SELECTION_CHANGED_NOTIFICATION,
                this.handlerCanvasSelection());

private void nodeSelected(final PNotification n)
{
}   // nodeSelected

Solution

  • The problem is that nodeSelected() method that is registered as a callback is declared private. The implementation of PNotificationCenter.addListener() uses reflection to lookup and register the callback method. It actually uses Class.getMethod() which returns only public methods. So if the method is not found (for whatever reason) the listener is not registered.

    Consider this simple example that demonstrates SELECTION_CHANGED_NOTIFICATION notifications:

    enter image description here

    import java.awt.*;
    import javax.swing.*;
    import edu.umd.cs.piccolo.*;
    import edu.umd.cs.piccolo.nodes.*;
    import edu.umd.cs.piccolox.event.*;
    
    public class TestSelectHandle {
    
        private static void createAndShowUI() {
            JFrame frame = new JFrame("TestSelectHandle");
            PCanvas canvas = new PCanvas() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(100, 200);
                }
            };
    
            final JTextArea output = new JTextArea(5, 20);
    
            JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
                    canvas, output);
            frame.add(splitPane);
    
            final PNode blueRect = PPath.createRectangle(50, 50, 50, 50);
            blueRect.setPaint(Color.BLUE);
            canvas.getLayer().addChild(blueRect);
    
            final PNode redRect = PPath.createRectangle(110, 110, 50, 50);
            redRect.setPaint(Color.RED);
            canvas.getLayer().addChild(redRect);
    
            canvas.removeInputEventListener(canvas.getPanEventHandler());
            canvas.removeInputEventListener(canvas.getZoomEventHandler());
    
            PSelectionEventHandler selectionHandler = new PSelectionEventHandler(
                    canvas.getLayer(), canvas.getLayer());
            canvas.addInputEventListener(selectionHandler);
            canvas.getRoot().getDefaultInputManager()
                    .setKeyboardFocus(selectionHandler);
    
            PNotificationCenter.defaultCenter().addListener(
                    new NodeSelectionListener(output), "selectionChanged",
                    PSelectionEventHandler.SELECTION_CHANGED_NOTIFICATION,
                    selectionHandler);
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static class NodeSelectionListener {
            private JTextArea output;
    
            public NodeSelectionListener(JTextArea output) {
                this.output = output;
            }
    
            public void selectionChanged(final PNotification notfication) {
                output.append("selection changed\n");
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowUI();
                }
            });
        }
    }