2015-11-03 3 views
0

Я пытаюсь понять класс MouseActionListener/Adapter, а также Graphics, и я подумал, что сделаю это, создав игру Tic-Tac-Toe. Я не хотел использовать JButtons, потому что я бы просто изменил формулировку на кнопке, а не рисовал графический образ. У меня возникли проблемы с получением моих панелей, чтобы нарисовать изображение. Я создал два внутренних класса для JPanels под названием Board и один для класса MouseAdapter. Мой метод рисования находится в классе Board, но когда я нажимаю JPanel, он не рисует графику (пока я просто нарисовал X). Я знаю, что он распознает, что панель была нажата с помощью отладчика, но я не понимаю, почему она не вызывает метод paint при вызове.Невозможно нарисовать на JPanels

Вот мой код:

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 в StackOverflowError выбрасывается, когда метод super.paint() вызываются и мое JButtons принять навсегда, чтобы появиться. Просто чтобы узнать, что произойдет, я прокомментировал эту строку и запустил программу. При этом я получаю следующее: Черные панели - это то, что я нажал. Панели должны быть черными для запуска, и при нажатии зеленой линии должно появиться. Кроме того, появляется только одна из зеленых линий (должно быть два, так как это x). Я прилагаю все усилия, чтобы следить за учебниками, но любая дополнительная помощь очень ценится!

+0

1. Не создавайте новый экземпляр 'Board' в' BorderActon', в этом нет необходимости; 2. Переопределите 'paintComponent' в пользу' paint'; 3.Предположительно, вы 'BoardAction' должны фактически изменить состояние' Board' каким-либо значимым образом. – MadProgrammer

ответ

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 Swing и 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 класс должен переопределить getPreferredSize и возврат некоторый размер другой тогда 0x0

3
public void piant(Graphics g){ 

piant! = Краска.

  1. Вы должны переопределить paintComponent
  2. всегда предварять каждое переопределение с @Override аннотацию поэтому компилятор сообщит вам, когда вы делаете это неправильно.
  3. Прочтите учебники по рисованию Swing.
+0

@JonnyHenly. Потому что он фактически не отвечает на вопрос, но дает в целом хороший совет, который поможет OP еще больше сократить количество проблем с помощью там код, который может помочь изолировать фактическую проблему. И если мы это однажды сказали, мы сказали это тысячу раз: P – MadProgrammer