1.GUI概述和GUI与CLI的区别
![](https://i-blog.csdnimg.cn/blog_migrate/f0b80fb040c8a1111cf3308f23a755c7.png)
2.java.awt和javax.swing包的区别
Java为GUI提供的对象都存在java.Awt和javax.Swing两个包中。
java.awt:Abstract Window ToolKit (抽象窗口工具包),需要调用本地系统方法实现功能。属重量级控件。
javax.swing:在AWT的基础上,建立的一套图形界面系统,其中提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级控件。
javax--- java扩展包
轻量级(移植性好),重量级(移植性差)说的是与系统的关联性的大小
3.GUI中组件继承图
![](https://i-blog.csdnimg.cn/blog_migrate/cad2c514a94524484de06d2167a3b64f.png)
那么,从哪里学起呢??
Component??Container??
都不是,应该从Frame学起。
![](https://i-blog.csdnimg.cn/blog_migrate/454bd2e7090c8b6e65c057589daf3778.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6b113dc329b3004b72db014a40ffabab.png)
Frame继承的方法太多了,,,,但是Frame本身的方法不多。
![](https://i-blog.csdnimg.cn/blog_migrate/307b3f8e7008d230105301255d9c68be.png)
4.HelloWorld窗体案例
===============================================
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象
// Frame f = new Frame();
// Frame(String title)
Frame f = new Frame("林青霞");//设置窗体标题可以用构造方法
// 设置窗体标题
f.setTitle("HelloWorld");//设置窗口标题的第二个方法
// 设置窗体大小
f.setSize(400, 300); // 单位:像素
// 设置窗体位置(就是设置程序一运行就弹出窗口的位置,默认左上角)
f.setLocation(400, 200);
// 调用一个方法,设置让窗体可见
// f.show();//已过时
f.setVisible(true);//setVisible一般放在最后写,因为设置好窗体才看到窗体比较好(就好像穿好衣服化好妆出门才好)
// System.out.println("helloworld");
}
}
==================================================
以下是一些解析以及注意的问题
窗体直接点右上角(如图红色关闭区域)关闭不了,而是要强制关闭程序才可以。
![](https://i-blog.csdnimg.cn/blog_migrate/caea343a6742a402db6d952bff644569.png)
窗体太小,调大一点
![](https://i-blog.csdnimg.cn/blog_migrate/0182574a0c56da5ada15c90c7ce8988c.png)
改变打开时窗体弹出的位置
![](https://i-blog.csdnimg.cn/blog_migrate/5348ac54015d126f8baba5aa881be7fa.png)
5.优化HelloWorld窗体案例代码
public class FrameDemo2 {
public static void main(String[] args) {
// 创建对象
Frame f = new Frame("方法调用的前后关系");
// f.setVisible(true);
// try {
// Thread.sleep(3000);//让线程睡一会的目的就是说setVisible要放到最后而不要放在前面,也就是先设置窗体位置大小,再显示窗体,就好像先穿衣服,打扮再出门。
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// // f.setSize(400, 300);
// // Dimension(int width, int height)
// Dimension d = new Dimension(400, 300);
// f.setSize(d);
// // f.setLocation(400, 200);
// // Point(int x, int y)
// Point p = new Point(400, 200);
// f.setLocation(p);
// 一个方法搞定
f.setBounds(400, 200, 400, 300);
f.setVisible(true);
}
}
============================================
以下是解析
f.setSize(400, 300);
等价于
// Dimension(int width, int height)
// Dimension d = new Dimension(400, 300);
// f.setSize(d);
=================================
f.setLocation(400, 200);
等价于
// Point(int x, int y)//point是点的意思
// Point p = new Point(400, 200);
// f.setLocation(p);
====================================
其实,
// 设置窗体大小
f.setSize(400, 300); // 单位:像素
// 设置窗体位置
f.setLocation(400, 200);
以上两行代码直接可以用一句来代替
// 一个方法搞定
f.setBounds(400, 200, 400, 300);
也就是,最终三行代码搞掂
![](https://i-blog.csdnimg.cn/blog_migrate/7287642348be863bcee2768a30a6d45c.png)
============================================================
6.事件监听机制原理概述及举例
事件监听机制:
A:事件源 事件发生的地方
B:事件 就是要发生的事情
C:事件处理 就是针对发生的事情做出的处理方案
D:事件监听 就是把事件源和事件关联起来
举例:人受伤事件。
事件源:人(具体的对象)
Person p1 = new Person("张三");
Person p2 = new Person("李四");
事件:受伤
interface 受伤接口 {
一拳();
一脚();
一板砖();
}
事件处理:
受伤处理类 implements 受伤接口 {
一拳(){ System.out.println("鼻子流血了,送到卫生间洗洗"); }
一脚(){ System.out.println("晕倒了,送到通风处"); }
一板砖(){ System.out.println("头破血流,送到太平间"); }
}
事件监听:
p1.注册监听(受伤接口)
7.窗体关闭案例
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象
Frame f = new Frame("窗体关闭案例");
// 设置窗体属性
f.setBounds(400, 200, 400, 300);
// 让窗体关闭
//事件源---f为事件源
//事件:对窗体的处理
//事件处理:关闭窗口(System.exit(0));//退出虚拟机
//事件监听
f.addWindowListener(new WindowListener() {//匿名内部类
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);//退出虚拟机
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
});
// 设置窗体可见
f.setVisible(true);
}
}
添加事件监听后窗体就可以通过点右上角红色的关闭按钮关闭了
8.适配器设计模式讲解
如上面代码可以看见,代码非常多且累赘,那些并不需要(甚至说不应该或者说不能)实现的方法也强迫要实现
问题:
* 接口(方法比较多) -- 实现类(仅仅使用一个,也得把其他的实现给提供了,哪怕是空实现)
* 太麻烦了。
* 解决方案:
* 接口(方法比较多) -- 适配器类(实现接口,仅仅空实现) -- 实现类(用哪个重写哪个)//适配器类实现了分离
================================================
首先新建一个接口
/*
* 针对用户操作的四种功能
*/
public interface UserDao {
public abstract void add();
public abstract void delete();
public abstract void update();
public abstract void find();
}
=========================================
然后实现这个接口//这个实现类需要实现全部方法比较麻烦
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("添加功能");
}
@Override
public void delete() {
System.out.println("删除功能");
}
@Override
public void update() {
System.out.println("修改功能");
}
@Override
public void find() {
System.out.println("查找功能");
}
}
====================================================
测试类中
public class UserDaoDemo {
public static void main(String[] args) {
UserDao ud = new UserDaoImpl();
ud.add();//为了用add方法必须把其余三个方法也实现了,不太合理
}
}
=====================================================
下面,加入适配器
先建一个抽象类(适配器)实现UserDao接口(空实现)
public abstract class UserAdapter implements UserDao {
@Override
public void add() {
}
@Override
public void delete() {
}
@Override
public void update() {
}
@Override
public void find() {
}
}
===========================================================
然后,新建一个类实现UserDao接口,但是不直接实现UserDao,而是继承UserAdapter (因为它实现了那个接口)
public class UserDaoImpl2 extends UserAdapter {
@Override
public void add() {
System.out.println("添加功能");
}
}
//UserDaoImpl2 比UserDapImpl1简洁多了
================================================
测试类中
public class UserDaoDemo {
public static void main(String[] args) {
// UserDao ud = new UserDaoImpl();
// ud.add();
// 我没有说我们需要四种功能都实现啊。
UserDao ud2 = new UserDaoImpl2();
ud2.add();
}
}
============================================
附上新建截图
![](https://i-blog.csdnimg.cn/blog_migrate/66c2e67b660023d21324f448e585d79e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/957069f561ccc7a04b54b1cf99e0d08c.png)
9.适配器类改进窗体关闭案例
原来代码是这样的
![](https://i-blog.csdnimg.cn/blog_migrate/8e834d0f834cb0e4863b79bb4e919492.png)
用适配器改进后
//用适配器类改进
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
简洁了很多
==================================================
10窗体添加按钮并对按钮添加事件案例
需求:把按钮添加到窗体,并对按钮添加一个点击事件。
A:创建窗体对象
B:创建按钮对象
C:把按钮添加到窗体
D:窗体显示
==============================================
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象
Frame f = new Frame("添加按钮");
// 设置属性
f.setBounds(400, 200, 400, 300);
// 设置布局为流式布局
f.setLayout(new FlowLayout());
// 创建按钮对象
Button bu = new Button("点我啊");
// bu.setSize(20, 10);
// 把按钮添加到窗体
f.add(bu);
// 设置窗体可以关闭
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
bu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("你再点试试");
}
});
// 窗体显示
f.setVisible(true);
}
}
=================================================
下面是一些解析
首先讲一下为什么要f.setLayout(new FlowLayout());
这个涉及窗体布局方案的问题
![](https://i-blog.csdnimg.cn/blog_migrate/ce9dc4673c9e02b2716d047c3d58372d.png)
如果不设置布局的话,默认是边界布局(BoderLayout),但是可以看到,这个按钮填充了整个窗体
![](https://i-blog.csdnimg.cn/blog_migrate/615a4e86f3517a1dcd815d1214cfb971.png)
因为边界布局分东,南,西,北,中按钮默认在中间,而其它位置有没有任何东西,所以它填充满了
整个窗体
还有名字忘了不要紧,会查就行---setLayout传的参数就是LayoutManager(接口)
![](https://i-blog.csdnimg.cn/blog_migrate/7a6fd8ca323168b058864c5a0462be6f.png)
还有适配器的问题,为什么ActionListener不用适配器呢?---原因是,整个接口本来就只需要实现一个方法,没必要动用到适配器类
![](https://i-blog.csdnimg.cn/blog_migrate/7606edd328876b44ddc8f9c40d8c7851.png)
运行示例
![](https://i-blog.csdnimg.cn/blog_migrate/14f92d661e9cf7dd73780ad769e36de2.png)
11.把文本框的值转移到文本域案例
案例预览
需求:如下图
把文本框数据转移到文本域
![](https://i-blog.csdnimg.cn/blog_migrate/229d377a16069350c0817204c13177bb.jpeg)
=======================================================
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象
Frame f = new Frame("数据转移");
// 设置窗体属性和布局
f.setBounds(400, 200, 400, 300);
f.setLayout(new FlowLayout());
// 创建文本框
final TextField tf = new TextField(20);
// 创建按钮
Button bu = new Button("数据转移");
// 创建文本域
final TextArea ta = new TextArea(10, 40);
// 把组件添加到窗体
f.add(tf);
f.add(bu);
f.add(ta);
// 设置窗体关闭
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// 对按钮添加事件
bu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 获取文本框的值
String tf_str = tf.getText().trim();//trim防止多余空格的输入
// 清空数据
tf.setText("");
// 设置给文本域
// ta.setText(tf_str);
// 追加和换行
ta.append(tf_str + "\r\n");//\r\n起到换行的作用,但是直接\n也可以??
//获取光标
tf.requestFocus();//点击按钮后光标自动回到TextField中
}
});
// 设置窗体显示
f.setVisible(true);
}
}
=================================================
以下为解析以及一些注意事项
TextField一般用列数那个构造方法
![](https://i-blog.csdnimg.cn/blog_migrate/b57cec00d4afa311e82b457f7b2fd7f2.png)
以下的问题在eclipse3.7(JDK1.7)报错,但是在eclipse4.4(JDK1.8)却不报错,我也不知道为什么
附上网上解析:
局部内部类,只能访问被final修饰的局部变量
内部类绝对不能访问非final的成员变量
因为内部类 也是类,他们实例化后存储在堆中;局部变量存储在栈中,所以一般情况而言内部类的声明周期长于局部变量。
试想一个活着的内部类去访问一个声明周期已经结束的局部变量~
因为内部类 也是类,他们实例化后存储在堆中;局部变量存储在栈中,所以一般情况而言内部类的声明周期长于局部变量。
试想一个活着的内部类去访问一个声明周期已经结束的局部变量~
所以,极有可能的原因是: jdk1.8版本内部类成员变量不用final修饰也能访问
![](https://i-blog.csdnimg.cn/blog_migrate/02d9668e9efe0ce973e615d76fbb6d10.png)
以前关于局部内部类的笔记
![](https://i-blog.csdnimg.cn/blog_migrate/cd70f7a9ae6ee227ddac7b56254c1311.png)
解决后
// 创建文本框
final TextField tf = new TextField(20);
// 创建文本域
final TextArea ta = new TextArea(10, 40);
=============================================
获取光标的意图
![](https://i-blog.csdnimg.cn/blog_migrate/773e783df2d46695989c18c3a6b84dee.png)
12.通过鼠标移动到按钮上更改背景色案例
需求:
![](https://i-blog.csdnimg.cn/blog_migrate/2cb5400a12e5e90530a0e39cc9ebe4ca.png)
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象
final Frame f = new Frame("更改背景色");
// 设置窗体属性和布局
f.setBounds(400, 200, 400, 300);
f.setLayout(new FlowLayout());
// 创建四个按钮
Button redButton = new Button("红色");
Button greenButton = new Button("绿色");
Button buleButton = new Button("蓝色");
// 添加按钮
f.add(redButton);
f.add(greenButton);
f.add(buleButton);
// 设置窗体关闭
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// 对按钮添加动作事件
// redButton.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// f.setBackground(Color.RED);
// }
// });
// 对按钮添加鼠标点击事件
// redButton.addMouseListener(new MouseAdapter() {
// @Override
// public void mouseClicked(MouseEvent e) {
// f.setBackground(Color.RED);
// }
// });
// 对按钮添加鼠标的进入事件
redButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
f.setBackground(Color.RED);
}
});
redButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
f.setBackground(Color.WHITE);
}
});
greenButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
f.setBackground(Color.GREEN);
}
});
greenButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
f.setBackground(Color.WHITE);
}
});
buleButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
f.setBackground(Color.BLUE);
}
});
buleButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
f.setBackground(Color.WHITE);
}
});
// 设置窗体显示
f.setVisible(true);
}
}
==============================================
解析
代码看着很长,其实很多重复的内容
动作事件和鼠标事件
![](https://i-blog.csdnimg.cn/blog_migrate/dd41571e668a23bc0e3e05dced60d93c.png)
redButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
f.setBackground(Color.RED);
}
});
鼠标事件用了适配器,因为原监听器接口要实现的方法挺多
mouseEntered: 鼠标移动到按钮区域就变颜色(移动到但是没有点按钮)
mouseExited: 鼠标离开按钮区域就变颜色(离开但是没有点按钮)
====================================================
13.如何控制在文本框里面只能输入数字字符案例
需求:
![](https://i-blog.csdnimg.cn/blog_migrate/35cabadb2a3d62d1ed43510796d8a680.png)
/*
* 你输入的如果是非数字字符,就取消你键盘录入的效果。
*/
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象并设置属性
Frame f = new Frame("不能输入非数字字符");
f.setBounds(400, 200, 400, 300);
f.setLayout(new FlowLayout());
// 创建Label标签对象
Label label = new Label("请输入你的QQ号码,不能是非数字,不信你试试");
TextField tf = new TextField(40);
// 添加到窗体上
f.add(label);
f.add(tf);
// 设置窗体关闭
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// 给文本框添加事件
tf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
// 如果你取得的字符不是数字字符就取消事件
// 思路:先获取字符,判断字符,取消事件
// char getKeyChar()
char ch = e.getKeyChar();
// System.out.println(ch);
if(!(ch>='0' && ch<='9')){
e.consume();//取消该键盘录入事件
}
}
});
// 设置窗体可见
f.setVisible(true);
}
}
===============================================
以下为解析
keyPressed---keyAdapter接口中
![](https://i-blog.csdnimg.cn/blog_migrate/5f500020180907d8d67c925a48384f0c.png)
可以看见,有三个方法,所以适配器替代了原来的监听器
还有,注意几个方法,getKeyChar(),consume() ----都在KeyEvent 类中
![](https://i-blog.csdnimg.cn/blog_migrate/ad00ca9c1f948f6f8be25812e20be873.png)
consume在代码中意思是取消该事件,让事件不再发生。在本案例中是当检测到非法字符时不输入(忽略输入非法字符)
14.一级菜单案例
需求:
/*
* 一级菜单
*/
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象并设置属性
Frame f = new Frame("一级菜单");
f.setBounds(400, 200, 400, 300);
f.setLayout(new FlowLayout());
// 创建菜单栏
MenuBar mb = new MenuBar();
// 创建菜单
Menu m = new Menu("文件");
// 创建菜单项
MenuItem mi = new MenuItem("退出系统");
// 谁添加谁呢
m.add(mi);
mb.add(m);
// 设置菜单栏
f.setMenuBar(mb);
// 设置窗体关闭
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// 设置窗体可见
f.setVisible(true);
}
}
===============================================
一个注意的问题
setMenuBar而不是add
![](https://i-blog.csdnimg.cn/blog_migrate/72ee7d18b92bfa2f2baa4b0b9fb3e7de.png)
15.多级菜单案例
需求
![](https://i-blog.csdnimg.cn/blog_migrate/a0a099cca4c0cca0020df78f25169585.png)
*
* 多级菜单
*/
public class FrameDemo {
public static void main(String[] args) {
// 创建窗体对象并设置属性
final Frame f = new Frame("多级菜单");
f.setBounds(400, 200, 400, 300);
f.setLayout(new FlowLayout());
final String name = f.getTitle();
// 创建菜单栏
MenuBar mb = new MenuBar();
// 创建菜单
Menu m1 = new Menu("文件");
Menu m2 = new Menu("更改名称");
// 创建菜单项
final MenuItem mi1 = new MenuItem("好好学习");
final MenuItem mi2 = new MenuItem("天天向上");
MenuItem mi3 = new MenuItem("恢复标题");
MenuItem mi4 = new MenuItem("打开记事本");
MenuItem mi5 = new MenuItem("退出系统");
// 谁添加谁呢
m2.add(mi1);
m2.add(mi2);
m2.add(mi3);
m1.add(m2);
m1.add(mi4);
m1.add(mi5);
mb.add(m1);
// 设置菜单栏
f.setMenuBar(mb);
// 设置窗体关闭
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
mi1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f.setTitle(mi1.getLabel());//getLabel表示这个Item的名称是什么就把它设置为Frame的标题
}
});
mi2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f.setTitle(mi2.getLabel());
}
});
mi3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f.setTitle(name);//name为最初的标题
}
});
mi4.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Runtime r = Runtime.getRuntime();//打开记事本,单例模式
try {
r.exec("notepad");
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
mi5.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// 设置窗体可见
f.setVisible(true);
}
}
=======================================================
一些注意事项
前面写final String name = f.getTitle();的作用(原因)
![](https://i-blog.csdnimg.cn/blog_migrate/dd9ad85d6d331a64acc9954ee8a31640.png)
初始默认值为"多级菜单",如上图所示,窗体标题已经被改为"天天向上",所以要恢复初始值不能直接getTitle
16.Netbeans的概述和使用
首先解决安装问题
安装成功的前提是有JDK
配好环境变量
然后,发现还是安装不了
![](https://i-blog.csdnimg.cn/blog_migrate/f0289994b48ec3fa40e81b71c564e95c.png)
用命令行
![](https://i-blog.csdnimg.cn/blog_migrate/b88fce7d42f35f205c736319ff0f74c1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8f5253cb9f054285bac5a58534f27aa2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9a089d3b64093277d486882705a139e0.png)
然后就可以安装了
![](https://i-blog.csdnimg.cn/blog_migrate/9428bc600b51ab20ded4eff02f41e001.png)
NetBeans主要用来做GUI方便,其它并不常用
![](https://i-blog.csdnimg.cn/blog_migrate/5a60cb32bbb81f6cdef7d84d621e1b46.png)
仅有的优点
![](https://i-blog.csdnimg.cn/blog_migrate/502180a1002541e597b98d4cafbfa0ad.png)
拖放使用非常方便
![](https://i-blog.csdnimg.cn/blog_migrate/aad24de6acf30c7b39c8fd720d29f19f.png)
常用快捷键(不用记)
完成代码:ctrl+\ //任何地方按下此组合键,均会提示相应的参考字段;
导入所需包:ctrl+shift+i
格式化代码:alt+shift+F
psvm+Tab 生成Main方法
sout + Tab //生成输出语句
================================
17.模拟四则运算案例
具体内容看视频
![](https://i-blog.csdnimg.cn/blog_migrate/d3ca6b2bfb1043070f897b9a33a8ddbe.png)
![](https://i-blog.csdnimg.cn/blog_migrate/99d81761bfb0c070e0f961d4f4e805c7.png)
在NetBeans中需要手动改动的代码
默认是没有标题的,所以编写初始化标题的代码
public NewJFrameDemo() {
initComponents();
init();
}
private void init() {
this.setTitle("模拟四则运算");
}
// 红字为手写的方法,初始化标题
====================================================
事件监听的代码(计算器四则运算)
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//获取第一个操作数
String firstNumberString = this.firstNumber.getText().trim();
//获取运算符
String selectOperator = this.selectOperator.getSelectedItem().toString();
//获取第二个操作数
String secondNumberString = this.secondNumber.getText().trim();
// System.out.println(firstNumberString);
// System.out.println(selectOperator);
// System.out.println(secondNumberString);
int firstNumber = Integer.parseInt(firstNumberString);
int secondNumber = Integer.parseInt(secondNumberString);
int resultNumber = 0;
switch (selectOperator) {
case "+":
resultNumber = firstNumber + secondNumber;
break;
case "-":
resultNumber = firstNumber - secondNumber;
break;
case "*":
resultNumber = firstNumber * secondNumber;
break;
case "/":
resultNumber = firstNumber / secondNumber;
break;
}
//把结果赋值给结果框
this.resultNumber.setText(String.valueOf(resultNumber));
}
然后修改窗体的图标代码
看图就好
首先建一个cn.itcast.util包
Uiutil类
然后建一个resource包,把图标图片放进包里
![](https://i-blog.csdnimg.cn/blog_migrate/a46a2646fb7e50318f7709c8b5c49b16.png)
Toolkit是抽象类
![](https://i-blog.csdnimg.cn/blog_migrate/72e44e610dccaa36ca04a295e9bc4ae2.png)
在NewJFrame类中改代码
this代表当前对象(窗体)
![](https://i-blog.csdnimg.cn/blog_migrate/eefcb4dca1bb1c39d3d4f36dfd7a06b9.png)
修改后运行
![](https://i-blog.csdnimg.cn/blog_migrate/93ae764c4e643170dcb1a760a2a6eeb0.png)
再设置一下初始运行时窗体的默认位置为居中
在UiUtil类中
//设置窗体居中
public static void setFrameCenter(JFrame jf) {
/*
思路:
A:获取屏幕的宽和高
B:获取窗体的宽和高
C:(用屏幕的宽-窗体的宽)/2,(用屏幕的高-窗体的高)/2作为窗体的新坐标。
*/
//获取工具对象
Toolkit tk = Toolkit.getDefaultToolkit();
//获取屏幕的宽和高
Dimension d = tk.getScreenSize();
double srceenWidth = d.getWidth();
double srceenHeigth = d.getHeight();
//获取窗体的宽和高
int frameWidth = jf.getWidth();
int frameHeight = jf.getHeight();
//获取新的宽和高
int width = (int) (srceenWidth - frameWidth) / 2;
int height = (int) (srceenHeigth - frameHeight) / 2;
//设置窗体坐标
jf.setLocation(width, height);
}
=======================================
在NewJFrame类中
public NewJFrame() {
initComponents();
init();
}
private void init() {
this.setTitle("模拟四则运算");
UiUtil.setFrameImage(this,"jjcc.jpg");
UiUtil.setFrameCenter(this);
}
附上UiUtil类
/**
* 专门做界面效果的类
*
* @author Administrator
*/
public class UiUtil {
private UiUtil() {
}
//修改窗体的图标
public static void setFrameImage(JFrame jf) {
//获取工具类对象
//public static Toolkit getDefaultToolkit():获取默认工具包。
Toolkit tk = Toolkit.getDefaultToolkit();
//根据路径获取图片
Image i = tk.getImage("src\\cn\\itcast\\resource\\user.jpg");
//给窗体设置图片
jf.setIconImage(i);
}
public static void setFrameImage(JFrame jf,String imageName) {
//获取工具类对象
//public static Toolkit getDefaultToolkit():获取默认工具包。
Toolkit tk = Toolkit.getDefaultToolkit();
//根据路径获取图片
Image i = tk.getImage("src\\cn\\itcast\\resource\\"+imageName);
//给窗体设置图片
jf.setIconImage(i);
}
//设置窗体居中
public static void setFrameCenter(JFrame jf) {
/*
思路:
A:获取屏幕的宽和高
B:获取窗体的宽和高
C:(用屏幕的宽-窗体的宽)/2,(用屏幕的高-窗体的高)/2作为窗体的新坐标。
*/
//获取工具对象
Toolkit tk = Toolkit.getDefaultToolkit();
//获取屏幕的宽和高
Dimension d = tk.getScreenSize();
double srceenWidth = d.getWidth();
double srceenHeigth = d.getHeight();
//获取窗体的宽和高
int frameWidth = jf.getWidth();
int frameHeight = jf.getHeight();
//获取新的宽和高
int width = (int) (srceenWidth - frameWidth) / 2;
int height = (int) (srceenHeigth - frameHeight) / 2;
//设置窗体坐标
jf.setLocation(width, height);
}
}
================================================
修改UI----皮肤包(略)
如何修改窗体的皮肤
![](https://i-blog.csdnimg.cn/blog_migrate/7d6eb320afb6e927ac9b9bdca8cda1c5.png)
附上MyLookAndFeel 类
=========================================================
//这里面定义了常见的要使用的皮肤的字符串路径。
public abstract class MyLookAndFeel {
// 系统自带皮肤,5种都能用
public static String SYS_METAL = "javax.swing.plaf.metal.MetalLookAndFeel";
public static String SYS_NIMBUS = "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";
// 有个性
public static String SYS_CDE_MOTIF = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
public static String SYS_WINDOWS = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
public static String SYS_WINDOWS_CLASSIC = "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel";
// JIattoo jar包资源
public static String JTATTOO_ACRYL = "com.jtattoo.plaf.acryl.AcrylLookAndFeel";
public static String JTATTOO_AERO = "com.jtattoo.plaf.aero.AeroLookAndFeel";
// 还可以
public static String JTATTOO_ALUMINUM = "com.jtattoo.plaf.aluminium.AluminiumLookAndFeel";
// 很喜欢
public static String JTATTOO_BERNSTEIN = "com.jtattoo.plaf.bernstein.BernsteinLookAndFeel";
public static String JTATTOO_FAST = "com.jtattoo.plaf.fast.FastLookAndFeel";
// 有个性
public static String JTATTOO_HIFI = "com.jtattoo.plaf.hifi.HiFiLookAndFeel";
public static String JTATTOO_LUNA = "com.jtattoo.plaf.luna.LunaLookAndFeel";
// 很喜欢
public static String JTATTOO_MCWIN = "com.jtattoo.plaf.mcwin.McWinLookAndFeel";
public static String JTATTOO_MINT = "com.jtattoo.plaf.mint.MintLookAndFeel";
// 有个性
public static String JTATTOO_NOIRE = "com.jtattoo.plaf.noire.NoireLookAndFeel";
public static String JTATTOO_SMART = "com.jtattoo.plaf.smart.SmartLookAndFeel";
// liquidlnf.jar包资源
// 很喜欢
public static String LIQUIDINF = "com.birosoft.liquid.LiquidLookAndFeel";
}
========================================================
测试几个看看效果
![](https://i-blog.csdnimg.cn/blog_migrate/ee437f96323ffd9b2f1dbfbf3cbe8f2b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f7d5c7363d58678032d935fd4e113d52.png)
最后,对四则运算案例加入校验和提示
代码(绿字为新增代码)
………………………………………………………………………………………………………………………………
………………………………………………省略前面代码……………………………………………………
//获取第二个操作数
String secondNumberString = this.secondNumber.getText().trim();
//数据校验,必须是数字字符串
String regex = "\\d+";
//校验第一个数
if (!firstNumberString.matches(regex)) {
// System.out.println("数据不匹配");
//public static void showMessageDialog(Component parentComponent,Object message)
JOptionPane.showMessageDialog(this, "第一个操作数不满足要求必须是数字");
this.firstNumber.setText("");
this.firstNumber.requestFocus();
return;//回去吧
}
if (!secondNumberString.matches(regex)) {
// System.out.println("数据不匹配");
//public static void showMessageDialog(Component parentComponent,Object message)
JOptionPane.showMessageDialog(this, "第二个操作数不满足要求必须是数字");
this.secondNumber.setText("");
this.secondNumber.requestFocus();
return;//回去吧
}
//把字符串数据转换为整数
int firstNumber = Integer.parseInt(firstNumberString);
int secondNumber = Integer.parseInt(secondNumberString);
…………………………………………省略后面代码…………………………………………………………
…………………………………………………………………………………………………………………………
附:JOptionPane类方法
![](https://i-blog.csdnimg.cn/blog_migrate/284eff6b50d619a3cb0e74f7b846b57d.png)
运行示例
![](https://i-blog.csdnimg.cn/blog_migrate/cefcf99885b1d08857542ce078fcb0e5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/50d575fc7ca07d7dd95da6c4da2849e6.png)
18.用户登录注册案例
![](https://i-blog.csdnimg.cn/blog_migrate/c4d7d5da4717456c3a9ad6d33ad2b104.png)
包结构
![](https://i-blog.csdnimg.cn/blog_migrate/c7324cd32e55c9f5aa9805eb2ec84653.png)
pojo包下
User类
public class User {
private String username;
private String password;
public User(){}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
}
注意:
![](https://i-blog.csdnimg.cn/blog_migrate/23a57da70083d0c4c48de916a75fd75e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/de80f2ed265b15cf64145487d52515f0.png)
============================================================
dao包下
UserDao接口
*/
public interface UserDao {
/**
* 这是用户登录功能
*
* @param username 用户名
* @param password 密码
* @return 登录是否成功
*/
public abstract boolean login(String username, String password);
/**
* 这是用户注册功能
*
* @param user 被注册的用户信息
*/
public abstract void regist(User user);
}
=======================================================
dao.impl包下UserDaoImpl类(与IO流的是一样的)
public class UserDaoImpl implements UserDao {
//定义文件
private static File file = new File("user.txt");
//类加载的时候就把文件创建
static {
try {
file.createNewFile();
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public boolean login(String username, String password) {
boolean flag = false;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
String[] datas = line.split("=");
if (datas[0].equals(username) && datas[1].equals(password)) {
flag = true;
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return flag;
}
@Override
public void regist(User user) {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(file, true));
bw.write(user.getUsername() + "=" + user.getPassword());
bw.newLine();
bw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bw.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
=============================================================
19.用户登录注册的界面实现,界面跳转
借助于NetBeans实现
![](https://i-blog.csdnimg.cn/blog_migrate/9c4a3525c7c2a4abf9864e826ea5e0d2.png)
再修改一下代码
public LoginFrame() {
initComponents();
init();
}
private void init() {
this.setTitle("登录界面");
UiUtil.setFrameCenter(this);
UiUtil.setFrameImage(this,"user.jpg");
}
注册界面同理,略
![](https://i-blog.csdnimg.cn/blog_migrate/87c9d00709aec320e2ddb781b360543d.png)
接着是界面跳转
dispose----使当前窗体关闭
![](https://i-blog.csdnimg.cn/blog_migrate/971b8c5573c6cd1e6a2f4cce4fe28e45.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d16054438f4ac96ca913944734ecfc7f.png)
this.setResizable(false);
还有就是让窗体大小不可改变
![](https://i-blog.csdnimg.cn/blog_migrate/58f18b7d2c44cd989ab2dc249342ad30.png)
private void init() {
this.setTitle("登录界面");
this.setResizable(false);//窗体大小不可改变
UiUtil.setFrameCenter(this);
UiUtil.setFrameImage(this,"user.jpg");
}
在注册按钮添加事件,跳转到注册界面
![](https://i-blog.csdnimg.cn/blog_migrate/db80a28b13aa6ba59c915ae8bc46c0d8.png)
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
RegistFrame rf = new RegistFrame();
// this.setVisible(false);
rf.setVisible(true);//让注册界面可见
this.dispose();//让登录界面不可见
}
![](https://i-blog.csdnimg.cn/blog_migrate/6709670bb9056db21c5fa48ebc377da8.png)
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
LoginFrame lf = new LoginFrame();
lf.setVisible(true);
this.dispose();
}
======================================================
20. 用户登录注册的最终版
LoginFrame类中
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
this.jtfUsername.setText("");
this.jpfPassword.setText("");
}//GEN-LAST:event_jButton2ActionPerformed
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
/*
思路:
A:获取用户名和密码
B:正则表达式校验用户名和密码
C:创建对象调用功能,返回一个boolean值
D:根据boolean值给出提示
*/
//获取用户名和密码
String username = this.jtfUsername.getText().trim();
String password = this.jpfPassword.getText().trim();
//用正则表达式做数据校验
//定义规则
//用户名规则
String usernameRegex = "[a-zA-z]{5}";
//密码规则
String passwordRegex = "\\w{6,12}";
//校验
if(!username.matches(usernameRegex)) {
JOptionPane.showMessageDialog(this, "用户名不满足条件(5个英文字母组成)");
this.jtfUsername.setText("");
this.jtfUsername.requestFocus();
return;
}
if(!password.matches(passwordRegex)) {
JOptionPane.showMessageDialog(this, "密码不满足条件(6-12个任意单词字符)");
this.jpfPassword.setText("");
this.jpfPassword.requestFocus();
return;
}
//创建对象调用功能,返回一个boolean值
UserDao ud = new UserDaoImpl();
boolean flag = ud.login(username, password);
if(flag){
JOptionPane.showMessageDialog(this, "恭喜你登录成功");
// NewJFrame njf = new NewJFrame();
NewJFrame njf = new NewJFrame(username);
njf.setVisible(true);
this.dispose();
}else {
JOptionPane.showMessageDialog(this, "用户名或者密码有误");
this.jtfUsername.setText("");
this.jpfPassword.setText("");
this.jtfUsername.requestFocus();
}
}
=============================================================
RegistFrame类
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
/*
分析:
A:获取用户名和密码
B:用正则表达式做数据校验
C:封装成用户对象
D:调用用户操作的功能进行注册
E:回到登录界面
*/
//获取用户名和密码
String username = this.jtfUsername.getText().trim();
String password = this.jpfPassword.getText().trim();
//用正则表达式做数据校验
//定义规则
//用户名规则
String usernameRegex = "[a-zA-z]{5}";
//密码规则
String passwordRegex = "\\w{6,12}";
//校验
if(!username.matches(usernameRegex)) {
JOptionPane.showMessageDialog(this, "用户名不满足条件(5个英文字母组成)");
this.jtfUsername.setText("");
this.jtfUsername.requestFocus();
return;
}
if(!password.matches(passwordRegex)) {
JOptionPane.showMessageDialog(this, "密码不满足条件(6-12个任意单词字符)");
this.jpfPassword.setText("");
this.jpfPassword.requestFocus();
return;
}
//封装成用户对象
User user = new User();
user.setUsername(username);
user.setPassword(password);
//调用用户操作的功能进行注册
UserDao ud = new UserDaoImpl();
ud.regist(user);
//给出提示
JOptionPane.showMessageDialog(this, "用户注册成功,回到登录界面");
goLogin();
}
private void goLogin() { //跳转功能
LoginFrame lf = new LoginFrame();
lf.setVisible(true);
this.dispose();
}
补充:四则运算修改
![](https://i-blog.csdnimg.cn/blog_migrate/2310866a0ba30790de9a2f09dd16d710.png)
==============================================
day25补充笔记
注意一个工具"exe4j" jar转exe可执行文件
如何让Netbeans的东西Eclipse能访问。
在Eclipse中创建项目,把Netbeans项目的src下的东西给拿过来即可。
注意:修改项目编码为UTF-8(NetBeans默认编码是UTF-8,而eclipse是GBK)
事件监听机制(理解)
A:事件源
B:事件
C:事件处理
D:事件监听
适配器模式(理解)
A:接口
B:抽象适配器类
C:实现类