简体   繁体   English

在一个JPanels数组中交换JPanels

[英]Swap JPanels in an array of JPanels

I am able to SWAP the panels but it is not good enough. 我可以交换面板,但还不够好。 For instance, if panel1 collides panel2, it swaps, but if the same collides panel3, panel3 also moves to panel1 location(which I don't want to happen). 例如,如果panel1碰撞panel2,它将交换,但是如果相同碰撞panel3,panel3也将移动到panel1位置(我不想发生)。 If there are about 10 panels, and if I want to swap panel1 with panel10 it is not possible with current logic. 如果大约有10个面板,并且如果我想将panel1与panel10交换,则使用当前逻辑是不可能的。 Can anyone please help me out. 谁能帮我一下。

Below is the code with the above logic: 以下是具有上述逻辑的代码:

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

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

If you don't want to use drag-and-drop, and if your JPanels are in columns, then consider these suggestions: 如果您不想使用拖放操作,并且您的JPanel位于列中,那么请考虑以下建议:

  • I've gotten this to work having the container JPanel (the one that holds the multiple column components) use a FlowLayout 我已经使容器JPanel(容纳多个列组件的容器)使用FlowLayout起作用了
  • I've added the MouseAdapter as a MouseListener and MouseMotionListener to the container JPanel, not the column components. 我已经将MouseAdapter作为MouseListener和MouseMotionListener添加到了容器JPanel中,而不是列组件中。
  • I obtained the selected column component by calling getComponentAt(mouseEvent.getPoint()) on the container JPanel. 我通过在容器JPanel上调用getComponentAt(mouseEvent.getPoint())获得了选定的列组件。 Of course check that it's not null. 当然,请检查它是否不为空。
  • If the selected component is not null, then I set a selectedComponent variable with this component, and put a placeholder JLabel that has the same preferredSize in its place. 如果选择的组件不为null,那么我为此组件设置一个selectedComponent变量,并在其位置放置一个具有相同preferredSize的占位符JLabel。 I do this by removing all components from the container JPanel, and then re-adding them all back except for the selected component where I instead add the placeholder JLabel. 为此,我从容器JPanel中删除了所有组件,然后将所有组件重新添加回去,除了所选组件之外,我在其中添加了占位符JLabel。 I then call revalidate and repaint on the container. 然后,我调用revalidate并在容器上重新绘制。
  • To drag the selected component, elevate it to the glassPane (ie, add it to the glassPane). 要拖动选定的组件,请将其提升到glassPane(即,将其添加到glassPane)。
  • make the glassPane visible and give it a null layout. 使glassPane可见,并为其提供空布局。
  • Drag the selected component in the glassPane simply by changing its location relative to the glassPane. 只需通过更改所选组件相对于glassPane的位置,即可将其拖动到glassPane中。
  • On mouseReleased, find out what column component the mouse is over, again by using getComponentAt(...) . 在mouseReleased上,再次使用getComponentAt(...)找出鼠标悬停在哪个列组件上。
  • Then remove all components from the container JPanel, 然后从容器JPanel中删除所有组件,
  • and then add them all back in the desired order. 然后按所需顺序将它们全部重新添加。
  • Then again call revalidate and repaint on the container JPanel. 然后再次调用revalidate并在容器JPanel上重新绘制。

For example: 例如:

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM