无法在JPanel上绘图

时间:2015-11-03 04:15:06

标签: java swing graphics mouselistener

我尝试了解MouseActionListener / Adapter类以及Graphics,我认为我是通过创建Tic-Tac-Toe游戏来实现的。我并不想使用JButton,因为我只是改变按钮上的措辞而不是绘制图形图像。 我无法让我的面板绘制图像。我为JPanels创建了两个内部类,一个叫做Board,一个用于MouseAdapter类。我的绘制方法位于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());
        }
    }
}

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

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;

}

因此,在将paint方法更改为paintComponent之后,调用super.paint()方法时会抛出StackOverflowError,并且我的JButton将永远显示。只是为了看看会发生什么,我评论说排队并运行程序。通过这样做,我得到了这个: 黑色面板是我点击的那个。面板应为黑色以开始,单击时绿线应显示。此外,只有一条绿线出现(应该有两条,因为它是一个x)。我正在尽力遵循教程,但非常感谢任何其他帮助!

2 个答案:

答案 0 :(得分:3)

public void piant(Graphics g){

piant!=油漆。

  1. 您应该覆盖paintComponent
  2. 始终在每个覆盖前加上@Override注释,以便编辑器在您做错时告诉您。
  3. 阅读Swing绘画教程。

答案 1 :(得分:3)

不要在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。有关详细信息,请参阅Painting in AWT and SwingPerforming 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类还应覆盖getPreferredSize并返回0x0以外的其他大小