编程入门:用Java画一个象棋棋盘

发布时间:2026/8/1 11:28:49
编程入门:用Java画一个象棋棋盘 Java图形界面入门手把手教你画一个中国象棋棋盘附完整代码先放效果图一、准备工作新建窗体和所有Swing程序一样第一步是创建一个JFrame窗口。我们新建一个类GoBangUI在showUI()方法中设置窗体的基本属性packagexiang_qi;importjavax.swing.*;importjava.awt.*;publicclassGoBangUI{publicvoidshowUI(){JFramejfnewJFrame();jf.setTitle(象棋);// 设置标题jf.setSize(450,500);// 设置大小宽450高500jf.setLocation(500,200);// 设置窗口在屏幕上的位置jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭按钮退出程序jf.setVisible(true);// 让窗口显示出来}publicstaticvoidmain(String[]args){GoBangUIuinewGoBangUI();ui.showUI();}}此时运行你会看到一个空白的灰色窗口接下来我们要在上面画棋盘。二、绘制棋盘的步骤我们需要在窗体的“画布”上做四件事画线、填充底色、写字、贴背景图片。1. 画线drawLinedrawLine(x1, y1, x2, y2)方法用于画一条从(x1, y1)到(x2, y2)的线段。我们先定义几个常量方便后续计算X 50棋盘最左边那条线的 X 坐标Y 75棋盘最上边那条线的 Y 坐标SIZE 40每个格子的大小像素ROW 10行数中国象棋是10行COL 9列数中国象棋是9列画横线10行每行一条横线for(inti0;iROW;i){g.drawLine(X,Yi*SIZE,X(COL-1)*SIZE,Yi*SIZE);}画竖线9列但中间有“楚河汉界”断开所以分为上下两段for(inti0;iCOL;i){if(i0||iCOL-1){// 最左边和最右边的竖线要画通到底g.drawLine(Xi*SIZE,Y,Xi*SIZE,Y(ROW-1)*SIZE);}else{// 中间的竖线只画上半部分到第4行和下半部分从第5行开始g.drawLine(Xi*SIZE,Y,Xi*SIZE,Y4*SIZE);g.drawLine(Xi*SIZE,Y5*SIZE,Xi*SIZE,Y(ROW-1)*SIZE);}}画斜线两个“九宫格”的斜线// 上方九宫格g.drawLine(X3*SIZE,Y,X5*SIZE,Y2*SIZE);g.drawLine(X5*SIZE,Y,X3*SIZE,Y2*SIZE);// 下方九宫格g.drawLine(X3*SIZE,Y9*SIZE,X5*SIZE,Y7*SIZE);g.drawLine(X5*SIZE,Y9*SIZE,X3*SIZE,Y7*SIZE);2. 填充底色fillRect为了让棋盘看起来更真实我们先用一个矩形铺上木色背景。fillRect(x, y, width, height)会画一个以(x, y)为左上角、指定宽高的实心矩形。ColorcolornewColor(202,141,20);// 木黄色RGBg.setColor(color);g.fillRect(X-SIZE/2,Y-SIZE/2,(COL-1)*SIZESIZE,(ROW-1)*SIZESIZE);g.setColor(Color.BLACK);// 画线前改回黑色小技巧在 IntelliJ IDEA 中new Color(r, g, b)的括号里可以直接点击颜色预览帮你肉眼选色非常方便。3. 写字drawString中国象棋棋盘中央需要写“楚河”和“汉界”并且“汉界”正立“楚河”倒置让对阵双方各看各的。drawString(text, x, y)的(x, y)是文字左下角的位置基线。若字体大小为负数文字就会上下颠倒。// 写“汉界”正立Stringtext汉 界;FontfontnewFont(篆体,Font.BOLD,30);g.setFont(font);g.drawString(text,90,265);// 写“楚河”倒置Stringtext2楚 河;Fontfont2newFont(篆体,Font.BOLD,-30);// 负字号实现翻转g.setFont(font2);g.drawString(text2,330,245);注意负字号翻转并非所有系统都稳定更标准的方法是使用Graphics2D旋转但作为入门教学此技巧简洁直观。4. 贴入背景图片drawImage我们还可以在窗体的顶部或背景加上一张图片例如棋盘的木质纹理或装饰图。ImageIconimgnewImageIcon(C:\\Users\\chenjiaqin\\Desktop\\download.png);g.drawImage(img.getImage(),0,40,800,800,null);drawImage的参数依次为图片对象、左上角 X、左上角 Y、宽度、高度、图像观察者通常写null即可。三、一个问题线条会消失按照上面的代码如果直接在showUI()方法里用getGraphics()获取画笔并画图当你拖动窗口边缘改变大小、最小化再还原、或者被其他窗口遮挡后再显示你画的线条、文字和图片都会消失只剩下灰色的背景。为什么会这样因为 Java Swing 的窗口在每次需要重绘时比如上述事件系统会自动调用paint(Graphics g)方法来刷新界面。如果你没有重写paint默认的paint只会清空画布并画一个灰色背景你之前用getGraphics画上去的内容就像用粉笔写在黑板上被彻底擦除了。怎么办解决方法就是重写paint方法。我们把所有绘图代码都放在paint方法里这样每次系统要求重绘时都会自动执行我们的画图逻辑图形就会“永久”保留。四、正确的做法继承 JFrame 并重写 paint新建一个类MyFrame继承JFrame并重写paint方法packagexiang_qi;importjavax.swing.*;importjava.awt.*;publicclassMyFrameextendsJFrame{// 背景图片ImageIconimgnewImageIcon(C:\\Users\\chenjiaqin\\Desktop\\download.png);// 重写 paint 方法publicvoidpaint(Graphicsg){// 必须保留调用父类的 paint完成清空、绘制边框等基础工作super.paint(g);System.out.println(窗体刷新);// 可以观察每次重绘的时机// 画背景图片g.drawImage(img.getImage(),0,40,800,800,null);// 定义棋盘参数intX50,Y75,SIZE40,ROW10,COL9;// 填充木色背景ColorcolornewColor(202,141,20);g.setColor(color);g.fillRect(X-SIZE/2,Y-SIZE/2,(COL-1)*SIZESIZE,(ROW-1)*SIZESIZE);g.setColor(Color.BLACK);// 画横线for(inti0;iROW;i){g.drawLine(X,Yi*SIZE,X(COL-1)*SIZE,Yi*SIZE);}// 画竖线断开楚河汉界for(inti0;iCOL;i){if(i0||iCOL-1){g.drawLine(Xi*SIZE,Y,Xi*SIZE,Y(ROW-1)*SIZE);}else{g.drawLine(Xi*SIZE,Y,Xi*SIZE,Y4*SIZE);g.drawLine(Xi*SIZE,Y5*SIZE,Xi*SIZE,Y(ROW-1)*SIZE);}}// 画九宫格斜线g.drawLine(X3*SIZE,Y,X5*SIZE,Y2*SIZE);g.drawLine(X5*SIZE,Y,X3*SIZE,Y2*SIZE);g.drawLine(X3*SIZE,Y9*SIZE,X5*SIZE,Y7*SIZE);g.drawLine(X5*SIZE,Y9*SIZE,X3*SIZE,Y7*SIZE);// 写“汉界”正Stringtext汉 界;FontfontnewFont(篆体,Font.BOLD,30);g.setFont(font);g.drawString(text,90,265);// 写“楚河”倒Stringtext2楚 河;Fontfont2newFont(篆体,Font.BOLD,-30);g.setFont(font2);g.drawString(text2,330,245);}}现在窗口的绘图逻辑被“固化”在paint中无论怎么刷新棋盘都会稳稳地显示出来。五、主程序启动类修改GoBangUI让它创建MyFrame实例并显示窗口。packagexiang_qi;importjavax.swing.*;importjava.awt.*;publicclassGoBangUI{publicvoidshowUI(){MyFramejfnewMyFrame();// 使用我们自己的 JFrame 子类jf.setTitle(象棋);jf.setSize(450,500);jf.setLocation(500,200);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setVisible(true);// 注意这里的 for 循环和 getGraphics() 仅为演示说明实际可删去for(inti0;i100000;i){System.out.println(hello);}// Graphics g jf.getGraphics(); // 此方法画图会消失不推荐使用}publicstaticvoidmain(String[]args){GoBangUIuinewGoBangUI();ui.showUI();}}六、关于for循环你在某些教材或视频中可能会看到这样的代码for(inti0;i100000;i){System.out.println(hello);}Graphicsgjf.getGraphics();// 然后用 g 画图...这个循环有什么用它是用来强行拖延时间的。因为setVisible(true)后窗口的初始化包括绘制并不是立刻完成的主线程会继续向下执行。如果马上调用getGraphics()很可能获取到的画笔是null或者绘图环境未就绪导致画不出来。用这个循环打印 10 万次“hello”让主线程“卡”一会儿等窗口完全显示后再获取画笔就能成功。但是这种做法会产生一些问题。它让程序启动变慢控制台刷出大量无用信息。即使获取到画笔画出来的图还是会在刷新时消失因为没有重写paint。正确的做法就是第 4 节讲的那样永远把绘图代码放在paint方法里既不需要延时循环也不需要手动getGraphics。结束~