目录
1 Info类(static,public,private的理解)
2 MainFrame类
2.1 创建窗口
2.2 创建菜单
2.3 画板网格设计
2.4 底部按钮设置
2.5 菜单功能(“设置”)监听事件
2.6 MainFrame类代码
该类是用来存储一些初始变量的类。比如说连连看窗口左上角坐标,格子的间距,每行每列的格子数,每个格子的长宽,延迟时间。
这些变量有的是不可变的,有的是可变的。不可变的有格子的长宽、每行每列的格子数,格子的间距,使用final定义不可变属性。可变的有连连看窗口左上角坐标以及延迟时间,需要使用set方法。
类中的静态变量:相当于变量放内存中,程序启动时会被set方法修改,只要程序没有中断,改过之后就不会变回来,即使创建了新的类,类中的静态变量也是被修改过的。而带有静态属性的变量,在这个类创建的时候优先被加载。
而public和private的区别是,public不用创建类就能用到这个变量,比如说Info.变量名,private要创建类,才能调用get方法获取变量。
/**
* 存储全局参数
*/
public class Info {
// 公开的 静态的(先加载静态的) 每个格子的尺寸
public static final int PICWIDTH = 38;
public static final int PICHEIGH = 43;
// 定义窗口初始的宽和高
// 每一个图标中间的缝隙
public static final int GAP = 3;
// 声明初始位置
public static int PICX = 481;
public static int PICY = 371;
// 窗口内部初始值(宽有几个格子,长有几个格子)
public static final int MAPWIDTH = 11;
public static final int MAPHEIGH = 9;
// 休眠时间
public static int SLEEPTIME = 0;
// 改变初始位置
public static void setPICX(int picx){
PICX = picx;
}
public static void setPICY(int picy){
PICY = picy;
}
// 改变休眠时间
public static void setSLEEPTIME(int sleepTime){
SLEEPTIME = sleepTime;
}
}
该类是用来做程序界面用的。一个程序界面(窗口)有菜单条、画板。而菜单条上有菜单,画板上有标签、文本以及按钮。要把菜单、标签、文本以及按钮放在窗口上,必须先放在对应的菜单或画板上。最终要实现下图的效果。
首先,创建窗口使用的是JFrame类,直接继承这个类就行了,然后就能直接使用类中的方法。
第一件事,就是创建标题叫连连看的窗口。分别用到setTitle()、setSize()方法,窗口的位置设置使用 setLocationRelativeTo()。然后,显示窗口使用setVisible(true),这个方法放最后使用一次就行了,会把前面设计的窗口都显示出来。最后,使用setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE),该方法可以使窗口关闭时退出程序,在主窗口中需要设置。因此,总结为5个set方法!
import javax.swing.*;
public class Deom extends JFrame {
private void initUi(){
setSize(500,500);
setTitle("连连看");
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
Deom deom = new Deom();
deom.initUi();
}
}
以上代码得到的效果图如下:
创建顺序如下:菜单功能-->菜单-->菜单条-->窗口。
因此,需要一个菜单条对象JMenuBar,一个菜单对象JMenu以及一个菜单条款对象JMenuItem。
先把菜单功能放到菜单上,使用菜单对象.add(菜单功能对象)。然后,把菜单放在菜单条上,使用菜单条对象.add(菜单对象)。最后,把菜单条放在窗口上,直接在窗口的类中使用setJMenuBar(菜单条对象)。总结为1个set和2个add。
菜单设计代码如下:
import javax.swing.*;
public class Deom extends JFrame {
private JMenuItem setting = new JMenuItem("设置相关参数");
private JMenu menu = new JMenu("设置");
private JMenuBar menuBar = new JMenuBar();
private void initUi(){
// 窗口设置
setSize(500,500);
setTitle("连连看");
setLocationRelativeTo(null);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 菜单设置
menu.add(setting);
menuBar.add(menu);
setJMenuBar(menuBar);
setVisible(true);
}
public static void main(String[] args) {
Deom deom = new Deom();
deom.initUi();
}
}
最终菜单效果图如下:
画板网格设计过程:设置画板样式(几行几列)-->在画板上添加按钮-->将画板添加到窗口中。
如果不设计画板样式,则按钮画出来之后,就不知道怎么排列,不知道排几行几列。如下图所示:
画板按钮设置使用setLayout()方法,在里面传入GridLayout,即网格布局对象。写成:setLayout(new GridLayout(行,列))。
画板按钮添加有两步,一是先创建按钮,按钮是放在二维数组中,数组的类型为JButton,然后遍历这个数组,把按钮取出来再放到画板中,其实这一步只是给画板提供满足样式数量的按钮,排列靠上一步的样式设置。使用如下代码实现:
private JButton[][] buttons = new JButton[MAPHEIGH][MAPWIDTH];; //此时数组中是空的,只是说明数组的维度
private JPanel jPanel = new JPanel(); //创建画板对象
// 画网格
for (int i = 0; i < MAPHEIGH; i++) {
for (int j = 0; j < MAPWIDTH; j++) {
button[i][j] = new JButton(); // 创建按钮对象赋给数组中的第i行第j列元素
jPanel.add(button[i][j]); // 画到画板上
}
}
最终,使用add(jPanel),把画板添加到窗口中,画板效果图如下:
底部按钮是在不同画板中的,需要先创建画板样式,然后创建按钮,然后创建画板,最后将画板添加到窗口中。但这个画板在添加到窗口需要指定位置,不然会和上一个画板冲突。
首先,创建画板样式,1行2列的网格布局。
private JPanel downPanel = new JPanel();
downPanel.setLayout(new GridLayout(1,2)); // 创建画板样式
然后,创建两个按钮对象。
private JButton cheat = new JButton("捕获窗口");
private JButton start = new JButton("开始游戏");
把按钮添加到画板中。
downPanel.add(cheat);
downPanel.add(start);
把画板添加到窗口中,并设置边界布局。
add(downPanel,BorderLayout.SOUTH); // 画板边界布局
以上代码汇总如下:
private JButton cheat = new JButton("捕获窗口");
private JButton start = new JButton("开始游戏");
private JPanel downPanel = new JPanel();
// 底部按钮设置
downPanel.setLayout(new GridLayout(1,2)); // 创建画板样式
downPanel.add(cheat);
downPanel.add(start);
add(downPanel,BorderLayout.SOUTH); // 画板边界布局
底部按钮效果图如下:
如果要实现点击菜单的“设置”时会跳出子菜单,如下图所示。这时就需要对setting对象设置监听事件。使用对象名.addActionListener(new ActionListener())即可。
具体代码如下。在actionPerformed方法中写的就是按下设置功能时会触发的事件!在这里只是举一个例子,具体实现将在下一章进行介绍。
// setting的监听事件
setting.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("你好呀!");
}
});
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
// 继承后就不用new对象来调用了,直接用JFrame对象的方法就行。
public class MainFrame extends JFrame{
/**
* 初始化界面
*/
private JMenuBar menuBar = new JMenuBar(); //菜单条
private JMenu menu = new JMenu("设置"); // 菜单,设置按钮
private JMenuItem setting = new JMenuItem("设置相关参数"); // 菜单"设置"里面的内容
// 静态的东西可以不用new对象就能得到
private int MAPWIDTH = Info.MAPWIDTH;
private int MAPHEIGH = Info.MAPHEIGH;
private LineBorder border = new LineBorder(Color.black); //设置边框颜色
// 画板中的大按钮
private JButton cheat = new JButton("捕获窗口");
private JButton start = new JButton("开始游戏");
// 声明二维数组
private JButton[][] button = new JButton[MAPHEIGH][MAPWIDTH]; //创建MAPHEIGH列MAPWIDTH行的button
private void initUi(){
// 参数设置
setSize(600,430); // 设置窗口长宽
setTitle("外挂"); //设置标签
setLocationRelativeTo(null);//默认居中
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 窗口关闭,程序也关闭
setJMenuBar(menuBar); //设置菜单条
menuBar.add(menu);
menu.add(setting);
// 设置画板
JPanel jPanel = new JPanel();
// 9*11个按钮
jPanel.setLayout(new GridLayout(MAPHEIGH,MAPWIDTH)); // 画板有MAPWIDTH行MAPHEIGH列网格(还没画,画完是铺满的)
add(jPanel);
// 画网格
for (int i = 0; i < MAPHEIGH; i++) {
for (int j = 0; j < MAPWIDTH; j++) {
button[i][j] = new JButton(); // 创建按钮对象赋给数组中的第i行第j列元素
button[i][j].setBorder(border);
jPanel.add(button[i][j]); // 画到画板上
}
}
// 监听事件,setting菜单功能
setting.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 触发事件
SettingDialog settingDialog = new SettingDialog(MainFrame.this);
settingDialog.setVisible(true);
}
});
// 再加个画板放按钮
JPanel buttonPanel = new JPanel();
buttonPanel.add(cheat);
buttonPanel.add(start);
buttonPanel.setLayout(new GridLayout(1,2)); // 按钮样式,铺满1行2列
add(buttonPanel,BorderLayout.SOUTH); // 放上一个画板的下边
setVisible(true); //放最后
}
// 有点像py的if main
public static void main(String[] args) {
MainFrame mainFrame = new MainFrame();
mainFrame.initUi();
}
}
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
// 继承自对话框
public class SettingDialog extends JDialog {
private JFrame parent ; // 主窗口
private JButton submit = new JButton("提交");
private JButton exit = new JButton("取消");
private JTextField picX = new JTextField(Info.PICX+"");
private JTextField picY = new JTextField(Info.PICY+"");
private JTextField sleepTime = new JTextField(Info.SLEEPTIME+"");
public SettingDialog(JFrame parent){
super(parent,true);
this.parent = parent;
initUi();
initlistener();
}
private void initUi(){
setTitle("详细参数设置");
setSize(300,160);
// 注意:默认位置相对于主窗口居中
setLocationRelativeTo(parent);
// 设置布局
// 布局为边框布局 东西南北中 五个位置,空间添加
setLayout(new BorderLayout());
JPanel buttonPanel = new JPanel();
// 按钮
buttonPanel.setLayout(new GridLayout(1,2));
buttonPanel.add(submit);
buttonPanel.add(exit);
add(buttonPanel,BorderLayout.SOUTH);
//
JPanel mainPanel =new JPanel();
mainPanel.setBorder(new TitledBorder("请设置对应的xy轴:")); // 画板的标题
mainPanel.add(new JLabel("x轴:")); //标签
mainPanel.add(picX);
mainPanel.add(new JLabel("y轴:"));
mainPanel.add(picY);
mainPanel.add(new JLabel("休眠时间:"));
mainPanel.add(sleepTime);
mainPanel.setLayout(new GridLayout(3,2,0,0)); //几行几列,上下间距,左右间距
add(mainPanel,BorderLayout.CENTER); //居中
}
private void initlistener(){
submit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int x = Integer.parseInt(picX.getText());
int y = Integer.parseInt(picY.getText());
int sleepTimeNow = Integer.parseInt(sleepTime.getText());
Info.setPICX(x);
Info.setPICY(y);
Info.setSLEEPTIME(sleepTimeNow);
// 按下确定要销毁小窗口
dispose(); // 销毁当前窗口,不销毁进程
}
});
exit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
}
}