Я пытаюсь понять класс 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). Я прилагаю все усилия, чтобы следить за учебниками, но любая дополнительная помощь очень ценится!
1. Не создавайте новый экземпляр 'Board' в' BorderActon', в этом нет необходимости; 2. Переопределите 'paintComponent' в пользу' paint'; 3.Предположительно, вы 'BoardAction' должны фактически изменить состояние' Board' каким-либо значимым образом. – MadProgrammer