实现边框组件调整大小器偏移



在为我的窗口框架使用 WebLookAndFeel UI 时,我查找了一种调整未修饰框架大小的方法。幸运的是,找到了该解决方案:拖动和调整未修饰的 JFrame 的大小

但是,在使用组件调整器代码时,我遇到了边界检测问题。调整大小检测到稍微超出了我的应用程序的视觉边界。使用Windows的截图工具,我通过将模式设置为窗口截图模式来确认我的怀疑,您可以在此处看到。我的框架的实际边框延伸到典型用户会看到的视觉部分之外,因为为框架渲染了柔和阴影。

如何在组件调整器代码中实现偏移量,以便在视觉边框上检测光标,而不是在外观上的柔和阴影边框上检测?我尝试过使用插图和更改内部值,但没有骰子。任何帮助,不胜感激。

在自己重新创建类以便我了解代码的工作原理后,我在那里实现了偏移量。请注意,我只测试过负偏移量,但它似乎工作正常。我还更改了安装侦听器和变量进行控制的方式,例如 zone,它所做的只是在决定要使用的光标之前检查偏移行的一半和偏移行中的一半。因此,区域 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;
    }
}

最新更新