Создание перетаскиваемого и изменяемого размера компонента в Java

Как создать компонент, который можно перетаскивать и изменять размер в Java Swing?

Как и функция "Текстовые поля" в MS Paint, выделенная красной рамкой на изображении.

Я только хочу перетащить и изменить размер объекта, а не форматирование текста.

Как я могу реализовать этот компонент с помощью Java Swing?

Компонент выделен красной рамкой

2 ответа

В своем стремлении решить эту проблему я обнаружил библиотеку Piccolo2d ZUI.

Это именно то, что я искал! Тем не менее, это может быть не лучшим подходом для реализации "Draggable & Resizable Text Box", но я получил его за час с помощью Piccolo2d. Итак, я выкладываю код здесь, если кто-то может найти его полезным.

Вот скриншот примера приложения!Draggable & Resizable Box, используя Piccolo2d

Я попытался сделать код максимально описываемым, поэтому он немного длинный.

Вам потребуется piccolo2d-core-XXX.jar & piccolo2d-extras-XXX.jar запустить этот код, который можно загрузить из Центрального репозитория Maven. Я использовал версию 3.0 и не тестировал ни с какой другой версией!

Класс пользовательских компонентов

class PBox extends PNode {

    private PCanvas canvas;

    private Rectangle2D rectangle;

    private Cursor moveCursor;

    public PBox(PCanvas canvas) {           
        this(0, 0, 50, 50, canvas);         
    }

    public PBox(double x, double y, double width, double height, PCanvas canvas) {
        this.canvas = canvas;
        rectangle = new Rectangle2D.Double();
        moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);

