这样的问题,你们不会认为是作业吧?
百度了一番,没百到。或者说,如何在调用repaint方法时,保持指定的graphics对象显示在前面?
还是那个棋盘棋子的问题,下棋的效果是终于做出来了。但是,现在的问题是:每次重绘后,棋盘的网格显示在棋子的上面,这不符合人的习惯。所以请教一下。代码如下:package gobang;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Graphics;public class TestChess extends  JPanel{
private static final long serialVersionUID = 4785452373598819718L;
private int x, y; //位置
final int ChessSize = 28;//棋子大小
private int width=600, height=600;//
private int d = width / 20;
public int boardOps[][] = new int[20][20];//0表示无子,1表示白子,2表示黑子
ImageIcon whiteIcon = new ImageIcon("image/white.png");
Image white = whiteIcon.getImage();

public TestChess() {

this.addMouseListener(new MouseAdapter() { 
int i=0, j=0;
public void mouseClicked(MouseEvent e) { 
x = e.getX(); 
y = e.getY(); 
if(x>d-1 && x<width-d+1 && y>d-1 && y<height-d+1){
boolean flag = true;
if(x%30<12) x = x - x%30;
else if(x%30>18) x = x - x%30 + 30;
else flag = false;
if(y%30<12) y = y - y%30;
else if(y%30>18) y = y - y%30 + 30;
else flag = false;
i = x/30;
j = y/30;
if(flag){
boardOps[i][j] = 1;
repaint(); 
//其他操作
}
}

}); 
}

public void paint(Graphics g) {//画棋盘 
for(int i = 0; i<=width; i+= d){//画网格
if(i==0 || i==width){
g.drawLine(i, 0, i, height);
g.drawLine(0, i, width, i);
}else{
g.drawLine(i, d, i, height-d);
g.drawLine(d, i, width-d, i);
}
}

int k=1;
char c='A';
for(int i = d; i<=width-d; i+=d){//位置标签
String str0 = String.format("%02d", k);
g.drawString(str0,10, i+10);
String str1 = String.valueOf(c);
g.drawString(str1,i,20);
c++;
k++;
}
g.drawImage(white, x-ChessSize/2, y-ChessSize/2, ChessSize, ChessSize, this);
  
} public static void main(String[] args) {
JFrame frame = new JFrame(); 
frame.add(new TestChess());
frame.setTitle("TestChess"); 
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800); 
frame.setVisible(true);  }}

解决方案 »

  1.   

    你 应该 调用 JFrame 的 repaint
      

  2.   

    我只弄过没有图标放棋盘上的5子棋
    package finalFiveChess;import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Shape;
    import java.awt.Stroke;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Ellipse2D;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;import javax.swing.JOptionPane;
    import javax.swing.JPanel;/**
     * 棋盘中间的网格图形,覆盖了该类的paintComponent()方法,重新绘制图形。
     * @author Administrator
     *
     */
    public class GraphicPanel extends JPanel{
    private boolean isBlack=true;//当前下子是否是黑方
    private char[][] allChess;//保存所有棋子的数组

    private int boardX=-1;//最后一次有效落子在棋盘的x,y坐标
    private int boardY=-1;

    public static final int ROW_NUM=16;//行数
    public static final int COL_NUM=16;//列数

    public static final int LEFT_BORDER=20;//左边界
    public static final int RIGTH_BORDER=20;//右边界
    public static final int UP_BORDER=20;//上边界
    public static final int DOWN_BORDER=20;//下边界

    public static final int ROW_GAP=40;//行间隙
    public static final int COL_GAP=40;//列间隙

    public static final int ChessRadio=15;//棋子半径

    public GraphicPanel(){
    allChess=new char[ROW_NUM][COL_NUM];
    for(int i=0;i<allChess.length;i++){//给旗子数组实例化
    for(int j=0;j<allChess[i].length;j++){
    allChess[i][j]='*';//初始时都赋为‘*’
    }
    }

    ChessBoard.label.setText((isBlack?"黑":"白")+"方请下子...");

    addMouseListener(new MouseAdapter(){//给该面板添加鼠标事件监听
    public void mouseClicked(MouseEvent e) {
    int button=e.getButton();
    if(button!=MouseEvent.BUTTON1){//如果不是鼠标左键点击
    return;//则不做任何处理
    }
    int x=e.getX();//获得鼠标点击位置的x,y坐标
    int y=e.getY();

    //如果鼠标点击点没有发生在棋盘的有效位置
    if(x<LEFT_BORDER/2 || x> LEFT_BORDER+(COL_NUM-1)*COL_GAP+RIGTH_BORDER/2
    || y<UP_BORDER/2 || y>UP_BORDER+(ROW_NUM-1)*ROW_GAP+DOWN_BORDER/2){

    ChessBoard.label.setText("无效位置!");
    return;//则不做任何处理
    }


    //将鼠标点击点的x,y坐标换算成棋盘上的x,y坐标。
    int boardX=Math.round((float)(x-LEFT_BORDER)/ROW_GAP);
    int boardY=Math.round((float)(y-UP_BORDER)/COL_GAP);

    //如果该位置上有棋子
    if(allChess[boardY][boardX]!='*'){
    ChessBoard.label.setText("该位置有棋子");
    return;//则不做任何处理
    }
    //将棋盘上该位置设置为指定棋子
    allChess[boardY][boardX]=isBlack?'@':'O';

    GraphicPanel.this.boardX=boardX;//保存最后一次有效落子的坐标
    GraphicPanel.this.boardY=boardY;

    //重画棋盘
    repaint();

    if(wasWin()){
    String mesg=(isBlack?"黑":"白")+"方获胜!";
    ChessBoard.label.setText(mesg);
    JOptionPane.showMessageDialog(GraphicPanel.this,mesg);
    clear();
    return;
    }
    //改变下棋方
    isBlack=!isBlack;
    ChessBoard.label.setText((isBlack?"黑":"白")+"方请下子...");
    }
    });
    }

    /**
     * 判断当前落子方是否获胜的方法
     * @return
     */
    public  boolean wasWin(){
    return wasWinAtV()||wasWinAtH()||wasWinAtLD()||wasWinAtRD();
    }

    /**
     * 判断水平方向上是否获胜
     * @return
     */
    private  boolean wasWinAtV(){
    char ch=isBlack?'@':'O';
    int i=boardX;
    while(i>=0 && allChess[boardY][i]==ch){//向左找到第一个不是ch的字符
    i--;
    }
    int num=0;
    i++;
    while(i<allChess.length && allChess[boardY][i]==ch){
    num++;
    i++;
    }
    return num>=5;

    }

    /**
     * 判断垂直方向上是否获胜
     * @return
     */
    private  boolean wasWinAtH(){
    char ch=isBlack?'@':'O';
    int i=boardY;
    while(i>=0 && allChess[i][boardX]==ch){//向左找到第一个不是ch的字符
    i--;
    }
    int num=0;
    i++;
    while(i<allChess.length && allChess[i][boardX]==ch){
    num++;
    i++;
    }
    return num>=5;
    }

    /**
     * 判断左斜方向上时候获胜
     * @return
     */
    private  boolean wasWinAtLD(){
    char ch=isBlack?'@':'O';
    int i=boardY;
    int j=boardX;
    while(i>=0 && j<allChess.length && allChess[i][j]==ch){//向左找到第一个不是ch的字符
    i--;
    j++;
    }
    int num=0;
    i++;
    j--;
    while(i<allChess.length && j>=0 && allChess[i][j]==ch){
    num++;
    i++;
    j--;
    }
    return num>=5;
    }


    /**
     * 判断右斜方向上是否获胜
     * @return
     */
    private  boolean wasWinAtRD(){
    char ch=isBlack?'@':'O';
    int i=boardY;
    int j=boardX;
    while(i>=0 && j>=0 && allChess[i][j]==ch){//向左找到第一个不是ch的字符
    i--;
    j--;
    }
    int num=0;
    i++;
    j++;
    while(i<allChess.length && j<allChess.length && allChess[i][j]==ch){
    num++;
    i++;
    j++;
    }
    return num>=5;
    }


    /**
     * 该方法在获胜后重新绘制棋盘,并初始化参数。
     *
     */
    public void clear(){
    boardX=-1;
    boardY=-1;
    for(int i=0;i<allChess.length;i++){
    for(int j=0;j<allChess[i].length;j++){
    allChess[i][j]='*';//初始时都赋为‘*’
    }
    }
    isBlack=true;
    // 重画棋盘
    repaint();
    ChessBoard.label.setText((isBlack?"黑":"白")+"方请下子...");
    }

    /**
     * 把当前棋盘状态保存到指定的文件中!
     * @param f
     */
    public boolean saveToFile(File f){
    //1,建立一个FileOutputStream
    FileOutputStream fos=null;
    try {
    fos=new FileOutputStream(f);
    for(int i=0;i<allChess.length;i++){
    for(int j=0;j<allChess[i].length;j++){
    if(i==boardY && j==boardX){
    fos.write(isBlack?'W':'B');
    }else{
    fos.write(allChess[i][j]);
    }
    }
    }
    } catch (IOException e) {
    e.printStackTrace();
    return false;
    }finally{
    if(fos!=null)try{fos.close();}catch(IOException e){}
    } return true;
    }


    /**
     * 从指定的文件中装载棋盘信息
     * @param f
     */
    public boolean loadFromFile(File f){
    FileInputStream fis=null;
    try {
    fis=new FileInputStream(f);
    for(int i=0;i<allChess.length;i++){
    for(int j=0;j<allChess[i].length;j++){
    char c=(char)fis.read();
    if(c!='*' && c!='O' && c!='@' && c!='W' && c!='B'){
    return false;
    }
    if(c=='B'){
    allChess[i][j]='@';
    boardX=j;
    boardY=i;
    isBlack=false;
    }else if(c=='W'){
    allChess[i][j]='O';
    boardX=j;
    boardY=i;
    isBlack=true;
    }else{
    allChess[i][j]=c;
    }
    }
    }
    } catch (IOException e) {
    e.printStackTrace();
    return false;
    }finally{
    if(fis!=null)try{fis.close();}catch(IOException e){}
    }

    this.repaint();
    return true;
    }
    @Override

    /**
     * 该方法为覆盖父类的方法,每次重画棋盘时系统会自动调用该方法。
     */
    public void paintComponent(Graphics g){
    super.paintComponent(g);
    //定义画笔类型
    Stroke stroke=new BasicStroke(2.0f);

    Graphics2D g2=(Graphics2D)g;
    g2.setStroke(stroke);

    //循环画出若干水平平行直线
    for(int i=0;i<ROW_NUM;i++){
    g2.drawLine(LEFT_BORDER,UP_BORDER+ROW_GAP*i,
    (COL_NUM-1)*COL_GAP+LEFT_BORDER,UP_BORDER+ROW_GAP*i);
    }

    //循环画出若干垂直平行直线
    for(int i=0;i<COL_NUM;i++){
    g2.drawLine(LEFT_BORDER+COL_GAP*i,UP_BORDER,
    LEFT_BORDER+COL_GAP*i,(ROW_NUM-1)*ROW_GAP+UP_BORDER);
    }


    //循环读取allChess数组,根据数组的内容画出每一个棋子。
    for(int i=0;i<allChess.length;i++){
    for(int j=0;j<allChess[i].length;j++){
    if(allChess[i][j]=='*'){
    continue;
    }
    Shape s=new Ellipse2D.Double(j*COL_GAP+LEFT_BORDER-ChessRadio,
    i*ROW_GAP+UP_BORDER-ChessRadio,ChessRadio*2,ChessRadio*2); 
    g2.setColor(Color.BLACK);
    g2.draw(s);
    if(allChess[i][j]=='@'){
    g2.setColor(Color.BLACK);
    }else{
    g2.setColor(Color.WHITE);
    }
    g2.fill(s);
    }
    }

    if(boardX!=-1){//在最后一次有效落点位置画一个红‘X’,用以标识。
    g2.setColor(Color.RED);
    g2.drawLine(boardX*ROW_GAP+LEFT_BORDER-5,boardY*COL_GAP+UP_BORDER-5,boardX*ROW_GAP+LEFT_BORDER+5,boardY*COL_GAP+UP_BORDER+5);
    g2.drawLine(boardX*ROW_GAP+LEFT_BORDER+5,boardY*COL_GAP+UP_BORDER-5,boardX*ROW_GAP+LEFT_BORDER-5,boardY*COL_GAP+UP_BORDER+5);
    }

    }
    }
      

  3.   

    主方法:(需要的话就参考一下吧)package finalFiveChess;import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.File;import javax.swing.JFileChooser;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JOptionPane;/**
     * 棋盘类,用来绘制棋盘
     * @author Administrator
     *
     */
    public class ChessBoard extends JFrame implements ActionListener{
    private GraphicPanel panel;
    private JMenuBar bar;//菜单条
    private JMenu game;//游戏菜单
    public static JLabel label;//状态栏
    public static final int DEFAULT_WIDTH=650;//棋盘宽度
    public static final int DEFAULT_HEIGHT=700;//棋盘高度

    public ChessBoard(){
    super("五子棋 v1.1");
    label=new JLabel(" ",JLabel.CENTER);
    panel=new GraphicPanel();
    this.add(panel,BorderLayout.CENTER);
    this.add(label,BorderLayout.SOUTH);
    bar=new JMenuBar();
    game=new JMenu("游戏");

    JMenuItem item=null;
    game.add(item=new JMenuItem("重新开始")); item.addActionListener(this);
    game.add(item=new JMenuItem("保存游戏...")); item.addActionListener(this);
    game.add(item=new JMenuItem("装载游戏...")); item.addActionListener(this);
    game.addSeparator();
    game.add(item=new JMenuItem("退出")); item.addActionListener(this);

    bar.add(game);
    this.setJMenuBar(bar);
    }

    public void showMe(){
    this.setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
    this.setVisible(true);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }



    public void actionPerformed(ActionEvent e) {
    if(e.getActionCommand().equals("保存游戏...")){
    //1,弹出保存文件对话框
    JFileChooser jfc=new JFileChooser();
    jfc.showSaveDialog(this);

    // 2,获得用户选择的文件
    File f=jfc.getSelectedFile();

    // 3,调用 
    if(f!=null){
    if(panel.saveToFile(f)){
    JOptionPane.showMessageDialog(this,"保存成功!");
    }else{
    JOptionPane.showMessageDialog(this,"保存文件失败!");
    }
    }

    return;
    }
    if(e.getActionCommand().equals("装载游戏...")){
    //1,弹出打开文件对话框
    JFileChooser jfc=new JFileChooser();
    jfc.showOpenDialog(this);
    //2,获得用户选择的文件
    File f=jfc.getSelectedFile();

    // 3,调用
    if(f!=null){
    if(!panel.loadFromFile(f)){
    JOptionPane.showMessageDialog(this,"文件格式不正确或已损坏!");
    }
    }
    return;
    }
    if(e.getActionCommand().equals("重新开始")){
    panel.clear();
    }
    if(e.getActionCommand().equals("退出")){
     System.exit(0);
    }

    } public static void main(String[] args){
    new ChessBoard().showMe();
    }}
      

  4.   

    repaint重载!
    repaint重载!
    repaint重载!
    repaint重载!
    repaint重载!
    repaint重载!