为了深入学习Java中GUI与事件处理机制,利用java中的GUI与事件处理机制等功能实现围棋小游戏。
效果图
image.png
一、概述

1、GUI是指图形用户界面也称图形用户接口,在Java中是进行人机交互的窗口,在这个窗口中用户可以实现应用程序提供的所有功能。事件处理机制在上一篇文章中有详细介绍,这里不多说明。

二、设计

(本人的设计思想是:先设计一个整体的框架,再往设计好的框架中加入组件,并一步步的进行调试,争取每步都在正确的路线上,各代码之间相互融合。)

1、逻辑设计

1)、首先创建一个顶级窗口容器类myframe,作为整体的框架。

2)、然后创建规则类Rule,加入到框架中

3)、然后创建棋盘类ChessPad,加入到框架中,再在棋盘类中添加具体的组件,比如说一个重新开始按钮和两个用于提示作用的文本框,如上效果图。

4)、再创建黑棋子类Chess_black和白棋子类Chess_white,加入到棋盘类中

5)、最后创建实现鼠标监听事件类Listen,用于实现各组件的产生的事件。

6)、最后创建一个主类mains,用于启动程序。

注意:这里其实是有三个容器,一个顶级窗口容器属于最顶级的,一个规则类容器(因为这里我是用继承JPanel面板容器实现的)和一个棋盘类容器(还是用继承JPanel面板容器实现的)。我把各种组件都是添加到棋盘类容器中的,所以当实现组件产生的事件时,其实是在棋盘类容器中进行各种操作的,而不是在顶级窗口容器中。
image.png
2、代码实现

(1)、这里通过创建一个窗口类myfame继承JFrame类来创建顶级窗口容器。注意:这里的窗口类布局管理器为空布局。

package 单机围棋;
 
import javax.swing.JFrame;
 
class myframe extends JFrame//窗口类
{
    private static final long serialVersionUID=2l;
    ChessPad chessPad=new ChessPad();
    //方法定义
    public void display()//窗口设置
    {
        setTitle("围棋");
        setLayout(null);//设置容器布局为空布局
        setSize(570,560);//窗口大小
        /***********************************************/
        Rule rule=new Rule();//规则面板类对象
        add(rule);
        rule.setBounds(60, 20, 440, 30);//设置规则面板类在窗口中的位置和大小
        /***********************************************/
        ChessPad chessPad=new ChessPad();//棋盘面板类对象
        add(chessPad);
        chessPad.setBounds(60, 60, 440, 440);//设置棋盘面板类在窗口中的位置和大小
        /***********************************************/
        setVisible(true);//窗口为可见
        setResizable(false);//不可改变窗口大小
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

(2)、通过创建一个Rule类继承JPanel面板容器实现规则面板,再加入到顶级窗口容器中,并设置在窗口中的位置。

package 单机围棋;
 
import java.awt.Color;
 
import javax.swing.JLabel;
import javax.swing.JPanel;
 
public class Rule extends JPanel//规则面板类
{
    private static final long serialVersionUID=2l;
    
    //属性定义 
    JLabel label;//标签
    //方法定义
    public Rule() 
    {
        setBackground(Color.orange);//面板颜色
        setSize(440, 30);//面板大小
        label=new JLabel("单击左键下棋子,双击左键吃棋子,落子无悔!请慎重!");
        add(label);
    }
}

(3)、通过创建棋盘类ChessPad继承JPanel面板容器实现棋盘,并在棋盘容器中加入重新开始组件,一个标签组件,和两个文本框组件。

package 单机围棋;
 
import java.awt.Color;
import java.awt.Graphics;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
 
public class ChessPad extends JPanel//棋盘面板类
{
    private static final long serialVersionUID=3l;
    //属性定义
    JButton button;//按钮
    JTextField text1,text2;//文本框
    JLabel label;//标签
    Listen listen=new Listen();//创建监听器对象
    //方法定义
    ChessPad()//构造方法
    {
        setSize(440,440);//棋盘面板大小
        setLayout(null);//棋盘布局为空
        setBackground(Color.orange);//面板颜色
        button=new JButton("重新开始");
        add(button);
        button.addMouseListener(listen);//在按钮中添加监听器
        button.setBounds(3, 10, 85, 20);
        text1=new JTextField("请黑棋下子");
        add(text1);
        text1.addMouseListener(listen);//在文本框1中添加监听器
        text1.setBounds(92, 10, 100, 20);
        label=new JLabel("提示框:"); 
        add(label);
        label.setBounds(214, 10, 60, 20);
        text2=new JTextField("游戏开始,请黑棋先下子");
        add(text2);
        text2.setBounds(257, 10, 180, 20);//在文本框2中添加监听器
        listen.set1(button, this);//把按钮实例对象和棋盘实例对象传入实现监听事件类的中
        listen.set2(text1, text2,label);//把文本框实例对象和标签实例对象传入实现监听事件类的中
        addMouseListener(listen);//在棋盘类中添加监听器,注意这里是吧整个棋盘面板作为事件源
    }
    @Override
    public void paintComponent(Graphics g)//画线,棋盘行列间距为40像素,行列为19
    {
        super.paintComponent(g);
        for(int i=40;i<=400;i=i+20)
            g.drawLine(40, i, 400, i);
        for(int j=40;j<=400;j=j+20)
            g.drawLine(j, 40, j, 400);
        //在棋盘的指定位置绘制实心圆,注意左上角坐标不是圆心坐标
        g.fillOval(97, 97, 6, 6);
        g.fillOval(337, 97, 6, 6);
        g.fillOval(97, 337, 6, 6);
        g.fillOval(337, 337, 6, 6);
        g.fillOval(217, 217, 6, 6);
    }
    public void paintchess()//在棋盘上画棋子的方法
    {
        Graphics p=getGraphics();
        p.fillOval(96, 96, 10, 10);
    }
}

(4)、创建黑棋子类,并实现MouseListener接口用来在自身类中实现”双击黑棋子进行吃黑棋子“的功能。这里的黑棋是通过继承JPanel容器实现的,也就是说黑棋子其实也是个面板容器(同样白棋子也是)。

package 单机围棋;
 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
 
import javax.swing.JPanel;
 
public class Chess_black extends JPanel implements MouseListener//黑棋子类继承面板容器,自身实现鼠标点击事件
{
    public static final long serialVersionUID=03l;//序列号
    ChessPad chessPad;
    
    public void get(ChessPad chessPad)//传入棋盘实例对象
    {
        this.chessPad=chessPad;
    }
    
    public Chess_black()//定义黑棋子面板容器大小,并添加鼠标事件监听器 
    {
        setSize(20,20);
        addMouseListener(this);
    }
    
    @Override
    public void paint(Graphics p)//定义黑棋子颜色宽高
    {
        p.setColor(Color.black);
        p.fillOval(0, 0, 20, 20);
    }
    
    @Override
    public void mouseClicked(MouseEvent e)//实现鼠标监听事件
    {
        if (e.getClickCount()>=2)//如果鼠标连续点击了两下或以上
        {
            if(e.getSource()==this)//如果鼠标点击的是黑棋子组件
            {
                chessPad.remove(this);//在棋盘面板容器中移除被点击的黑棋子组件
                chessPad.repaint();//刷新棋盘,如果不刷新,则会显示异常
            }    
        }
    }
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

(5)、使用与创建黑棋子类相同的方法创建白棋子Chess_white。

package 单机围棋;
 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
 
import javax.swing.JPanel;
 
public class Chess_white extends JPanel implements MouseListener
{
    public static final long serialVersionUID=02l;//序列号
    ChessPad chessPad;
    
    public void get(ChessPad chessPad)
    {
        this.chessPad=chessPad;
    }
    
    public Chess_white()
    {
        setSize(20,20);
        addMouseListener(this);
    }
    
    @Override
    public void paint(Graphics p)//重写paint方法画好白棋子对象颜色和大小。该方法为在面板容器中使用的用来设计面板样式的方法,
                                 //所以只要调用该方法所在类的容器对象,就可以显示该方法所设计的容器的样子
    {
        p.setColor(Color.white);
        p.fillOval(0, 0, 20, 20);
        
    }
    
    @Override
    public void mouseClicked(MouseEvent e)
    {
        if (e.getClickCount()>=2)
        {
            if(e.getSource()==this)
            {
                chessPad.remove(this);
                chessPad.repaint();
            }    
        }
    }
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

(6)、鼠标监听事件类Listen,用于实现各组件相应的功能。

package 单机围棋;
 
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
 
public class Listen extends MouseAdapter//实现鼠标点击事件
{
    JButton button;
    ChessPad chessPad;
    JTextField text1,text2;
    JLabel label;
    
    int x,y;
    int color=0;//让黑棋先落子
    Chess_black chessblack;
    Chess_white chesswhite;
    
    public void set1(JButton button,ChessPad chessPad)//传入组件实例对象,并初始化
    {
        this.button=button;      
        this.chessPad=chessPad;
    }
 
    public void set2(JTextField text1,JTextField text2,JLabel label)//传入组件实例对象,并初始化
    {
        this.text1=text1;
        this.text2=text2;
        this.label=label;
    }
    
    @Override
    public void mouseClicked(MouseEvent e)//鼠标在组件上单击(按下并释放)时调用该方法。
    {
        if(e.getSource()==button)//重新开始事件的实现
        {
            chessPad.removeAll();//删除容器中所有组件
            chessPad.repaint();//刷新容器显示界面
            //重新往容器中添加组件
            chessPad.add(button);
            chessPad.add(text1);
            chessPad.text1.setText("请黑棋下子");
            chessPad.add(label);
            chessPad.add(text2);
            chessPad.text2.setText("重新开始了,请黑棋先下子");
 
            color=0;//颜色重新设置为0,重新从黑棋开始下        
        }    
            //得到鼠标在容器中的坐标
            x=e.getX();
            y=e.getY();
            //得到坐标在棋盘上的行列位置
            int a=(x+9-20)/20;//行位置
            int b=(y+9-20)/20;//列位置
        if(e.getSource()==chessPad)//在棋盘上下棋事件的实现
        {
            if(x<35||y<35||x>405||y>405)//判断鼠标下棋位置,若超出棋盘位置则不落子
            {
                chessPad.text2.setText("别乱点!棋只能下在棋盘上面!");//鼠标超出棋盘位置,不落子
            }
            else//鼠标在棋盘中,开始落子
            {
                if(color==1)//若棋子颜色为1,则落白子
                {
                    chesswhite=new Chess_white();//定义白棋子组件实例对象
                    chesswhite.get(chessPad);
                    chessPad.add(chesswhite);//往棋盘容器中添加白子
                    chesswhite.setBounds(a*20+10, b*20+10, 20, 20);//白子落子位置
                    chessPad.text1.setText("请黑棋下子");
                    chessPad.text2.setText(null);
                    color--;//棋子颜色设置0,控制下一步落子颜色为黑子
                }
                else if(color==0)//若棋子颜色为0,则落黑子
                {
                    chessblack=new Chess_black();//定义黑棋子组件的实例对象
                    chessblack.get(chessPad);
                    chessPad.add(chessblack);//往棋盘容器中添加黑子
                    chessblack.setBounds(a*20+10, b*20+10, 20, 20);//黑子落子位置
                    chessPad.text1.setText("请白棋下子");    
                    chessPad.text2.setText(null);
                    color++;//棋子颜色设置为1,控制下一步落子为白子
                }
            }
        }
    }
}

(7)、鼠标监听事件类Listen创建

package 单机围棋;
 
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
 
public class Listen extends MouseAdapter//实现鼠标点击事件
{
    JButton button;
    ChessPad chessPad;
    JTextField text1,text2;
    JLabel label;
    
    int x,y;
    int color=0;//让黑棋先落子
    Chess_black chessblack;
    Chess_white chesswhite;
    
    public void set1(JButton button,ChessPad chessPad)//传入组件实例对象,并初始化
    {
        this.button=button;      
        this.chessPad=chessPad;
    }
 
    public void set2(JTextField text1,JTextField text2,JLabel label)//传入组件实例对象,并初始化
    {
        this.text1=text1;
        this.text2=text2;
        this.label=label;
    }
    
    @Override
    public void mouseClicked(MouseEvent e)//鼠标在组件上单击(按下并释放)时调用该方法。
    {
        if(e.getSource()==button)//重新开始事件的实现
        {
            chessPad.removeAll();//删除容器中所有组件
            chessPad.repaint();//刷新容器显示界面
            //重新往容器中添加组件
            chessPad.add(button);
            chessPad.add(text1);
            chessPad.text1.setText("请黑棋下子");
            chessPad.add(label);
            chessPad.add(text2);
            chessPad.text2.setText("重新开始了,请黑棋先下子");
 
            color=0;//颜色重新设置为0,重新从黑棋开始下        
        }    
            //得到鼠标在容器中的坐标
            x=e.getX();
            y=e.getY();
            //得到坐标在棋盘上的行列位置
            int a=(x+9-20)/20;//行位置
            int b=(y+9-20)/20;//列位置
        if(e.getSource()==chessPad)//在棋盘上下棋事件的实现
        {
            if(x<35||y<35||x>405||y>405)//判断鼠标下棋位置,若超出棋盘位置则不落子
            {
                chessPad.text2.setText("别乱点!棋只能下在棋盘上面!");//鼠标超出棋盘位置,不落子
            }
            else//鼠标在棋盘中,开始落子
            {
                if(color==1)//若棋子颜色为1,则落白子
                {
                    chesswhite=new Chess_white();//定义白棋子组件实例对象
                    chesswhite.get(chessPad);
                    chessPad.add(chesswhite);//往棋盘容器中添加白子
                    chesswhite.setBounds(a*20+10, b*20+10, 20, 20);//白子落子位置
                    chessPad.text1.setText("请黑棋下子");
                    chessPad.text2.setText(null);
                    color--;//棋子颜色设置0,控制下一步落子颜色为黑子
                }
                else if(color==0)//若棋子颜色为0,则落黑子
                {
                    chessblack=new Chess_black();//定义黑棋子组件的实例对象
                    chessblack.get(chessPad);
                    chessPad.add(chessblack);//往棋盘容器中添加黑子
                    chessblack.setBounds(a*20+10, b*20+10, 20, 20);//黑子落子位置
                    chessPad.text1.setText("请白棋下子");    
                    chessPad.text2.setText(null);
                    color++;//棋子颜色设置为1,控制下一步落子为白子
                }
            }
        }
    }
}

(8)、主类mains创建,最后启动主类既可启动程序,进行围棋游戏啦!!

package 单机围棋;
 
public class mains
{
    public static void main (String []args)
    {
        new myframe().display();
    }
}

三、总结
  通过这次小游戏的实现,了解掌握GUI图形界面的设计,并学习界面中各组件与事件处理机制的功能交互实现。这里主要是运用到了JPanel容器(JPanel又称面板,是Java中最常用的轻量级容器之一,其默认布局管理器是FlowLayout(流式布局管理器)。JPanel可以容纳其他组件,但其本身不可见,需要加入到顶级容器中才能存在,因此也称为中间容器,JPanel之间可以嵌套,对组件进行组合。)来实现界面的设计。当然也可以使用其他的组件或者容器来进行界面的设计,并且也可以添加其他组件来实现相应更复杂的功能,但由于图形界面的设计并不是Java的强项,也由于GUI发展的停滞,这里不对GUI作深入的了解。本文旨在学习Java事件处理机制以及事件处理机制实现功能的过程,并对设计模式有一定的学习和了解,并规范代码的实现,给本人自己找准一种学习的思路,也希望能给读者带来帮助。

Java路漫漫,唯有君作伴~


0qqppyvt
29 声望6 粉丝