你能让 JToolBar 不可分离吗?

Can you make a JToolBar undetachable?

我想让我的 JToolBar 无法与其容器分离,但仍然让用户将它拖到容器的一侧。

我知道

public void setFloatable( boolean b )

但这根本不允许用户移动 JToolBar。

有没有什么方法可以在不覆盖 ToolBarUI 的情况下做到这一点?

此外,是否有一个选项可以在删除它之前突出显示它的新位置?

  • 我在 WinOS 上工作得很好,来自 SunForum 的旧代码

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CaptiveToolBar {

    private Robot robot;
    private JDialog dialog;
    private JFrame frame;

    public static void main(String[] args) {
        //JFrame.setDefaultLookAndFeelDecorated(true);
        //JDialog.setDefaultLookAndFeelDecorated(true);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new CaptiveToolBar().makeUI();
            }
        });
    }

    public void makeUI() {
        try {
            robot = new Robot();
        } catch (AWTException ex) {
            ex.printStackTrace();
        }
        final JToolBar toolBar = new JToolBar();
        for (int i = 0; i < 3; i++) {
            toolBar.add(new JButton("" + i));
        }
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);
        frame.add(toolBar, BorderLayout.NORTH);

        final ComponentListener dialogListener = new ComponentAdapter() {

            @Override
            public void componentMoved(ComponentEvent e) {
                dialog = (JDialog) e.getSource();
                setLocations(false);
            }
        };
        toolBar.addHierarchyListener(new HierarchyListener() {

            @Override
            public void hierarchyChanged(HierarchyEvent e) {
                Window window = SwingUtilities.getWindowAncestor(toolBar);
                if (window instanceof JDialog) {
                    boolean listenerAdded = false;
                    for (ComponentListener listener : window.getComponentListeners()) {
                        if (listener == dialogListener) {
                            listenerAdded = true;
                            break;
                        }
                    }
                    if (!listenerAdded) {
                        window.addComponentListener(dialogListener);
                    }
                }
            }
        });
        frame.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentMoved(ComponentEvent e) {
                if (dialog != null && dialog.isShowing()) {
                    setLocations(true);
                }
            }
        });
        frame.setVisible(true);
    }

    private void setLocations(boolean moveDialog) {
        int dialogX = dialog.getX();
        int dialogY = dialog.getY();
        int dialogW = dialog.getWidth();
        int dialogH = dialog.getHeight();
        int frameX = frame.getX();
        int frameY = frame.getY();
        int frameW = frame.getWidth();
        int frameH = frame.getHeight();
        boolean needToMove = false;
        if (dialogX < frameX) {
            dialogX = frameX;
            needToMove = true;
        }
        if (dialogY < frameY) {
            dialogY = frameY;
            needToMove = true;
        }
        if (dialogX + dialogW > frameX + frameW) {
            dialogX = frameX + frameW - dialogW;
            needToMove = true;
        }
        if (dialogY + dialogH > frameY + frameH) {
            dialogY = frameY + frameH - dialogH;
            needToMove = true;
        }
        if (needToMove) {
            if (!moveDialog && robot != null) {
                robot.mouseRelease(InputEvent.BUTTON1_MASK);
            }
            dialog.setLocation(dialogX, dialogY);
        }
    }
}

这不是最优雅的解决方案,但它确实有效。

public class Example extends JFrame {

    BasicToolBarUI ui;

    Example() {

        JToolBar tb = new JToolBar();
        tb.add(new JButton("AAAAA"));
        tb.setBackground(Color.GREEN);
        ui = (BasicToolBarUI) tb.getUI();

        getContentPane().addContainerListener(new Listener());
        getContentPane().add(tb, BorderLayout.PAGE_START);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(300, 300);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    class Listener implements ContainerListener {

        @Override
        public void componentAdded(ContainerEvent e) {}

        @Override
        public void componentRemoved(ContainerEvent e) {

            if (ui.isFloating()) {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {

                        ui.setFloating(false, null);
                    }
                }); 
            }
        }
    }

    public static void main(String[] args) {

        new Example();
    }
}

解释:

每当工具栏移动到浮动状态时,都会指示不要这样做。唯一的问题是你必须等待 EDT 完成创建浮动 window 的过程,然后你才能告诉它不要浮动。结果是您实际上看到 window 创建然后隐藏。

注:

我认为重写工具栏的 UI 是一个更好的解决方案,尽管使用更复杂的方法执行与我所做的类似的事情也可能会很好。