簡體   English   中英

如何將JLabel從JFrame中的一個JPanel拖動到同一JFrame中另一個JPanel的JTextField中?

[英]How should I drag a JLabel from one JPanel in a JFrame onto a JTextField in another JPanel in the same JFrame?

簡而言之,我想將JLabel的文本設置為JPanelpnlUser )中的JTextField的文本,然后將JLabelJPanel拖到整個屏幕上,拖到另一個JPanelpnlGrid )中的另一個JTextField上。

這是詳細信息。

我寫了一個“紙牌拼字游戲”程序。 用戶可以將文本光標放置在網格單元中(在pnlGridJTextField ),然后鍵入“用戶字母”列表中的字母(在pnlUserJTextField ),或者用戶可以模擬從“用戶字母”中拖動字母“並將其放入pnlGrid的目標網格單元中。

我之所以說“模擬”,是因為所選字母實際上並沒有在屏幕上拖動。 我使用鼠標指針HAND_CURSOR使拖放盡可能真實,但我還沒有弄清楚如何使HAND_CURSOR “抓住”字母並將其實際拖動到目標位置。

HAND_CURSOR ,該字母被突出顯示,但是在“ HAND_CURSOR ”在拖動操作過程中沿網格移動時留在“用戶字母”區域中。 當到達pnlGrid的目標單元格並釋放鼠標按鈕時,該字母便從“用戶字母”中刪除,並突然出現在網格單元格中。

因此,該字母或多或少地從“用戶字母”“傳送”到了網格單元中(請問我,斯科蒂)。 這太抽象了。 我希望用戶字母位於HAND_CURSOR的指尖處,並沿着網格拖到將其拖放到的網格單元中,如下面的3張圖片所示。

在此處輸入圖片說明在此處輸入圖片說明在此處輸入圖片說明

我已經使用JLayeredPane在一個小型測試程序(下面的資源)中成功實現了它,但是我無法在游戲中實現它。 但是直到兩天前我對JLayeredPane還是一無所知,所以我真的不知道自己在做什么。 (我改編了一個演示JLayeredPane的Oracle教程程序。)

我剛剛閱讀了有關“玻璃窗格”的內容,並認為在下載該演示的源代碼之前,實現起來可能會更容易,因為它很長,因此,它是全新的,適應起來會更加困難。

所以我想在花更多的時間沮喪之前,我應該問:

JLayeredPanesetGlassPane方法是否合適? 有沒有更簡便或更好的方法將JLabel從一個JPanel拖動到另一個JPanel

(該程序中的方法是確定所指向的“用戶字母”,將該字母存儲在JLabel ,然后確保在mouseDragged期間, HAND_CURSOR指尖位於該字母的底部中心。)

package mousemoveletter;
import javax.swing.*;
import javax.swing.border.*; 
import java.awt.*;
import static java.awt.Color.*;
import java.awt.event.*;
import static javax.swing.SwingUtilities.invokeLater;

public class LayeredPaneDemo extends JPanel 
{
  private static final int USER7 = 7;
  static Cursor HAND  = new Cursor(Cursor.HAND_CURSOR);
  static Cursor ARROW = new Cursor(Cursor.DEFAULT_CURSOR);

  private static JLayeredPane layeredPane;
  private static JLabel       lblToMove;
  private static JPanel       pnlUser;
  private static JPanel       pnlGrid;
  private static final JTextField[] txtUser = new JTextField[USER7];

  public LayeredPaneDemo()    // constructor
  {
    pnlGrid = new JPanel();
    setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
    layeredPane = new JLayeredPane();
    layeredPane.setPreferredSize(new Dimension(240, 240));
    pnlGrid.setSize(140, 140);
    pnlGrid.setBorder(new EtchedBorder(RED, GREEN));
    pnlGrid.setBackground(YELLOW);

    lblToMove = new JLabel("XXX");
    lblToMove.setSize(new Dimension(40,40));

    layeredPane.add(pnlGrid, 0,0);
    layeredPane.add(lblToMove, new Integer(0), -1);

    add(layeredPane);   
  }

