JLabels, в которых хранятся ImageIcons, возвращаются в исходное положение при щелчке мышью на панели.

Я добавил этот слушатель в JLabel, и я могу отлично перетаскивать изображение. Однако, как только я нажимаю на панель (в области, где нет JLabel), метка возвращается в исходное местоположение . Я не могу понять, почему это произошло. Пожалуйста, помогите мне, я потратил несколько часов, работая над этим. Спасибо!

public class CardLabelListener extends MouseAdapter {

    private MouseEvent initiateEvent = null;

    @Override
    public void mouseReleased(MouseEvent me) {
        System.err.println("mouse release");
        int dx = me.getX() - initiateEvent.getX();
        int dy = me.getY() - initiateEvent.getY();
        if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
            Rectangle oldBound = me.getComponent().getBounds();
            int newX = oldBound.x + dx;
            int newY = oldBound.y + dy;
            me.getComponent().setBounds(newX, newY, oldBound.width, oldBound.height);
        }
        initiateEvent = null;
    }

    public void mousePressed(MouseEvent me) {
        GreetingCard.setBackground.findComponentAt(me.getX(), me.getY());
        System.err.println("mouse pressed");
        initiateEvent = me;
        me.consume();
    }

    public void mouseDragged(MouseEvent me) {
        System.err.println(me.getSource());
        if (initiateEvent == null) return;

        me.consume();
        JComponent jc = (JComponent) me.getSource();
        TransferHandler handler = jc.getTransferHandler();
        handler.exportAsDrag(jc, me, TransferHandler.MOVE);

        initiateEvent = null;
    }
}

person zoy.khan    schedule 30.10.2012    source источник


Ответы (2)


Во-первых, вы перетаскиваете не иконку, а сам компонент.

Во-вторых, вы боретесь с менеджером компоновки, который содержит компонент метки. Когда панель становится недействительной, метки возвращаются в исходное положение макета.

Попытка использовать что-то вроде JLayeredPane для размещения ваших меток

ОБНОВЛЕНО с примером, основанным на отзывах

public class MoveMe {

    public static void main(String[] args) {
        new MoveMe();
    }

    public MoveMe() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new MoveMePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MoveMePane extends JLayeredPane {

        public MoveMePane() {
            int width = 400;
            int height = 400;
            for (int index = 0; index < 10; index++) {
                String text = "Label " + index;
                JLabel label = new JLabel(text);
                label.setSize(label.getPreferredSize());

                int x = (int) Math.round(Math.random() * width);
                int y = (int) Math.round(Math.random() * height);
                if (x + label.getWidth() > width) {
                    x = width - label.getWidth();
                }
                if (y + label.getHeight() > width) {
                    y = width - label.getHeight();
                }
                label.setLocation(x, y);
                add(label);
            }

            MoveMeMouseHandler handler = new MoveMeMouseHandler();
            addMouseListener(handler);
            addMouseMotionListener(handler);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }
    }

    public class MoveMeMouseHandler extends MouseAdapter {

        private int xOffset;
        private int yOffset;
        private JLabel draggy;
        private String oldText;

        @Override
        public void mouseReleased(MouseEvent me) {
            if (draggy != null) {
                draggy.setText(oldText);
                draggy.setSize(draggy.getPreferredSize());
                draggy = null;
            }
        }

        public void mousePressed(MouseEvent me) {
            JComponent comp = (JComponent) me.getComponent();
            Component child = comp.findComponentAt(me.getPoint());
            if (child instanceof JLabel) {
                xOffset = me.getX() - child.getX();
                yOffset = me.getY() - child.getY();

                draggy = (JLabel) child;
                oldText = draggy.getText();
                draggy.setText("What a drag");
                draggy.setSize(draggy.getPreferredSize());
            }
        }

        public void mouseDragged(MouseEvent me) {
            if (draggy != null) {
                draggy.setLocation(me.getX() - xOffset, me.getY() - yOffset);
            }
        }
    }
}
person MadProgrammer    schedule 30.10.2012
comment
Макет этой панели имеет значение Null, и это JTabbedPane. Все мои компоненты (JLabel, которые будут перемещены) находятся на этой JTabbedPane, на первой вкладке. - person zoy.khan; 30.10.2012
comment
Эту информацию было бы полезно знать заранее ;). В событии mouseDragged я не думаю, что необходимо экспортировать через API передачи. Просто установите новое местоположение компонентов относительно точки, в которой они были нажаты. Я предполагаю, что прослушиватель мыши находится на панели перетаскивания, а не на отдельных ярлыках. - person MadProgrammer; 30.10.2012
comment
Это помогло, мне было интересно, можете ли вы помочь мне здесь: -jlabel" title="сложность изменения размера изображения, хранящегося в jlabel">stackoverflow.com/questions/13149624/ - person zoy.khan; 31.10.2012

Чтобы это работало, вам нужно использовать макет null в контейнере, где находится JLabel, иначе позиция будет сброшена до той, где текущий менеджер компоновки размещает метку.

Лучше использовать DragLayout.

DragLayout был разработан для замены нулевого макета. Он будет учитывать расположение компонента. По умолчанию он будет использовать предпочтительный размер компонента для определения его размера. Наконец, он автоматически рассчитает предпочтительный размер контейнера.

person Reimeus    schedule 30.10.2012
comment
Или JDesktopPane или JLayerdPane - person MadProgrammer; 30.10.2012
comment
Привет, у меня уже есть макет, установленный на ноль. rightPanel = новая JTabbedPane(); rightPanel.setLayout(null); // и добавить мои компоненты на первую вкладку панели с вкладками - person zoy.khan; 30.10.2012
comment
Вы, ребята, лучшие! Я устанавливаю для макета значение Null каждый раз, когда использую его, и моя проблема решена. Несмотря на то, что я явно установил его равным нулю в одном месте, в других местах он не был установлен равным нулю. Спасибо. - person zoy.khan; 30.10.2012
comment
@ user1784190, тогда не забудьте проголосовать и принять правильный ответ - person mKorbel; 31.10.2012
comment
stackoverflow.com/questions/13149624/ - person zoy.khan; 31.10.2012