无法在 JPanels 上绘制

Unable to draw on JPanels

我正在尝试理解 MouseActionListener/Adapter class 以及图形,我想我会通过创建井字游戏来做到这一点。我不想不使用 JButtons,因为我只是更改按钮上的文字而不是绘制图形图像。 我在让我的面板绘制图像时遇到问题。我创建了两个内部 classes,一个用于名为 Board 的 JPanel,另一个用于 MouseAdapter class。我的绘画方法位于 Board class 中,但是当我单击 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());
        }
    }
}

这才是我真正的问题所在。我不太确定如何组织以及何时调用某些方法,以及应该调用什么才能使其正常工作。

private class BoardAction extends MouseAdapter{
    private Board panel = new Board();

    @Override
    public void mouseClicked(MouseEvent me){
        //determines which panel was clicked
        panel = (Board) me.getSource();
        panel.repaint();//calls paint method
    }
}



private class Board extends JPanel{
    public String status;

    public Board(){
        status="Empty";
    }

    public String getStatus(){
        return status;
    }
    public void setStatus(String s){
        status = s;
    }

    public void piant(Graphics g){
    super.paint(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);
           setStatus("X");
       } 
    }
}

//components
Board [][] board;
JPanel menuPanel, scorePanel, gridPanel, scoreLabelPanel, pointsPanel;
JButton goBtn, quitBtn, newBtn;
JLabel score, wins, losses, wPoints, lPoints, line;

}

因此,在将我的绘画方法更改为 paintComponent 后,调用 super.paint() 方法时会抛出 WhosebugError,并且我的 JButton 会永远出现。只是为了看看会发生什么,我评论了那行和 运行 程序。这样做我得到这个: 黑色面板是我点击的面板。面板应该是黑色的开始,点击时应该显示绿线。此外,只有一条绿线出现(应该有两条,因为它是 x)。我正在尽力按照教程进行操作,但非常感谢任何额外的帮助!

public void piant(Graphics g){

piant != paint.

  1. 你应该覆盖 paintComponent
  2. 始终在每个重写前加上 @Override 注释,这样编译器会在您做错时告诉您。
  3. 阅读 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");
   } 
}

paint 方法除了绘制组件的当前状态之外什么都不做,它不应该修改它。

paint 更喜欢使用 paintComponent。有关详细信息,请参阅 Painting in AWT and Swing and Performing Custom Painting

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

您的 BoardAction 实际上应该以某种有意义的方式改变 Board 的状态...

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 class 还应该覆盖 getPreferredSize 和 return 一些尺寸,而不是 0x0