javaswinglayoutlistenerjtoolbar

Get floatable JToolBar position when it changes


I have a floatable toolbar the user can move around at his convenience and I want to keep the last position so he finds it at the same location on next start.

I'm using a BorderLayout so the toolbar can be docked North, South, East or West (or be in a separate frame) so I'm able to call BorderLayout.getConstraints() to get its BorderLayout constraint.

I registered an AncestorListener to catch the ancestorMoved() callback but it gets called somehow randomly. A ComponentListener has the same effect (componentMoved() callback).

If I query the toolbar constraints periodically though I can see it change, so I could just query it when my application exits, but I'd like to understand why my listener doesn't get called as I hoped it would have been.

Running the following SSCCE on my Ubuntu Oracle JDK 1.7_80, I move the toolbar from North to West -> no output. West to South -> works. South to East -> works. East to North -> works. North to West -> no output, ... Same behaviour noted on Oracle JDK 1.8.0_102, and on Windows as well.

class ToolBarPos extends JFrame {

    private static final long serialVersionUID = 1L;

    ToolBarPos() {
        super();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setBounds(100, 100, 800, 600);
        Container cp = getContentPane();
        final BorderLayout layout = new BorderLayout();
        cp.setLayout(layout);
        final JToolBar tb = new JToolBar();
        cp.add(tb, BorderLayout.NORTH);
        tb.addAncestorListener(new AncestorListener() {
            @Override public void ancestorAdded(AncestorEvent event) { }
            @Override public void ancestorRemoved(AncestorEvent event) { }

            @Override public void ancestorMoved(AncestorEvent event) {
                String pos = (String)layout.getConstraints(event.getComponent()); // null if detached
                System.out.println("Moved "+pos+".");
            }
        });
        tb.add(new JLabel("Element"));
        cp.add(new JLabel("CENTER"), BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        new ToolBarPos().setVisible(true);
    }

}

Solution

  • I'm guessing that you don't get an event when the toolbar is moved from the NORTH to the WEST because the location doesn't change. That is it is still located at (0, 0) of the content pane.

    I would suggest you use a ComponentListener and listen for componentMoved and componentResized events.