2

我可以交换面板,但还不够好。例如,如果面板 1 与面板 2 发生碰撞,它会交换,但如果面板 3 发生相同的碰撞,面板 3 也会移动到面板 1 的位置(我不想发生这种情况)。如果大约有 10 个面板,并且如果我想将 panel1 与 panel10 交换,那么当前逻辑是不可能的。谁能帮帮我。

以下是具有上述逻辑的代码:

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) {
   }
}
4

2 回答 2

2

如果您不想使用拖放,并且您的 JPanel 在列中,请考虑以下建议:

  • 我已经让容器 JPanel(包含多个列组件的容器)使用 FlowLayout 来工作
  • 我已将 MouseAdapter 作为 MouseListener 和 MouseMotionListener 添加到容器 JPanel,而不是列组件。
  • 我通过调用getComponentAt(mouseEvent.getPoint())容器 JPanel 获得了选定的列组件。当然检查它是否不为空。
  • 如果所选组件不为空,则我为该组件设置一个 selectedComponent 变量,并在其位置放置一个具有相同 preferredSize 的占位符 JLabel。我通过从容器 JPanel 中删除所有组件来执行此操作,然后将它们全部重新添加回来,除了我添加占位符 JLabel 的选定组件。然后我在容器上调用 revalidate 和 repaint。
  • 要拖动选定的组件,请将其提升到 glassPane(即,将其添加到 glassPane)。
  • 使 glassPane 可见并给它一个空布局。
  • 只需更改其相对于 glassPane 的位置,即可在 glassPane 中拖动所选组件。
  • 在 mouseReleased 上,再次使用 .找出鼠标在哪个列组件上getComponentAt(...)
  • 然后从容器JPanel中移除所有组件,
  • 然后以所需的顺序将它们全部添加回来。
  • 然后再次调用容器 JPanel 上的 revalidate 和 repaint。

例如:

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;
   }

}
于 2013-08-25T17:00:00.030 回答
2

如果您不想使用 Swing拖放,请交换源和目标的内容,如本JLayeredPane 示例变体所示。

于 2013-08-25T15:46:47.670 回答