Поменять местами JPanels в массиве JPanels

Я могу поменять местами панели, но этого недостаточно. Например, если панель1 сталкивается с панелью2, она меняется местами, но если та же самая панель сталкивается с панелью3, панель3 также перемещается в расположение панели1 (чего я не хочу). Если есть около 10 панелей, и если я хочу поменять местами панель1 с панелью10, это невозможно с текущей логикой. Может кто-нибудь, пожалуйста, помогите мне.

Ниже приведен код с приведенной выше логикой:

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

public class GDragAndDrop extends JFrame {
   public GDragAndDrop() {
      add(new op());
   }

   public static void main(String[] args) {
      GDragAndDrop frame = new GDragAndDrop();
      frame.setTitle("GDragAndDrop");
      frame.setSize(600, 600);
      frame.setLocationRelativeTo(null);// Center the frame
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
   }
}

class op extends JPanel implements MouseListener, MouseMotionListener {
   JPanel p;
   Point pPoint;
   Point p1;
   Point p2;
   MouseEvent pressed;
   JPanel[] panels = new JPanel[3];

   public op() {
      int b = 3;
      int a = 0;
      for (int i = 0; i < b; i++) {
         panels[i] = new JPanel();
         panels[i].setBackground(Color.cyan);
         panels[i].setBorder(new LineBorder(Color.black));
         a = a + 20;
         panels[i].setPreferredSize(new Dimension(a, 400));
         panels[i].addMouseListener(this);
         panels[i].addMouseMotionListener(this);
         panels[i].setBorder(new LineBorder(Color.black));
         panels[i].setVisible(true);
         panels[i].add("Center", new JLabel("To Move" + i));
         this.add(panels[i]);
      }
   }

   public JPanel getPanelColliding(JPanel dragPanel) {
      Rectangle rDrag = dragPanel.getBounds();
      for (int i = 0; i < 3; i++) {
         if (panels[i] == dragPanel)
            continue;
         Rectangle r = panels[i].getBounds();
         if (r.intersects(rDrag)) {
            return panels[i];
         }
      }
      return null;
   }

   public void mousePressed(MouseEvent e) {
      int b = 3;
      for (int i = 0; i < b; i++) {
         if (e.getSource() == panels[i]) {
            pressed = e;
            p2 = panels[i].getLocation();
         }
      }
   }

   @Override
   public void mouseDragged(MouseEvent arg0) {
      int b = 3;
      for (int i = 0; i < b; i++) {
         if (arg0.getSource() == panels[i]) {
            pPoint = panels[i].getLocation(pPoint);
            int x = pPoint.x - pressed.getX() + arg0.getX();
            int y = pPoint.y - pressed.getY() + arg0.getY();
            if (getPanelColliding(panels[i]) != null) {
               JPanel DragP = new JPanel();
               DragP = getPanelColliding(panels[i]);
               p1 = getPanelColliding(panels[i]).getLocation(p1);
               int x1 = pPoint.x - pressed.getX() + arg0.getX();
               int y1 = pPoint.y - pressed.getY() + arg0.getY();
               panels[i].setLocation(x1, y1);
               DragP.setLocation(p2);
            } else
               panels[i].setLocation(x, y);
         }
      }
   }

   @Override
   public void mouseClicked(MouseEvent e) {
   }

   @Override
   public void mouseReleased(MouseEvent e) {
   }

   @Override
   public void mouseEntered(MouseEvent e) {
   }

   @Override
   public void mouseExited(MouseEvent e) {
   }

   @Override
   public void mouseMoved(MouseEvent e) {
   }
}

person Rookie86    schedule 25.08.2013    source источник
comment
Это возможный дубликат вашего другого очень похожего вопроса Как поменять местами JPanel, когда он сталкивается с другим JPanel. Пожалуйста, объясните: чем отличаются эти вопросы? Почему этот вопрос не должен быть закрыт как дубликат?   -  person Hovercraft Full Of Eels    schedule 25.08.2013
comment
Я закрыл предыдущий вопрос сейчас. Пожалуйста, помогите мне с этим вопросом. Спасибо Hovercraft Full of Eels за присмотр.   -  person Rookie86    schedule 25.08.2013


Ответы (2)


Если вы не хотите использовать перетаскивание и если ваши панели JPanel расположены в столбцах, рассмотрите следующие предложения:

  • Я заставил это работать, когда контейнер JPanel (тот, который содержит несколько компонентов столбца) использует FlowLayout
  • Я добавил MouseAdapter в качестве MouseListener и MouseMotionListener в контейнер JPanel, а не в компоненты столбца.
  • Я получил выбранный компонент столбца, вызвав getComponentAt(mouseEvent.getPoint()) в контейнере JPanel. Конечно, проверьте, что это не ноль.
  • Если выбранный компонент не равен нулю, то я устанавливаю переменную selectedComponent с этим компонентом и помещаю на его место заполнитель JLabel с тем же предпочтительным размером. Я делаю это, удаляя все компоненты из контейнера JPanel, а затем повторно добавляя их все обратно, за исключением выбранного компонента, где вместо этого я добавляю заполнитель JLabel. Затем я вызываю revalidate и перекрашиваю контейнер.
  • Чтобы перетащить выбранный компонент, поднимите его на стеклянную панель (т. е. добавьте его в стеклянную панель).
  • сделать стеклянную панель видимой и присвоить ей нулевой макет.
  • Перетащите выбранный компонент в GlassPane, просто изменив его положение относительно GlassPane.
  • В mouseReleased узнайте, над каким компонентом столбца находится мышь, снова используя getComponentAt(...).
  • Затем удалите все компоненты из контейнера JPanel,
  • а затем добавить их обратно в нужном порядке.
  • Затем снова вызовите revalidate и перерисуйте контейнер JPanel. <час>

Например:

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.*;

public class SwapPanelEg extends JPanel {
   private static final long serialVersionUID = 1594039652438249918L;
   private static final int PREF_W = 400;
   private static final int PREF_H = 400;
   private static final int MAX_COLUMN_PANELS = 8;
   private JPanel columnPanelsHolder = new JPanel();

   public SwapPanelEg() {
      columnPanelsHolder.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

      for (int i = 0; i < MAX_COLUMN_PANELS; i++) {
         int number = i + 1;
         int width = 20 + i * 3;
         int height = PREF_H - 30;
         columnPanelsHolder.add(new ColumnPanel(number, width, height));
      }

      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      columnPanelsHolder.addMouseListener(myMouseAdapter);
      columnPanelsHolder.addMouseMotionListener(myMouseAdapter);

      setLayout(new GridBagLayout());
      add(columnPanelsHolder);
   }

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

   private class MyMouseAdapter extends MouseAdapter {
      private JComponent selectedPanel;
      private Point deltaLocation;
      private JLabel placeHolder = new JLabel();
      private JComponent glassPane;

      @Override
      public void mousePressed(MouseEvent evt) {
         if (evt.getButton() != MouseEvent.BUTTON1) {
            return;
         }
         JPanel source = (JPanel) evt.getSource();
         selectedPanel = (JComponent) source.getComponentAt(evt.getPoint());

         if (selectedPanel == null) {
            return;
         }

         if (selectedPanel == source) {
            selectedPanel = null;
            return;
         }

         glassPane = (JComponent) SwingUtilities.getRootPane(source).getGlassPane();
         glassPane.setVisible(true);
         Point glassPaneOnScreen = glassPane.getLocationOnScreen();
         glassPane.setLayout(null);
         Point ptOnScreen = evt.getLocationOnScreen();
         Point panelLocOnScreen = selectedPanel.getLocationOnScreen();

         int deltaX = ptOnScreen.x + glassPaneOnScreen.x - panelLocOnScreen.x;
         int deltaY = ptOnScreen.y + glassPaneOnScreen.y - panelLocOnScreen.y;

         deltaLocation = new Point(deltaX, deltaY);

         Component[] allComps = source.getComponents();
         for (Component component : allComps) {
            source.remove(component);
            if (component == selectedPanel) {
               placeHolder.setPreferredSize(selectedPanel.getPreferredSize());
               source.add(placeHolder);
               selectedPanel.setSize(selectedPanel.getPreferredSize());
               int x = ptOnScreen.x - deltaLocation.x;
               int y = ptOnScreen.y - deltaLocation.y;
               selectedPanel.setLocation(x, y);
               glassPane.add(selectedPanel);
            } else {
               source.add(component);
            }
         }
         revalidate();
         repaint();

      }

      @Override
      public void mouseDragged(MouseEvent evt) {
         if (selectedPanel != null) {
            Point ptOnScreen = evt.getLocationOnScreen();

            int x = ptOnScreen.x - deltaLocation.x;
            int y = ptOnScreen.y - deltaLocation.y;
            selectedPanel.setLocation(x, y);
            repaint();
         }
      }

      @Override
      public void mouseReleased(MouseEvent evt) {
         if (evt.getButton() != MouseEvent.BUTTON1) {
            return;
         }
         if (selectedPanel == null) {
            return;
         }

         JComponent source = (JComponent) evt.getSource();

         Component[] allComps = source.getComponents();
         Component overComponent = (JComponent) source.getComponentAt(evt
               .getPoint());

         source.removeAll();

         if (overComponent != null && overComponent != placeHolder
               && overComponent != source) {
            for (Component component : allComps) {
               if (component == placeHolder) {
                  source.add(overComponent);
               } else if (component == overComponent) {
                  source.add(selectedPanel);
               } else {
                  source.add(component);
               }
            }
         } else {
            for (Component component : allComps) {
               if (component == placeHolder) {
                  source.add(selectedPanel);
               } else {
                  source.add(component);
               }
            }
         }
         revalidate();
         repaint();
         selectedPanel = null;
      }
   }

   private static void createAndShowGui() {
      SwapPanelEg mainPanel = new SwapPanelEg();

      JFrame frame = new JFrame("SwapPanelEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class ColumnPanel extends JPanel {
   private static final long serialVersionUID = 5366233209639059032L;
   private int number;
   private int prefWidth;
   private int prefHeight;

   public ColumnPanel(int number, int prefWidth, int prefHeight) {
      setName("ColumnPanel " + number);
      this.number = number;
      this.prefWidth = prefWidth;
      this.prefHeight = prefHeight;

      add(new JLabel(String.valueOf(number)));
      setBorder(BorderFactory.createLineBorder(Color.black));
      setBackground(Color.cyan);
   }

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

   public int getNumber() {
      return number;
   }

}
person Hovercraft Full Of Eels    schedule 25.08.2013
comment
Большое спасибо Hovercraft-full-of-eels, это именно то, что мне было нужно. Я долго мучился с этой частью. - person Rookie86; 26.08.2013

Если вы не хотите использовать Swing, перетащите, поменяйте местами содержимое источника и места назначения, как показано в этом JLayeredPane примере и вариант.

person trashgod    schedule 25.08.2013