java - 在 JPanel 数组中交换 JPanel

标签 java swing jpanel drag-and-drop mouse-listeners

我可以更换面板,但还不够好。例如,如果 panel1 碰撞 panel2,它会交换,但如果同样碰撞 panel3,panel3 也会移动到 panel1 位置(我不希望发生这种情况)。如果有大约 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) {
   }
}

最佳答案

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

  • 我已经让容器 JPanel(容纳多个列组件的容器)使用 FlowLayout 来实现这一点
  • 我已将 MouseAdapter 作为 MouseListener 和 MouseMotionListener 添加到容器 JPanel,而不是列组件。
  • 我通过在容器 JPanel 上调用 getComponentAt(mouseEvent.getPoint()) 获取了选定的列组件。当然要检查它是否不为空。
  • 如果所选组件不为 null,则我使用该组件设置 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;
   }

}

关于java - 在 JPanel 数组中交换 JPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18430202/

相关文章:

java - 如何在java中打开名称为字符串的文件

java - 我用 Swing 绘制的旋钮很难看。为什么?

java - 与缺失类相关的 Logica SMPP 错误

java - hibernate 异常 : Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set

java 运行 jmx 禁用操作

java - 在我的 GUI 中切换面板之前,如何使 JMessageDialog 不强制用户关闭它?

java - drawString 方法不起作用

java - 如何在单击 JCheckBox 时显示 JPopupMenu?

java - 调用 `setText()` 时 JTextfield 未更新

java - 3 JFrame中的Jpanel,我的按钮不可见