实现Border ComponentResizer Offset

时间:2014-11-23 19:02:26

标签: java mouseevent look-and-feel

在我的窗口框架中使用WebLookAndFeel UI时,我查找了一种调整未修饰框架大小的方法。幸运的是,找到了解决方案: Drag and Resize undecorated JFrame

但是,在使用Component Resizer代码时,我遇到了边框检测问题。调整大小是检测到我的应用程序的视觉边界之外的一点。使用Windows的剪切工具我通过将模式设置为Window Snip模式确认了我的怀疑,您可以看到here。我的框架的实际边框延伸超过典型用户可见的视觉部分,因为为框架渲染了柔和的阴影。

如何在Component Resizer代码中实现偏移,以便在视觉边框上检测光标而不是外观的柔和阴影边框?我尝试过使用插图并改变内部价值,但没有骰子。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

在自己重新创建类之后,我就能理解代码是如何工作的,我在那里实现了偏移。请注意,我只测试了负偏移,但似乎工作正常。我还改变了如何安装要控制的侦听器和变量,如区域,它所做的只是在决定要使用的游标之前检查一半的偏移量和一半的偏移量。因此,区域7将使光标检查3在外部,3在内部。

public class CustomResizer extends MouseAdapter
{
    protected final static Map<Component, CustomResizer> instance = new HashMap<Component, CustomResizer>();
    protected final static Map<Integer, Integer> cursors = new HashMap<Integer, Integer>();
    {
        cursors.put(1, Cursor.N_RESIZE_CURSOR);
        cursors.put(2, Cursor.W_RESIZE_CURSOR);
        cursors.put(4, Cursor.S_RESIZE_CURSOR);
        cursors.put(8, Cursor.E_RESIZE_CURSOR);
        cursors.put(3, Cursor.NW_RESIZE_CURSOR);
        cursors.put(9, Cursor.NE_RESIZE_CURSOR);
        cursors.put(6, Cursor.SW_RESIZE_CURSOR);
        cursors.put(12, Cursor.SE_RESIZE_CURSOR);
    }

    public static CustomResizer install(Component component)
    {
        if(instance.containsKey(component))
        {
            CustomResizer.uninstall(component);
        }
        CustomResizer crInstance = new CustomResizer();
        component.addMouseMotionListener(crInstance);
        component.addMouseListener(crInstance);
        instance.put(component, crInstance);
        return crInstance;
    }

    public static void uninstall(Component component)
    {
        CustomResizer crInstance = instance.get(component);
        instance.remove(component);
        component.removeMouseListener(crInstance);
        component.removeMouseMotionListener(crInstance);
    }

    public static CustomResizer getInstance(Component component)
    {
        return instance.get(component);
    }

    protected final static int NORTH = 1;
    protected final static int WEST = 2;
    protected final static int SOUTH = 4;
    protected final static int EAST = 8;

    private int zone = 7 / 2;
    private int offset = 0;

    private Point pressed;
    private int direction;
    private Rectangle bounds;
    private boolean resizing;
    private boolean autoscrolls;
    private Cursor originalCursor;

    @Override
    public void mouseEntered(MouseEvent e)
    {
        originalCursor = !(resizing) ? e.getComponent().getCursor() : originalCursor;
    }

    @Override
    public void mouseExited(MouseEvent e)
    {
        Component source = e.getComponent();
        source.setCursor(!(resizing) ? originalCursor : source.getCursor());
    }

    @Override
    public void mousePressed(MouseEvent e)
    {
        if(direction != 0)
        {
            resizing = true;

            pressed = e.getPoint();
            Component source = e.getComponent();
            SwingUtilities.convertPointToScreen(pressed, source);
            bounds = source.getBounds();

            if(source instanceof JComponent)
            {
                JComponent jc = (JComponent) source;
                autoscrolls = jc.getAutoscrolls();
                jc.setAutoscrolls(false);
            }
        }
    }

    @Override
    public void mouseDragged(MouseEvent e)
    {
        if(resizing)
        {
            Component source = e.getComponent();
            Point dragged = e.getPoint();
            SwingUtilities.convertPointToScreen(dragged, source);

            int x = bounds.x;
            int y = bounds.y;
            int width = bounds.width;
            int height = bounds.height;
            Dimension maximumSize = source.getMaximumSize();
            Dimension minimumSize = source.getMinimumSize();

            if(WEST == (direction & WEST))
            {
                int drag = getDragDistance(pressed.x, dragged.x);
                drag = getDragBounded(drag, width, minimumSize.width, Math.min(width + x - offset, maximumSize.width));

                x -= drag;
                width += drag;
            }
            if(NORTH == (direction & NORTH))
            {
                int drag = getDragDistance(pressed.y, dragged.y);
                drag = getDragBounded(drag, height, minimumSize.height, Math.min(height + y - offset, maximumSize.height));

                y -= drag;
                height += drag;
            }
            if(EAST == (direction & EAST))
            {
                int drag = getDragDistance(dragged.x, pressed.x);
                drag = getDragBounded(drag, width, minimumSize.width, Math.min(getBoundingSize(source).width - x, maximumSize.width));

                width += drag;
            }
            if(SOUTH == (direction & SOUTH))
            {
                int drag = getDragDistance(dragged.y, pressed.y);
                drag = getDragBounded(drag, height, minimumSize.height, Math.min(getBoundingSize(source).height - y, maximumSize.height));

                height += drag;
            }

            source.setBounds(x, y, width, height);
        }
    }

    @Override
    public void mouseMoved(MouseEvent e)
    {
        Component source = e.getComponent();
        direction = 0;

        Point location = e.getPoint();
        int x = location.x;
        int y = location.y;
        int widthOffset = source.getWidth() + offset;
        int heightOffset = source.getHeight() + offset;

        if(x < -offset + zone && x > -offset - zone) direction += WEST;
        if(x > widthOffset - zone && x < widthOffset + zone) direction += EAST;
        if(y < -offset + zone && y > -offset - zone) direction += NORTH;
        if(y > heightOffset - zone && y < heightOffset + zone) direction += SOUTH;

        source.setCursor(direction == 0 ? originalCursor : Cursor.getPredefinedCursor(cursors.get(direction)));
    }

    @Override
    public void mouseReleased(MouseEvent e)
    {
        resizing = false;

        Component source = e.getComponent();
        source.setCursor(originalCursor);

        if(source instanceof JComponent)
        {
            ((JComponent) source).setAutoscrolls(autoscrolls);
        }
    }

    private int getDragDistance(int larger, int smaller)
    {
        int drag = larger - smaller;
        drag += (drag < 0) ? -1 : 1;
        return drag;
    }

    private int getDragBounded(int drag, int dimension, int minimum, int maximum)
    {
        while(dimension + drag < minimum) drag += 1;
        while(dimension + drag > maximum) drag -= 1;
        return drag;
    }

    private Dimension getBoundingSize(Component source)
    {
        if(source instanceof Window)
        {
            Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
            return new Dimension(bounds.width - offset, bounds.height - offset);
        }
        else
        {
            Dimension size = source.getParent().getSize();
            return new Dimension(size.width - offset, size.height - offset);
        }
    }

    public void setOffset(int offset)
    {
        this.offset = offset;
    }

    public int getOffset()
    {
        return offset;
    }

    public void setZone(int zone)
    {
        this.zone = zone / 2;
    }

    public int getZone()
    {
        return zone;
    }
}