无法在 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.
- 你应该覆盖
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");
}
}
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
我正在尝试理解 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 会永远出现。只是为了看看会发生什么,我评论了那行和 运行 程序。这样做我得到这个:
public void piant(Graphics g){
piant != paint.
- 你应该覆盖
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");
}
}
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