【问题标题】:java swing associating JPanel with row col values for mouse listenerjava swing将JPanel与鼠标侦听器的行列值相关联
【发布时间】:2012-01-20 13:10:32
【问题描述】:

我正在编写一个带有 GUI 的棋盘游戏,基本上我有一个 10x10 GridLayout JPanel。

每个网格单元都是一个方形的 JPanel(我对这些 JPanel 使用了 BorderLayout,因此边框是可见的)。

无论如何我想要它,以便当单击这些方块之一时,它会更改 boardGameGrid,它是一个导入到游戏后端 GUI 的类。说我要使用方法

boardGameGrid.setCellCross(x,y)

当位置 (x,y) 的单元格被按下时。

我不知道该怎么做,因为每个 JPanel 不包含任何有关其位置的信息。

谢谢

【问题讨论】:

  • 当 Jtable 已经存在于 Java 中时,您正在模仿它。那么为什么要重新发明轮子呢?

标签: java swing grid jpanel mouselistener


【解决方案1】:

您必须将此 JPanel 准备为 Object 并将其放入 Map 或 List,基于伟大但简单的想法的简单示例

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.border.LineBorder;
//based on @trashgod code from http://stackoverflow.com/a/7706684/714968
public class FocusingPanel extends JFrame {

    private static final long serialVersionUID = 1L;
    private int elements = 10;
    private List<GridPanel> list = new ArrayList<GridPanel>();
    private final JFrame mainFrame = new JFrame();
    private final JPanel fatherPanel = new JPanel();

    public FocusingPanel() {
        fatherPanel.setLayout(new GridLayout(elements, elements));
        for (int i = 0; i < elements * elements; i++) {
            int row = i / elements;
            int col = i % elements;
            GridPanel gb = new GridPanel(row, col);
            list.add(gb);
            fatherPanel.add(gb);
        }
        mainFrame.setLayout(new BorderLayout(5, 5));
        mainFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        mainFrame.add(fatherPanel, BorderLayout.CENTER);
        mainFrame.pack();
        mainFrame.setVisible(true);
    }

    private GridPanel getGridPanel(int r, int c) {
        int index = r * elements + c;
        return list.get(index);
    }

    private class GridPanel extends JPanel {

        private int row;
        private int col;

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

        public GridPanel(int row, int col) {
            this.row = row;
            this.col = col;
            this.setBackground(Color.red);
            this.setBorder(new LineBorder(Color.black,1));
            this.addMouseListener(new MouseListener() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    int r = GridPanel.this.row;
                    int c = GridPanel.this.col;
                    GridPanel gb = FocusingPanel.this.getGridPanel(r, c);
                    System.out.println("r" + r + ",c" + c
                            + " " + (GridPanel.this == gb)
                            + " " + (GridPanel.this.equals(gb)));
                }

                @Override
                public void mousePressed(MouseEvent e) {
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    int r = GridPanel.this.row;
                    int c = GridPanel.this.col;
                    GridPanel gb = FocusingPanel.this.getGridPanel(r, c);
                    System.out.println("r" + r + ",c" + c
                            + " " + (GridPanel.this == gb)
                            + " " + (GridPanel.this.equals(gb)));
                    setBackground(Color.blue);

                }

                @Override
                public void mouseExited(MouseEvent e) {
                    setBackground(Color.red);
                }
            });
        }
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                FocusingPanel focusingPanel = new FocusingPanel();
            }
        });
    }
}

【讨论】:

  • 为什么这比 Jtable 更好?我实际上认为这是对资源的浪费。因为您的 GridPanel 包含与 Jtable 行为完全相同的行和列
  • 我的意思是,当 Jtable 已经存在于 Java 中时,您正在模仿它。那么为什么要重新发明轮子呢?
  • 1) 您在 JTable 的单元格中使用简单的 JPanel 是正确的,但如果 JPanel 嵌套了另一个 JComponents 或图形,则需要 SwingUtilities,2) JTable 知道从 MouseEvent 返回 Rectangle 或单元格,
  • 不清楚的问题是他为什么首先需要JPanels? 1)也许他不知道 JTable 2)他没有提供足够的信息来说明他想做什么
  • 我只是想知道他为什么要把 JPanel 放在首位
【解决方案2】:

你为什么不简单地让每个小组都知道他的位置:

public MyPanel(int x, int y) {
    this.x = x;
    this.y = y;
}

并且,在鼠标监听器中:

MyPanel p = (MyPanel) event.getSource();
boardGameGrid.setCellCross(p.getX(), p.getY());

如果您不想更改 MyPanel,也可以使用 Map&lt;MyPanel, Point&gt;,并将每个面板的位置存储在此地图中:

MyPanel p = (MyPanel) event.getSource();
Point point = panelPositionMap.get(p);
boardGameGrid.setCellCross(p.x, p.y);

【讨论】:

    【解决方案3】:

    您为什么不将其作为JTable 而不是JPanel,您可以为每个单元格添加一个侦听器。这样你就知道点击了哪一行哪一列

    【讨论】:

      【解决方案4】:

      每个 JPanel 都知道它的位置,您可以使用 panel.getX()/getY() 获得。好像你要求的是这样的:

      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      
      public class PanelLocation extends JFrame implements MouseListener
      {
          private JPanel mainPanel, footerPanel;
          private JPanel[] panel = new JPanel[9];
          private JTextField tfield;
      
          public PanelLocation()
          {
              mainPanel = new JPanel();
              mainPanel.setLayout(new GridLayout(3, 3));
      
              for (int i = 0; i < 9; i++)
              {
                  panel[i] = new JPanel();
                  panel[i].addMouseListener(this);
                  panel[i].setBorder(BorderFactory.createLineBorder(Color.BLUE));
                  mainPanel.add(panel[i]);
              }   
      
              footerPanel = new JPanel();
      
              tfield = new JTextField(10);
              footerPanel.add(tfield);
      
              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              setLocationRelativeTo(null);
      
              add(mainPanel, BorderLayout.CENTER);
              add(footerPanel, BorderLayout.PAGE_END);
      
              pack();     
              setVisible(true);
          }
      
      
      
           private void getWhichButtonGotPressed(int x, int y)
           {
               if ((x == panel[0].getX()) && (y == panel[0].getY()))
               {
                  panel[0].setBackground(Color.MAGENTA);
                  tfield.setText("You Clicked Panel : " + panel[0].getToolTipText());
               }
               else if ((x == panel[1].getX()) && (y == panel[1].getY()))
               {
                  panel[1].setBackground(Color.YELLOW);
                  tfield.setText("You Clicked Panel : " + panel[1].getToolTipText());
               }
               else if ((x == panel[2].getX()) && (y == panel[2].getY()))
               {
                  panel[2].setBackground(Color.RED);
                  tfield.setText("You Clicked Panel : " + panel[2].getToolTipText());
               }
               else if ((x == panel[3].getX()) && (y == panel[3].getY()))
               {
                  panel[3].setBackground(Color.DARK_GRAY);
                  tfield.setText("You Clicked Panel : " + panel[3].getToolTipText());
               }
               else if ((x == panel[4].getX()) && (y == panel[4].getY()))
               {
                  panel[4].setBackground(Color.ORANGE);
                  tfield.setText("You Clicked Panel : " + panel[4].getToolTipText());
               }
               else if ((x == panel[5].getX()) && (y == panel[5].getY()))
               {
                  panel[5].setBackground(Color.PINK);
                  tfield.setText("You Clicked Panel : " + panel[5].getToolTipText());
               }
               else if ((x == panel[6].getX()) && (y == panel[6].getY()))
               {
                  panel[6].setBackground(Color.BLUE);
                  tfield.setText("You Clicked Panel : " + panel[6].getToolTipText());
               }
               else if ((x == panel[7].getX()) && (y == panel[7].getY()))
               {
                  panel[7].setBackground(Color.CYAN);
                  tfield.setText("You Clicked Panel : " + panel[7].getToolTipText());
               }
               else if ((x == panel[8].getX()) && (y == panel[8].getY()))
               {
                  panel[8].setBackground(Color.GRAY);
                  tfield.setText("You Clicked Panel : " + panel[8].getToolTipText());
               }
          }
      
          public void mouseClicked(MouseEvent ae)
          {
              JPanel panel = (JPanel) ae.getSource();
      
              getWhichButtonGotPressed(panel.getX(), panel.getY());
          }
      
          public void mousePressed(MouseEvent ae)
          {
          }
      
          public void mouseReleased(MouseEvent ae)
          {
          }
      
          public void mouseEntered(MouseEvent ae)
          {
          }
      
          public void mouseExited(MouseEvent ae)
          {
          }
      
          public static void main(String[] args)
          {
              SwingUtilities.invokeLater(new Runnable()
                  {
                      public void run()
                      {
                          new PanelLocation();
                      }
                  });
          }
      }
      

      显示点击面板坐标的示例程序。您只需单击面板,坐标将传递给函数,该函数将检查单击了哪个面板,并返回所述面板的 toopTipText。

      这是程序的输出:

      希望这可能会有所帮助。

      问候

      【讨论】:

        【解决方案5】:

        您可以使用二维数组来存储对面板的引用。

        例子:

        JPanel[][] panels = new JPanel[10][10];
        
        //to store a panel:
        JPanel p = new JPanel();
        panels[x][y] = p;
        
        //then change your method so that it gets the panel at position (x,y) from the array
        public void setCellCross(int x, int y){
             JPanel clickedPanel = panels[x][y];
        }
        

        【讨论】:

        • 如果我理解正确的话,问题是从面板获取位置,而不是从位置获取面板。
        猜你喜欢
        • 1970-01-01
        • 2012-02-28
        • 1970-01-01
        • 1970-01-01
        • 2012-04-05
        • 1970-01-01
        • 2011-10-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多