涉及到的知识:
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 JMenuItemJMenuItem 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 FrameinitialFrame(width, height);// initial JMenuBarinitialJMenuBar();// initial ImageinitialImage();this.setVisible(true);}private void initialImage() {// clearthis.getContentPane().removeAll();// set countJLabel stepCount = new JLabel("步数为:" + count);stepCount.setBounds(50, 30, 100, 20);this.getContentPane().add(stepCount);// set win imageif (randomarr == winArr){JLabel win = new JLabel(new ImageIcon(winPath));win.setBounds(40, 40, 508, 560);this.getContentPane().add(win);winFlag = true;}// set patches imagefor (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {// set JLabelJLabel jLabel = new JLabel(new ImageIcon(completePath + "\\" + randomarr[i][j] + ".jpg"));// set JLabel locationjLabel.setBounds(j * 105 + 83, i * 105 + 134, 105, 105);// set border// 0 present RAISED, 1 present LOWEREDjLabel.setBorder(new BevelBorder(BevelBorder.RAISED));// get panelthis.getContentPane().add(jLabel);}}// set background imageJLabel bg = new JLabel(new ImageIcon(backgroundPath));bg.setBounds(40, 40, 508, 560);this.getContentPane().add(bg);// refresh interfacethis.getContentPane().repaint();}private void initialJMenuBar() {// set JMenuBarJMenuBar jMenuBar = new JMenuBar();// setJMenuJMenu 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 JMenuItemprettyGirl.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 Framethis.setJMenuBar(jMenuBar);}private void initialFrame(int width, int height) {this.setSize(width, height);// set titlethis.setTitle("拼图小游戏");// set frame always on topthis.setAlwaysOnTop(true);// set frame in the center of screenthis.setLocationRelativeTo(null);// close the program when click the Xthis.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);// cancel default center of framethis.setLayout(null);// add Key Listenerthis.addKeyListener(this);randomarr = randomArr(arr);// get winArrwin();}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;}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {// game overif (winFlag){return;}int keyCode = e.getKeyCode();switch (keyCode){case aKeyCode:// view origin image// clearthis.getContentPane().removeAll();// load origin image// set JLabelJLabel jLabel = new JLabel(new ImageIcon(completePath + "\\" + "all.jpg"));// set JLabel locationjLabel.setBounds(83, 134, 420, 420);// set border// 0 present RAISED, 1 present LOWEREDjLabel.setBorder(new BevelBorder(BevelBorder.RAISED));// get panelthis.getContentPane().add(jLabel);// set background imageJLabel bg = new JLabel(new ImageIcon(backgroundPath));bg.setBounds(40, 40, 508, 560);this.getContentPane().add(bg);// refresh interfacethis.getContentPane().repaint();break;}}@Overridepublic void keyReleased(KeyEvent e) {// game overif (winFlag){return;}// Listener// left:37, up:38, right:39, bottom:40int 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();}@Overridepublic 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 continuejDialog.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() {// clearthis.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 interfacethis.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);}@Overridepublic 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 textpublic 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;}@Overridepublic 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();}}@Overridepublic 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();}}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}
}
登录界面中的CodeUtil类产生验证码
package test;import java.util.Random;public class CodeUtil {// 开发验证码// 需求:// 定义方法实现随机产生一个5位的验证码// 验证码格式:// 长度为5// 有四位是大写字母或者小写字母// 有一位是数字public static String getCode(){// 65--90,97--122String 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()注释掉.