涉及到的知识:
1.图形用户接口GUI(Graphical User Interface)用图形化的方式显示操作界面
两个体系: AWT包和Swing包
2.界面会用到JFrame类
3.界面中的菜单会用到JMenuBar, JMenu, JMenuItem
4.添加图片
在设置完JLabel的location之后还需要获得展示内容的窗体, 通过setLayout(null)来取消默认的居中放置, 这样才能使图片放在我们想放的位置.
5.监听事件
5.1动作监听只能监听键盘的空格和鼠标的左键点击。
5.2鼠标监听
5.3键盘监听
6.背景图片的设置
注意:先加载的图片会置顶, 后加载的图片会被先加载的覆盖。
7.图片路径的简化
路径分为两种:
绝对路径:一定是从盘符开始的。如C:\
相对路径:不是从盘符开始的, 相对路径是相对当前项目而言的。
在当前项目下,去找aaa文件夹,里面再找bbb文件夹。
8.Java代码
8.1拼图游戏界面的代码
package com.orange.ui;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GameJFrame extends JFrame implements KeyListener, ActionListener {
private int zerolocationx = 0;
private int zerolocationy = 0;
private final int leftKeyCode = 37;
private final int upKeyCode = 38;
private final int rightKeyCode = 39;
private final int bottomKeyCode = 40;
private final int aKeyCode = 65;
private final int cheatCode = 87;
private int[][] randomarr = new int[4][4];
private int[][] winArr = new int[4][4];
private final String imagepath = "JigsawPuzzle\\image";
private String imageType = "girl";
private int numImage = 1;
private String completePath = imagepath + "\\" + imageType + "\\" + imageType + numImage;
private String backgroundPath = "JigsawPuzzle\\image\\background.png";
private String winPath = "JigsawPuzzle\\image\\win.png";
private boolean winFlag = false;
int[] arr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
private int count = 0;
// set JMenuItem
JMenuItem replayJMenuItem = new JMenuItem("重新游戏");
JMenuItem reLoginJMenuItem = new JMenuItem("重新登录");
JMenuItem closeJMenuItem = new JMenuItem("关闭游戏");
JMenuItem prettyGirl = new JMenuItem("妹子");
JMenuItem animal = new JMenuItem("动物");
JMenuItem sport = new JMenuItem("运动");
JMenuItem focusmeJMenuItem = new JMenuItem("关注我");
public GameJFrame(int width, int height){
// initial Frame
initialFrame(width, height);
// initial JMenuBar
initialJMenuBar();
// initial Image
initialImage();
this.setVisible(true);
}
private void initialImage() {
// clear
this.getContentPane().removeAll();
// set count
JLabel stepCount = new JLabel("步数为:" + count);
stepCount.setBounds(50, 30, 100, 20);
this.getContentPane().add(stepCount);
// set win image
if (randomarr == winArr){
JLabel win = new JLabel(new ImageIcon(winPath));
win.setBounds(40, 40, 508, 560);
this.getContentPane().add(win);
winFlag = true;
}
// set patches image
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
// set JLabel
JLabel jLabel = new JLabel(new ImageIcon(completePath + "\\" + randomarr[i][j] + ".jpg"));
// set JLabel location
jLabel.setBounds(j * 105 + 83, i * 105 + 134, 105, 105);
// set border
// 0 present RAISED, 1 present LOWERED
jLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
// get panel
this.getContentPane().add(jLabel);
}
}
// set background image
JLabel bg = new JLabel(new ImageIcon(backgroundPath));
bg.setBounds(40, 40, 508, 560);
this.getContentPane().add(bg);
// refresh interface
this.getContentPane().repaint();
}
private void initialJMenuBar() {
// set JMenuBar
JMenuBar jMenuBar = new JMenuBar();
// setJMenu
JMenu functionJMenu = new JMenu("功能");
JMenu aboutusJMenu = new JMenu("关于我们");
JMenu changeImage = new JMenu("更换图片");
changeImage.add(prettyGirl);
changeImage.add(animal);
changeImage.add(sport);
functionJMenu.add(changeImage);
functionJMenu.add(replayJMenuItem);
functionJMenu.add(reLoginJMenuItem);
functionJMenu.add(closeJMenuItem);
aboutusJMenu.add(focusmeJMenuItem);
// binding ActionListener for JMenuItem
prettyGirl.addActionListener(this);
animal.addActionListener(this);
sport.addActionListener(this);
replayJMenuItem.addActionListener(this);
reLoginJMenuItem.addActionListener(this);
closeJMenuItem.addActionListener(this);
focusmeJMenuItem.addActionListener(this);
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutusJMenu);
// set JMenuBar in the Frame
this.setJMenuBar(jMenuBar);
}
private void initialFrame(int width, int height) {
this.setSize(width, height);
// set title
this.setTitle("拼图小游戏");
// set frame always on top
this.setAlwaysOnTop(true);
// set frame in the center of screen
this.setLocationRelativeTo(null);
// close the program when click the X
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// cancel default center of frame
this.setLayout(null);
// add Key Listener
this.addKeyListener(this);
randomarr = randomArr(arr);
// get winArr
win();
}
public int[][] randomArr(int[] arr){
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
int index = random.nextInt(arr.length);
int temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
int[][] twoDarr= new int[4][4];
int k = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (arr[k] == 0){
zerolocationx = i;
zerolocationy = j;
}
twoDarr[i][j] = arr[k];
k++;
}
}
return twoDarr;
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
// game over
if (winFlag){
return;
}
int keyCode = e.getKeyCode();
switch (keyCode){
case aKeyCode:
// view origin image
// clear
this.getContentPane().removeAll();
// load origin image
// set JLabel
JLabel jLabel = new JLabel(new ImageIcon(completePath + "\\" + "all.jpg"));
// set JLabel location
jLabel.setBounds(83, 134, 420, 420);
// set border
// 0 present RAISED, 1 present LOWERED
jLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
// get panel
this.getContentPane().add(jLabel);
// set background image
JLabel bg = new JLabel(new ImageIcon(backgroundPath));
bg.setBounds(40, 40, 508, 560);
this.getContentPane().add(bg);
// refresh interface
this.getContentPane().repaint();
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
// game over
if (winFlag){
return;
}
// Listener
// left:37, up:38, right:39, bottom:40
int keyCode = e.getKeyCode();
// System.out.println("keyboard represent code is:" + keyCode);
switch (keyCode){
case leftKeyCode:
changepatchlocation(0, 1);
break;
case upKeyCode:
changepatchlocation(1, 0);
break;
case rightKeyCode:
changepatchlocation(0, -1);
break;
case bottomKeyCode:
changepatchlocation(-1, 0);
break;
case aKeyCode:
initialImage();
break;
case cheatCode:
cheat();
break;
}
}
private void cheat() {
randomarr = winArr;
initialImage();
}
private void win(){
int k = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
winArr[i][j] = k;
k++;
}
}
winArr[0][0] = 1;
winArr[3][3] = 0;
}
private void changepatchlocation(int codex, int codey) {
if (zerolocationx + codex < 0 || zerolocationx + codex > 3 || zerolocationy + codey < 0 || zerolocationy + codey > 3){
return;
}
randomarr[zerolocationx][zerolocationy] = randomarr[zerolocationx + codex][zerolocationy + codey];
randomarr[zerolocationx + codex][zerolocationy + codey] = 0;
zerolocationx = zerolocationx + codex;
zerolocationy = zerolocationy + codey;
count++;
initialImage();
}
@Override
public void actionPerformed(ActionEvent e) {
Random r = new Random();
Object source = e.getSource();
if (source == replayJMenuItem){
randomarr = randomArr(arr);
count = 0;
initialImage();
} else if (source == reLoginJMenuItem) {
this.setVisible(false);
new LoginJFrame(300, 400);
} else if (source == closeJMenuItem) {
System.exit(0);
} else if (source == focusmeJMenuItem) {
JDialog jDialog = new JDialog();
JLabel jLabel = new JLabel(new ImageIcon("JigsawPuzzle\\image\\focusme.jpg"));
jLabel.setBounds(0, 0, 934, 936);
jDialog.getContentPane().add(jLabel);
jDialog.setSize(1000, 1000);
jDialog.setAlwaysOnTop(true);
jDialog.setLocationRelativeTo(null);
// if JDialog don't close, we can't continue
jDialog.setModal(true);
jDialog.setVisible(true);
} else if (source == prettyGirl) {
int i = r.nextInt(13) + 1;
imageType = "girl";
numImage = i;
completePath = imagepath + "\\" + imageType + "\\" + imageType + numImage;
randomarr = randomArr(arr);
count = 0;
initialImage();
}else if (source == animal){
int i = r.nextInt(8) + 1;
imageType = "animal";
numImage = i;
completePath = imagepath + "\\" + imageType + "\\" + imageType + numImage;
randomarr = randomArr(arr);
count = 0;
initialImage();
} else if (source == sport) {
int i = r.nextInt(10) + 1;
imageType = "sport";
numImage = i;
completePath = imagepath + "\\" + imageType + "\\" + imageType + numImage;
randomarr = randomArr(arr);
count = 0;
initialImage();
}
}
}
8.2登录界面的代码
package com.orange.ui;
import test.CodeUtil;
import test.UserMember;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Objects;
public class LoginJFrame extends JFrame implements MouseListener {
private String codeStr = CodeUtil.getCode();
private String logInImage = "JigsawPuzzle\\image\\login\\登录按钮.png";
private String registerImage = "JigsawPuzzle\\image\\login\\注册按钮.png";
JButton login = new JButton();
JButton register = new JButton();
JTextField usernameText = new JTextField();
JPasswordField passwordText = new JPasswordField();
JTextField codeText = new JTextField();
JLabel rightCode = new JLabel();
//创建一个集合存储正确的用户名和密码
static ArrayList<UserMember> list = new ArrayList<>();
static {
list.add(new UserMember("zhangsan","123"));
list.add(new UserMember("lisi","1234"));
}
public LoginJFrame(int width, int height){
//初始化界面
initJFrame(width, height);
//在这个界面中添加内容
initView();
//让当前界面显示出来
this.setVisible(true);
}
public void initView() {
// clear
this.getContentPane().removeAll();
//1. 添加用户名文字
JLabel usernameImage = new JLabel(new ImageIcon("JigsawPuzzle\\image\\login\\用户名.png"));
usernameImage.setBounds(116, 135, 47, 17);
this.getContentPane().add(usernameImage);
//2.添加用户名输入框
usernameText.setBounds(195, 134, 200, 30);
this.getContentPane().add(usernameText);
//3.添加密码文字
JLabel passwordImage = new JLabel(new ImageIcon("JigsawPuzzle\\image\\login\\密码.png"));
passwordImage.setBounds(130, 195, 32, 16);
this.getContentPane().add(passwordImage);
//4.密码输入框
passwordText.setBounds(195, 195, 200, 30);
this.getContentPane().add(passwordText);
//验证码提示
JLabel codeImage = new JLabel(new ImageIcon("JigsawPuzzle\\image\\login\\验证码.png"));
codeImage.setBounds(133, 256, 50, 30);
this.getContentPane().add(codeImage);
//验证码的输入框
codeText.setBounds(195, 256, 100, 30);
this.getContentPane().add(codeText);
// 验证码内容
//设置内容
rightCode.setText(codeStr);
//位置和宽高
rightCode.setBounds(300, 256, 50, 30);
//添加到界面
this.getContentPane().add(rightCode);
//5.添加登录按钮
login.setBounds(123, 310, 128, 47);
login.setIcon(new ImageIcon(logInImage));
//去除按钮的默认边框
login.setBorderPainted(false);
//去除按钮的默认背景
login.setContentAreaFilled(false);
this.getContentPane().add(login);
//6.添加注册按钮
register.setBounds(256, 310, 128, 47);
register.setIcon(new ImageIcon(registerImage));
//去除按钮的默认边框
register.setBorderPainted(false);
//去除按钮的默认背景
register.setContentAreaFilled(false);
this.getContentPane().add(register);
// 鼠标点击监听
login.addMouseListener(this);
register.addMouseListener(this);
rightCode.addMouseListener(this);
//7.添加背景图片
JLabel background = new JLabel(new ImageIcon("JigsawPuzzle\\image\\login\\background.png"));
background.setBounds(0, 0, 470, 390);
this.getContentPane().add(background);
// refresh interface
this.getContentPane().repaint();
}
public void initJFrame(int width, int height) {
this.setSize(width, height);//设置宽高
this.setTitle("拼图小游戏--登录");//设置标题
this.setDefaultCloseOperation(3);//设置关闭模式
this.setLocationRelativeTo(null);//居中
this.setAlwaysOnTop(true);//置顶
this.setLayout(null);//取消内部默认布局
}
//要展示用户名或密码错误
public void showJDialog(String content) {
//创建一个弹框对象
JDialog jDialog = new JDialog();
//给弹框设置大小
jDialog.setSize(200, 150);
//让弹框置顶
jDialog.setAlwaysOnTop(true);
//让弹框居中
jDialog.setLocationRelativeTo(null);
//弹框不关闭永远无法操作下面的界面
jDialog.setModal(true);
//创建Jlabel对象管理文字并添加到弹框当中
JLabel warning = new JLabel(content);
warning.setBounds(0, 0, 200, 150);
jDialog.getContentPane().add(warning);
//让弹框展示出来
jDialog.setVisible(true);
}
@Override
public void mouseClicked(MouseEvent e) {
Object source = e.getSource();
if (source == rightCode){
codeStr = CodeUtil.getCode();
initView();
} else if (source == login) {
String utext = usernameText.getText();
String ptext = passwordText.getText();
String ctext = codeText.getText();
if (Objects.equals(ctext, codeStr)){
boolean flag = userPasswordCorrect(list, utext, ptext);
if (flag){
// showJDialog("登录成功, 开始游戏!");
this.setVisible(false);
GameJFrame gameJFrame = new GameJFrame(603, 680);
}else {
showJDialog("用户名或密码错误, 请重新填写!");
}
}else {
showJDialog("验证码错误, 请重新填写!");
}
// codeStr = CodeUtil.getCode();
// initView();
} else if (source == register) {
RegisterJFrame registerJFrame = new RegisterJFrame(500, 600);
}
}
// judgment the Username and Password correct
// need list and Username text and Password text
public boolean userPasswordCorrect(ArrayList<UserMember> arrayList, String usernameText, String passwordText){
boolean flag = false;
for (UserMember userMember : list) {
if (Objects.equals(usernameText, userMember.getUsername()) && Objects.equals(passwordText, userMember.getPassword())) {
flag = true;
break;
}
}
return flag;
}
@Override
public void mousePressed(MouseEvent e) {
Object source = e.getSource();
if (source == login){
logInImage = "JigsawPuzzle\\image\\login\\登录按下.png";
initView();
} else if (source == register) {
registerImage = "JigsawPuzzle\\image\\login\\注册按下.png";
initView();
}
}
@Override
public void mouseReleased(MouseEvent e) {
Object source = e.getSource();
if (source == login){
logInImage = "JigsawPuzzle\\image\\login\\登录按钮.png";
initView();
} else if (source == register) {
registerImage = "JigsawPuzzle\\image\\login\\注册按钮.png";
initView();
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
登录界面中的CodeUtil类产生验证码
package test;
import java.util.Random;
public class CodeUtil {
// 开发验证码
// 需求:
// 定义方法实现随机产生一个5位的验证码
// 验证码格式:
// 长度为5
// 有四位是大写字母或者小写字母
// 有一位是数字
public static String getCode(){
// 65--90,97--122
String code = "";
Random r = new Random();
for (int i = 0; i < 4; i++) {
int random = r.nextInt(2);
if (random == 0){
// 大写字母
int a = r.nextInt(26) + 65;
code = code + (char) a;
} else if (random == 1) {
// 小写字母
int a = r.nextInt(26) + 97;
code = code + (char) a;
}
}
// System.out.println(code);
int num = r.nextInt(10);
int location = r.nextInt(5);
String newCode = "";
if (location == 4){
newCode = code + num;
}else {
for (int i = 0; i < code.length(); i++) {
if (i == location){
newCode = newCode + num + code.charAt(i);
continue;
}else {
newCode = newCode + code.charAt(i);
}
}
}
return newCode;
}
}
9.存在的问题
当我在登录成功的上面加上showJDialog()函数时, 程序会不断地访问鼠标点击事件, 出现弹窗关掉又出现的情况, 最后我没有好的解决办法只好将showJDialog()注释掉.