  private static void createAndShowGUI() {
    JFrame frame = new JFrame("LayeredPaneDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JComponent newContentPane = new LayeredPaneDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    makeUser();

    frame.add(pnlUser);

    frame.pack();
    frame.setVisible(true);
  }

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

  private static void makeUser(){
    pnlUser = new JPanel(new GridLayout(1,USER7));
    pnlUser.setPreferredSize(new Dimension(225, 50));
    pnlUser.setBackground(Color.green);
    pnlUser.setBorder(BorderFactory.createLineBorder(Color.BLUE));
    for(int k = 0; k < USER7; k++)
    {
      txtUser[k] = new JTextField("" + (char)(Math.random()*26+65));
      txtUser[k].setName("" + k);
      txtUser[k].setEditable(false);
      txtUser[k].addMouseMotionListener(new MouseMotionAdapter() 
      {
        public void mouseDragged(MouseEvent e) 
        {
          lblToMove.setCursor(HAND);
          int w = Integer.parseInt(e.getComponent().getName());
          lblToMove.setText(txtUser[w].getText());
          layeredPane.setLayer(lblToMove, 0, 0);
          lblToMove.setLocation(e.getX() + (e.getComponent().getWidth())*w, 
                                e.getY() + layeredPane.getHeight() - e.getComponent().getHeight()/2);
        };
      });

      txtUser[k].addMouseListener(new MouseAdapter()
      {
        public void mouseReleased(MouseEvent e)
        {
          lblToMove.setCursor(ARROW);
        }          
      });
      pnlUser.add(txtUser[k]);
    }
  }
}

感謝@trashgod,我通過關注他到本示例變體的鏈接來弄清楚了它; 我將在那里找到的棋盤的拖放調整適應了我自己對“拼字游戲”的特殊需要。

下面的代碼不是我的Solitaire Scrabble程序的最終代碼,而是概念驗證,可能被希望將單元從1xN網格拖到MxM網格的其他人使用。

        package components;
        import java.awt.*;
        import static java.awt.BorderLayout.NORTH;
        import static java.awt.BorderLayout.SOUTH;
        import java.awt.event.*;
        import static java.lang.Integer.parseInt;
        import javax.swing.*;
        import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
        import javax.swing.event.MouseInputAdapter;

        public class ChessBoard //implements MouseListener, MouseMotionListener
        {
          static Point parentLocation;
          int homeRow, homeCol; // where to restore moved user letter if dropped on occupied cell

          static int    N     = 11; // NxN 'chessboard' squares
          static int    S     = 44; // square dimensions: SxS 
          static int    W         ; // chessboard dimensions: WxW 
          static int    USER7 = 7;
          static Font   dragFont;
          static JFrame frame;
          JLayeredPane  layeredPane;
          static JPanel gamePanel, // encompasses both pnlGrid and pnlUser
                        pnlGrid, 
                        pnlUser;
          JLabel        userDragLetter = new JLabel(); // main item to drag around or restore if needed
          int           xAdjustment, yAdjustment; // how to locate drops accurately

          String userLetters[] ;

          public ChessBoard() // constructor
          {
            W = S*N;
            dragFont = new Font("Courier", Font.PLAIN, S);

            userLetters = new String[USER7];
            for (int i = 0; i < USER7; i++)
              userLetters[i] = "" + (char)(65 + Math.random()*26);

            Dimension gridSize  = new Dimension(W,  W);  
            Dimension userSize  = new Dimension(W,      S);
            Dimension gameSize  = new Dimension(W, (W + S));

            frame               = new JFrame();
            frame.setSize(new Dimension(gameSize)); // DO NOT USE PREFERRED

            layeredPane = new JLayeredPane();
            layeredPane.setPreferredSize( gameSize ); // NO PREFERRED => NO GRID!

            gamePanel   = new JPanel();

// **EDIT** LOSE THIS LINE            gamePanel.setLayout(new BorderLayout());

            gamePanel.setPreferredSize(gameSize);

            pnlGrid     = new JPanel();
            pnlGrid.setLayout(new GridLayout(N, N));
            pnlGrid.setPreferredSize( gridSize );
            pnlGrid.setBounds(0, 0, gridSize.width, gridSize.height);

            pnlUser     = new JPanel();
            pnlUser.setLayout(new GridLayout(1, N));
            pnlUser.setPreferredSize(userSize);
            pnlUser.setBounds(0, gridSize.height, userSize.width, userSize.height);

            layeredPane.add(pnlGrid, JLayeredPane.DEFAULT_LAYER); // panels to drag over
            layeredPane.add(pnlUser, JLayeredPane.DEFAULT_LAYER); //  "         "

            for (int i = 0; i < N; i++){
              for (int j = 0; j < N; j++){
                JPanel square = new JPanel();
                square.setBackground( (i + j) % 2 == 0 ? Color.red : Color.white );
                pnlGrid.add( square );
              }
            }

            for (int i = 0; i < N; i++) {
              JPanel square = new JPanel(new BorderLayout());
              square.setBackground(Color.YELLOW);
              pnlUser.add(square);
            }

            for (int i = 0; i < USER7; i++)
              addPiece(i, 0, userLetters[i]);

            gamePanel.addMouseListener(new MouseInputAdapter()
            {
              public void mousePressed (MouseEvent e){mousePressedActionPerformed (e);}
              public void mouseReleased(MouseEvent e){mouseReleasedActionPerformed(e);}
            });

            gamePanel.addMouseMotionListener(new MouseMotionAdapter()
            {
              public void mouseDragged(MouseEvent me){mouseDraggedActionPerformed(me);}
            });

    // **EDIT: LOSE THE NEXT TWO LINES AND REPLACE BY THE LINE AFTER THEM** 


        //        gamePanel.add(layeredPane, NORTH);
        //        gamePanel.add(pnlUser,     SOUTH);
                 gamePanel.add(layeredPane);
              }

          private void addPiece(int col, int row, String glyph) {
            JLabel piece = new JLabel(glyph, JLabel.CENTER);
            piece.setFont(dragFont);
            JPanel panel = (JPanel) pnlUser.getComponent(col + row * N);
            piece.setName("piece " + glyph + " @ " + row + " " + col);
            panel.add(piece);
          }

          void mousePressedActionPerformed(MouseEvent e)
          {
            userDragLetter = null; // signal that we're not dragging if no piece is in the square

            gamePanel.setCursor(new Cursor(Cursor.HAND_CURSOR));

            Component c =  pnlGrid.findComponentAt(e.getX(), e.getY());
            if(c != null)
              return; // Illegal to click pnlGrid

            c =  pnlUser.findComponentAt(e.getX(), e.getY() - pnlGrid.getHeight()); 

            if(c ==  null | c instanceof JPanel)
              return; // letter already played; can't drag empty cell

            parentLocation = c.getParent().getLocation();
            xAdjustment = parentLocation.x - e.getX(); 
            yAdjustment = parentLocation.y - e.getY() + gamePanel.getHeight() - pnlUser.getHeight();

            userDragLetter = (JLabel)c;
            userDragLetter.setPreferredSize(new Dimension(S, S)); // prevent 2 letters in a square
            userDragLetter.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);

            layeredPane.add(userDragLetter, JLayeredPane.DRAG_LAYER);

            homeRow = parseInt(userDragLetter.getName().substring(10,11)); // save restore location 
            homeCol = parseInt(userDragLetter.getName().substring(12,13));
          }

          void mouseDraggedActionPerformed(MouseEvent me)
          {
            if (userDragLetter == null)
              return; // nothing to drag

            int x = me.getX() + xAdjustment; // make sure grid cell will be chosen in-bounds
            int xMax = layeredPane.getWidth() - userDragLetter.getWidth();
            x = Math.min(x, xMax);
            x = Math.max(x, 0);

            int y = me.getY() + yAdjustment;
            int yMax = layeredPane.getHeight() - userDragLetter.getHeight();
            y = Math.min(y, yMax);
            y = Math.max(y, 0);

            if(y >= pnlGrid.getHeight())
              return; // can't drag to location off grid

            userDragLetter.setLocation(x, y); 
          }

          void mouseReleasedActionPerformed(MouseEvent e)
          {

    //**EDIT: CHANGED NEXT LINE**

             gamePanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

            if (userDragLetter == null) 
              return; // nothing to drag; nothing to release

            //  Make sure the chess piece is no longer painted on the layered pane
            userDragLetter.setVisible(false);
            layeredPane.remove(userDragLetter);
            userDragLetter.setVisible(true);

            int xMax = layeredPane.getWidth() - userDragLetter.getWidth();
            int x = Math.min(e.getX(), xMax);
            x = Math.max(x, 0);

            int yMax = layeredPane.getHeight()- userDragLetter.getHeight();
            int y = Math.min(e.getY(), yMax);
            y = Math.max(y, 0);

            Component c =  pnlGrid.findComponentAt(x, y); // find deepest nested child component

            if(c == null) // then grid cell is unoccupied so ...
              c = pnlUser.findComponentAt(x, y); // see if there's a letter there ...

            if(c == null | (c instanceof JLabel)){ // and if illegal or there is one, put it back...
              userDragLetter.setLocation(parentLocation.x + xAdjustment, 
                                         parentLocation.y + yAdjustment + gamePanel.getHeight());
              userDragLetter.setVisible(true);
              addPiece(homeCol, homeRow,userDragLetter.getName().substring(6,7));
              layeredPane.remove(userDragLetter);
              return;
            }
            else // but if NO letter ...
            {
              Container parent = (Container)c;
              parent.add( userDragLetter );  // put one in the grid cell
              parent.validate();
            }
            userDragLetter.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
          }

          public static void main(String[] args)
          {
            new ChessBoard();
            frame.add(gamePanel);
            frame.setDefaultCloseOperation( DISPOSE_ON_CLOSE );
        //    frame.setResizable( false );
            frame.pack();
            frame.setLocationRelativeTo( null );
            frame.setVisible(true);
          }
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM