Java 无法使用JPanels

Java 无法使用JPanels,java,swing,graphics,mouselistener,Java,Swing,Graphics,Mouselistener,我试图理解MouseActionListener/Adapter类以及图形,我想我应该通过创建一个Tic-Tac-Toe游戏来做到这一点。我不想使用JButtons,因为我只是在更改按钮上的文字,而不是绘制图形图像。 我无法让我的面板绘制图像。我创建了两个内部类,一个用于JPanel,称为Board,另一个用于MouseAdapter类。我的paint方法位于Board类中,但当我单击JPanel时,它不会绘制图形(到目前为止,我只是设置为绘制X)。 我知道它可以识别面板是通过使用调试器单击的,

我试图理解MouseActionListener/Adapter类以及图形,我想我应该通过创建一个Tic-Tac-Toe游戏来做到这一点。我不想使用JButtons,因为我只是在更改按钮上的文字,而不是绘制图形图像。 我无法让我的面板绘制图像。我创建了两个内部类,一个用于JPanel,称为Board,另一个用于MouseAdapter类。我的paint方法位于Board类中,但当我单击JPanel时,它不会绘制图形(到目前为止,我只是设置为绘制X)。 我知道它可以识别面板是通过使用调试器单击的,但我不明白为什么它在调用时不调用paint方法

这是我的密码:

package xno;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics.*;
/**
 *
 * @author jordynsmith
 */
public class XnOFrame extends JFrame {
    private int win=0;
    private int loss=0;
    private int turn=1; //keeps track of the turn so that color can change with each turn
    public XnOFrame(){
        super("X n' O");

    //instantiate
    board = new Board[3][3];
    for(int i=0 ;i< 3; i++){
        for(int j=0; j<3; j++){
            board[i][j] = new Board();
            board[i][j].setStatus("Empty");
            board[i][j].setBackground(Color.black);
            //creates tic tac toe border
            //1st column
            if(j==0){//top
                    board[i][j].setBorder(BorderFactory.createMatteBorder(0, 0, 2, 2, Color.blue));
                if(i==1){//center
                    board[i][j].setBorder(BorderFactory.createMatteBorder(2, 0, 2, 0, Color.blue));    
                }
                if(i==2){//bottom
                    board[i][j].setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, Color.blue));
                }
            }
            //2nd column
            else if(j==1){//top
            board[i][j].setBorder(BorderFactory.createMatteBorder(0, 2, 2, 2, Color.blue));
                if(i==1){//center
                board[i][j].setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.blue));    
                }
                if(i==2){//bottom
                board[i][j].setBorder(BorderFactory.createMatteBorder(2, 2, 0, 2, Color.blue));
                }
            }
            //3rd column
            else if(j==2){//top
            board[i][j].setBorder(BorderFactory.createMatteBorder(0, 2, 2, 0, Color.blue));
                if(i==1){//center
                board[i][j].setBorder(BorderFactory.createMatteBorder(2, 2, 2, 0, Color.blue));    
                }
                if(i==2){//bottom
                board[i][j].setBorder(BorderFactory.createMatteBorder(2, 2, 0, 0, Color.blue));
                }
            }
        }
    }
    goBtn = new JButton("Start Game");
    quitBtn = new JButton("End Game");
    newBtn = new JButton("New Game");
    score = new JLabel("Score");
    wins = new JLabel("Wins");
    losses = new JLabel("Losses");
    wPoints = new JLabel(win + "");
    lPoints = new JLabel(loss + "");
    line = new JLabel("||");
    menuPanel = new JPanel();
    scorePanel = new JPanel();
    gridPanel = new JPanel();
    scoreLabelPanel = new JPanel();
    pointsPanel = new JPanel();

    //set layout
    this.setLayout(new BorderLayout());
    menuPanel.setLayout(new FlowLayout());
    scorePanel.setLayout(new BorderLayout());
    gridPanel.setLayout(new GridLayout(3,3));
    scoreLabelPanel.setLayout(new FlowLayout());
    pointsPanel.setLayout(new FlowLayout());

    //add components
    this.add(gridPanel, BorderLayout.CENTER);
    this.add(menuPanel, BorderLayout.SOUTH);
    this.add(scorePanel, BorderLayout.WEST);
    menuPanel.add(goBtn);
    menuPanel.add(quitBtn);
    menuPanel.add(newBtn);
    scorePanel.add(scoreLabelPanel, BorderLayout.NORTH);
    scorePanel.add(pointsPanel, BorderLayout.CENTER);
    scoreLabelPanel.add(score);
    pointsPanel.add(wins);
    pointsPanel.add(wPoints);
    pointsPanel.add(line);
    pointsPanel.add(losses);
    pointsPanel.add(lPoints);
    for(int i=0; i<board.length; i++){
        for(int j=0; j<board[i].length; j++){
            gridPanel.add(board[i][j]);
        }
    }

    //adding action
    for(int i=0; i<board.length; i++){
        for(int j=0; j<board[i].length; j++){
            board[i][j].addMouseListener(new BoardAction());
        }
    }
}
}

因此,在将我的paint方法更改为paintComponent之后,调用super.paint()方法时会抛出StackOverflower错误,我的JButtons会永远出现。为了看看会发生什么,我把那行注释掉,然后运行程序。通过这样做,我得到了以下结论: 黑色面板就是我点击的那个。面板开始时应为黑色,单击时应显示绿线。此外,只有一条绿线显示(因为它是x,所以应该有两条)。我正在尽我最大的努力学习教程,但是非常感谢任何额外的帮助

public void piant(Graphics g){
皮安特!=油漆

  • 您应该覆盖
    paintComponent
  • 始终在每个重写之前加上
    @override
    注释,这样编译器会在您出错时告诉您
  • 阅读Swing绘画教程
  • 皮安特!=油漆

  • 您应该覆盖
    paintComponent
  • 始终在每个重写之前加上
    @override
    注释,这样编译器会在您出错时告诉您
  • 阅读Swing绘画教程

  • 不要更改内部组件的状态
    paint

    private  void draw(Graphics g){
        if(status.equals("Empty")){//paints x if empty
           if(turn%2 != 0){//if turn is odd the color is green
            g.setColor(Color.green);
           }
           else//if even the color is yellow
               g.setColor(Color.yellow);
    
           g.drawLine(0, 0, getWidth(), getHeight());
           g.drawLine(getHeight(), 0, getWidth(), 0);
           // This is bad idea...
           setStatus("X");
       } 
    }
    
    绘制方法不应在绘制组件的当前状态时再进行任何操作,它不应修改组件的当前状态

    更喜欢使用
    paintComponent
    而不是
    paint
    。有关详细信息,请参阅和

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        draw(g);
    }
    
    private void draw(Graphics g) {
        if (status.equals("Empty")) {//paints x if empty
            if (turn % 2 != 0) {//if turn is odd the color is green
                g.setColor(Color.green);
            } else//if even the color is yellow
            {
                g.setColor(Color.yellow);
            }
    
            g.drawLine(0, 0, getWidth(), getHeight());
            g.drawLine(getHeight(), 0, getWidth(), 0);
        }
    }
    
    您的
    板操作
    实际上应该以某种有意义的方式更改
    的状态

    private class BoardAction extends MouseAdapter {
    
        @Override
        public void mouseClicked(MouseEvent me) {
            //determines which panel was clicked
            Board panel = (Board) me.getSource();
            panel.setStatus("X");
            panel.repaint();//calls paint method
        }
    }
    

    另外请考虑,您的
    Board
    类还应覆盖
    getPreferredSize
    并返回一些大小,然后
    0x0

    不要更改内部组件的状态
    paint

    private  void draw(Graphics g){
        if(status.equals("Empty")){//paints x if empty
           if(turn%2 != 0){//if turn is odd the color is green
            g.setColor(Color.green);
           }
           else//if even the color is yellow
               g.setColor(Color.yellow);
    
           g.drawLine(0, 0, getWidth(), getHeight());
           g.drawLine(getHeight(), 0, getWidth(), 0);
           // This is bad idea...
           setStatus("X");
       } 
    }
    
    绘制方法不应在绘制组件的当前状态时再进行任何操作,它不应修改组件的当前状态

    更喜欢使用
    paintComponent
    而不是
    paint
    。有关详细信息,请参阅和

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        draw(g);
    }
    
    private void draw(Graphics g) {
        if (status.equals("Empty")) {//paints x if empty
            if (turn % 2 != 0) {//if turn is odd the color is green
                g.setColor(Color.green);
            } else//if even the color is yellow
            {
                g.setColor(Color.yellow);
            }
    
            g.drawLine(0, 0, getWidth(), getHeight());
            g.drawLine(getHeight(), 0, getWidth(), 0);
        }
    }
    
    您的
    板操作
    实际上应该以某种有意义的方式更改
    的状态

    private class BoardAction extends MouseAdapter {
    
        @Override
        public void mouseClicked(MouseEvent me) {
            //determines which panel was clicked
            Board panel = (Board) me.getSource();
            panel.setStatus("X");
            panel.repaint();//calls paint method
        }
    }
    

    另外,考虑一下,您的
    Board
    类还应该重写
    getPreferredSize
    并返回一些大小,而不是
    0x0

    1。不要在
    BorderActon
    中创建
    Board
    的新实例,不需要它;2.覆盖
    paintComponent
    ,以支持
    paint
    ;3.据推测,您的
    BoardAction
    实际上应该以某种有意义的方式更改
    Board
    的状态1。不要在
    BorderActon
    中创建
    Board
    的新实例,不需要它;2.覆盖
    paintComponent
    ,以支持
    paint
    ;3.据推测,您的
    BoardAction
    实际上应该以某种有意义的方式更改
    Board
    的状态way@JonnyHenly因为它实际上并没有回答这个问题,但提供了通常很好的建议,这将有助于OP进一步减少问题的数量,这些代码有助于隔离实际问题。如果我们说过一次,我们已经说过一千次了:P@JonnyHenly因为它实际上并没有回答这个问题,但提供了通常很好的建议,这将有助于OP进一步减少问题的数量,这些代码有助于隔离实际问题。如果我们说过一次,我们已经说过一千次了:P