        addAnchors(x, y, width, height);
        setBounds(x, y, width, height);
        setInputEventListener();
    }

    private void addAnchors(double x, double y, double width, double height) {
        addChild(new Anchor(SwingConstants.NORTH));
        addChild(new Anchor(SwingConstants.NORTH_EAST));
        addChild(new Anchor(SwingConstants.EAST));
        addChild(new Anchor(SwingConstants.SOUTH_EAST));
        addChild(new Anchor(SwingConstants.SOUTH));
        addChild(new Anchor(SwingConstants.SOUTH_WEST));
        addChild(new Anchor(SwingConstants.WEST));
        addChild(new Anchor(SwingConstants.NORTH_WEST));
    }

    private void setInputEventListener() {
        addInputEventListener(new PBasicInputEventHandler() {

            @Override
            public void mouseEntered(PInputEvent event) {
                canvas.setCursor(moveCursor);
            }

            @Override
            public void mouseExited(PInputEvent event) {
                canvas.setCursor(Cursor.getDefaultCursor());
            }

            @Override
            public void mouseDragged(PInputEvent event) {
                PDimension delta = event.getDeltaRelativeTo(PBox.this);
                translate(delta.width, delta.height);
                event.setHandled(true);
            }

        });
    }

    @Override
    protected void layoutChildren() {
        Iterator iterator = getChildrenIterator();
        int position = SwingConstants.NORTH;
        while (iterator.hasNext()) {
            PNode anchor = (PNode) iterator.next();
            anchor.setBounds(getAnchorBounds(position));
            ++position;
        }
    }

    private Rectangle2D getAnchorBounds(int position) {             
        double x = 0, y = 0;
        Rectangle2D b = getBounds();

        switch (position) {                 
        case SwingConstants.NORTH:
            x = b.getX()+b.getWidth()/2;
            y = b.getY();
            break;

        case SwingConstants.NORTH_EAST:
            x = b.getX()+b.getWidth();
            y = b.getY();
            break;

        case SwingConstants.EAST:
            x = b.getX()+b.getWidth();
            y = b.getY()+b.getHeight()/2;
            break;

        case SwingConstants.SOUTH_EAST:
            x = b.getX()+b.getWidth();
            y = b.getY()+b.getHeight();
            break;

        case SwingConstants.SOUTH:
            x = b.getX()+b.getWidth()/2;
            y = b.getY()+b.getHeight();
            break;

        case SwingConstants.SOUTH_WEST:
            x = b.getX();
            y = b.getY()+b.getHeight();
            break;  

        case SwingConstants.WEST:
            x = b.getX();
            y = b.getY()+b.getHeight()/2;
            break;              

        case SwingConstants.NORTH_WEST:
            x = b.getX();
            y = b.getY();
            break;
        }

        return new Rectangle2D.Double(x-2, y-2, 4, 4);
    }

    @Override
    public boolean setBounds(double x, double y, double width, double height) {
        if (super.setBounds(x, y, width, height)) {
            rectangle.setFrame(x, y, width, height);
            return true;
        }
        return false;
    }

    @Override
    public boolean intersects(Rectangle2D localBounds) {
        return rectangle.intersects(localBounds);
    }

    @Override
    protected void paint(PPaintContext paintContext) {
        Graphics2D g2 = paintContext.getGraphics();
        g2.setPaint(Color.BLACK);
        g2.setStroke(new BasicStroke(1.0f,
                BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_MITER,
                1.0f, new float[]{4.0f}, 0));
        g2.draw(rectangle);
    }

    class Anchor extends PNode {

        private Rectangle2D point;

        private Cursor resizeCursor;

        Anchor(int position) {
            point = new Rectangle2D.Double();
            setCursor(position);
            setInputEventListener(position);
        }

        private void setCursor(int position) {
            switch (position) {                 
            case SwingConstants.NORTH:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
                break;

            case SwingConstants.NORTH_EAST:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR);
                break;

            case SwingConstants.EAST:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
                break;

            case SwingConstants.SOUTH_EAST:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
                break;

            case SwingConstants.SOUTH:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
                break;

            case SwingConstants.SOUTH_WEST:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR);
                break;  

            case SwingConstants.WEST:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
                break;              

            case SwingConstants.NORTH_WEST:
                resizeCursor = Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR);
                break;

            default:
                resizeCursor = Cursor.getDefaultCursor();
            }
        }

        private void setInputEventListener(final int position) {
            addInputEventListener(new PBasicInputEventHandler() {

                @Override
                public void mouseEntered(PInputEvent event) {
                    canvas.setCursor(resizeCursor);
                    event.setHandled(true);
                }

                @Override
                public void mouseExited(PInputEvent event) {
                    canvas.setCursor(Cursor.getDefaultCursor());
                    event.setHandled(true);
                }

                @Override
                public void mouseDragged(PInputEvent event) {
                    PDimension delta = event.getDeltaRelativeTo(Anchor.this);
                    PNode parent = getParent();

                    if (position == SwingConstants.EAST
                            || position == SwingConstants.NORTH_EAST
                            || position == SwingConstants.SOUTH_EAST) {
                        parent.setWidth(parent.getWidth() + delta.width);
                    } else if (position == SwingConstants.WEST
                            || position == SwingConstants.NORTH_WEST
                            || position == SwingConstants.SOUTH_WEST) {
                        parent.setX(parent.getX() + delta.width);
                        parent.setWidth(parent.getWidth() - delta.width);
                    }

                    if (position == SwingConstants.SOUTH
                            || position == SwingConstants.SOUTH_EAST
                            || position == SwingConstants.SOUTH_WEST) {
                        parent.setHeight(parent.getHeight() + delta.height);
                    } else if (position == SwingConstants.NORTH
                            || position == SwingConstants.NORTH_EAST
                            || position == SwingConstants.NORTH_WEST) {
                        parent.setY(parent.getY() + delta.height);
                        parent.setHeight(parent.getHeight() - delta.height);
                    }

                    event.setHandled(true);
                }

            });
        }

        @Override
        public boolean setBounds(double x, double y, double width, double height) {
            if (super.setBounds(x, y, width, height)) {
                point.setFrame(x, y, width, height);
                return true;
            }
            return false;
        }

        @Override
        public boolean intersects(Rectangle2D localBounds) {
            return point.intersects(localBounds);
        }

        @Override
        protected void paint(PPaintContext paintContext) {
            Graphics2D g2 = paintContext.getGraphics();
            g2.setColor(Color.WHITE);
            g2.fill(point);
            g2.setStroke(new BasicStroke(1.0f));
            g2.setColor(Color.BLACK);
            g2.draw(point);
        }

    }

}

И основной класс

public class Piccolo2DExample extends PFrame {

    @Override
    public void initialize() {
        PCanvas canvas = getCanvas();

        PNode text = new PText("Draggable & Resizable Box using Piccolo2d");
        text.scale(2.0);
        canvas.getCamera().addChild(text);

        PLayer layer = canvas.getLayer();

        PNode aLayerNode = new PText("A_Layer_Node");
        aLayerNode.setOffset(10, 50);
        layer.addChild(aLayerNode);

        // Adding the component to layer
        layer.addChild(new PBox(50, 100, 250, 50, canvas));
    }

    public static void main(String[] args) {
        PFrame frame = new Piccolo2DExample();
        frame.setSize(800, 640);
    }

}

Это не должно быть трудно сделать это самостоятельно. Просто добавьте слушателя мыши и слушателя движения мыши к компоненту. Создайте переменные int lastMouseX, lastMouseY, mode; а также логическая мышь Press. Установите lastMouseX и lastMouseY в событиях mouseMoved и mouseDragged. В слушателе мыши на нажатие мыши проверьте, что должно быть сделано (то есть изменение размера или перемещение) в зависимости от положения мыши. Установите для этого режим (т. Е. 1 при перетаскивании и 2 при изменении размера). И после этого в обработчике движения мыши в mouseDragged просто вычислите смещение мыши относительно последней позиции мыши и сделайте соответствующие вещи. Если вы будете бороться после моего объяснения, я выложу некоторый код.

Другие вопросы по тегам