为了深入学习Java中GUI与事件处理机制,利用java中的GUI与事件处理机制等功能实现围棋小游戏。
效果图
一、概述
1、GUI是指图形用户界面也称图形用户接口,在Java中是进行人机交互的窗口,在这个窗口中用户可以实现应用程序提供的所有功能。事件处理机制在上一篇文章中有详细介绍,这里不多说明。
二、设计
(本人的设计思想是:先设计一个整体的框架,再往设计好的框架中加入组件,并一步步的进行调试,争取每步都在正确的路线上,各代码之间相互融合。)
1、逻辑设计
1)、首先创建一个顶级窗口容器类myframe,作为整体的框架。
2)、然后创建规则类Rule,加入到框架中
3)、然后创建棋盘类ChessPad,加入到框架中,再在棋盘类中添加具体的组件,比如说一个重新开始按钮和两个用于提示作用的文本框,如上效果图。
4)、再创建黑棋子类Chess_black和白棋子类Chess_white,加入到棋盘类中
5)、最后创建实现鼠标监听事件类Listen,用于实现各组件的产生的事件。
6)、最后创建一个主类mains,用于启动程序。
注意:这里其实是有三个容器,一个顶级窗口容器属于最顶级的,一个规则类容器(因为这里我是用继承JPanel面板容器实现的)和一个棋盘类容器(还是用继承JPanel面板容器实现的)。我把各种组件都是添加到棋盘类容器中的,所以当实现组件产生的事件时,其实是在棋盘类容器中进行各种操作的,而不是在顶级窗口容器中。
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路漫漫,唯有君作伴~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。