传智播客-Java学习笔记day25

1.GUI概述和GUI与CLI的区别
 
2.java.awt和javax.swing包的区别

Java为GUI提供的对象都存在java.Awt和javax.Swing两个包中。

 

 

java.awt:Abstract Window ToolKit (抽象窗口工具包),需要调用本地系统方法实现功能。属重量级控件。
 
javax.swing:在AWT的基础上,建立的一套图形界面系统,其中提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级控件。

 

javax--- java扩展包
 
轻量级(移植性好),重量级(移植性差)说的是与系统的关联性的大小
 
3.GUI中组件继承图
 
那么,从哪里学起呢??
Component??Container??
都不是,应该从Frame学起。
 
 
Frame继承的方法太多了,,,,但是Frame本身的方法不多。
 
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");
    }
}
==================================================
以下是一些解析以及注意的问题
窗体直接点右上角(如图红色关闭区域)关闭不了,而是要强制关闭程序才可以。
 
窗体太小,调大一点
 
改变打开时窗体弹出的位置
 
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 = new Point(400, 200);
        // f.setLocation(p);
====================================
其实,
// 设置窗体大小
        f.setSize(400, 300); // 单位:像素
        // 设置窗体位置
        f.setLocation(400, 200);
以上两行代码直接可以用一句来代替
// 一个方法搞定
        f.setBounds(400, 200, 400, 300);
 
也就是,最终三行代码搞掂
 
============================================================
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();
    }
}
============================================
附上新建截图
 
 
 
9.适配器类改进窗体关闭案例
原来代码是这样的
 
用适配器改进后
 
        //用适配器类改进
        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());
这个涉及窗体布局方案的问题
 
如果不设置布局的话,默认是边界布局(BoderLayout),但是可以看到,这个按钮填充了整个窗体
 
因为边界布局分东,南,西,北,中按钮默认在中间,而其它位置有没有任何东西,所以它填充满了
整个窗体
还有名字忘了不要紧,会查就行---setLayout传的参数就是LayoutManager(接口)
 
 
还有适配器的问题,为什么ActionListener不用适配器呢?---原因是,整个接口本来就只需要实现一个方法,没必要动用到适配器类
 
运行示例
 
11.把文本框的值转移到文本域案例
案例预览
需求:如下图
把文本框数据转移到文本域
 
=======================================================
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一般用列数那个构造方法
 
以下的问题在eclipse3.7(JDK1.7)报错,但是在eclipse4.4(JDK1.8)却不报错,我也不知道为什么
附上网上解析:
局部内部类,只能访问被final修饰的局部变量
内部类绝对不能访问非final的成员变量
  因为内部类 也是类,他们实例化后存储在堆中局部变量存储在栈中,所以一般情况而言内部类的声明周期长于局部变量。
试想一个活着的内部类去访问一个声明周期已经结束的局部变量~ 
所以,极有可能的原因是: jdk1.8版本内部类成员变量不用final修饰也能访问
 
以前关于局部内部类的笔记
 
解决后
// 创建文本框
        final TextField tf = new TextField(20);
       
        // 创建文本域
        final TextArea ta = new TextArea(10, 40);
=============================================
获取光标的意图
 
12.通过鼠标移动到按钮上更改背景色案例
需求:
 
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);
    }
}
==============================================
解析
代码看着很长,其实很多重复的内容
动作事件和鼠标事件
 
redButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                f.setBackground(Color.RED);
            }
        });
鼠标事件用了适配器,因为原监听器接口要实现的方法挺多
 mouseEntered: 鼠标移动到按钮区域就变颜色(移动到但是没有点按钮)
mouseExited: 鼠标离开按钮区域就变颜色(离开但是没有点按钮)
====================================================
13.如何控制在文本框里面只能输入数字字符案例
需求:
 
/*
 * 你输入的如果是非数字字符,就取消你键盘录入的效果
 */
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接口中
 
可以看见,有三个方法,所以适配器替代了原来的监听器
 
 
还有,注意几个方法,getKeyChar(),consume() ----都在KeyEvent 类中
 
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
15.多级菜单案例
需求
*
 * 多级菜单
 */
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();的作用(原因)
 
初始默认值为"多级菜单",如上图所示,窗体标题已经被改为"天天向上",所以要恢复初始值不能直接getTitle
 
16.Netbeans的概述和使用
首先解决安装问题
安装成功的前提是有JDK
配好环境变量
然后,发现还是安装不了

 

用命令行
 
 
 
然后就可以安装了
 
NetBeans主要用来做GUI方便,其它并不常用
 
仅有的优点
 
拖放使用非常方便
常用快捷键(不用记)
完成代码:ctrl+\ //任何地方按下此组合键,均会提示相应的参考字段; 
导入所需包:ctrl+shift+i 
格式化代码:alt+shift+F 
psvm+Tab 生成Main方法 
sout + Tab //生成输出语句
 
================================
17.模拟四则运算案例
具体内容看视频
 
 
在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包,把图标图片放进包里
Toolkit是抽象类
在NewJFrame类中改代码
this代表当前对象(窗体)
修改后运行
再设置一下初始运行时窗体的默认位置为居中
在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----皮肤包(略)
如何修改窗体的皮肤
附上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";
}
========================================================
测试几个看看效果
 
 
最后,对四则运算案例加入校验和提示
代码(绿字为新增代码)
………………………………………………………………………………………………………………………………
………………………………………………省略前面代码……………………………………………………
//获取第二个操作数
        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类方法
 
运行示例
 
 
18.用户登录注册案例
包结构
 
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;
    }
 
 
}
注意:
 
============================================================
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实现
再修改一下代码
 public LoginFrame() {
        initComponents();
        init();
    }
 
    private void init() {
        this.setTitle("登录界面");
        UiUtil.setFrameCenter(this);
        UiUtil.setFrameImage(this,"user.jpg");
    }
 
注册界面同理,略
 
接着是界面跳转
dispose----使当前窗体关闭
 
 
this.setResizable(false);
 
还有就是让窗体大小不可改变
 
 private void init() {
        this.setTitle("登录界面");
        this.setResizable(false);//窗体大小不可改变
        UiUtil.setFrameCenter(this);
        UiUtil.setFrameImage(this,"user.jpg");
    }
在注册按钮添加事件,跳转到注册界面
 
    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        RegistFrame rf = new RegistFrame();
//        this.setVisible(false);
        rf.setVisible(true);//让注册界面可见
        this.dispose();//让登录界面不可见
    }  
 
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();
    }
 
补充:四则运算修改
 
==============================================
 
day25补充笔记
注意一个工具"exe4j" jar转exe可执行文件
 
如何让Netbeans的东西Eclipse能访问。
    在Eclipse中创建项目,把Netbeans项目的src下的东西给拿过来即可。
    注意:修改项目编码为UTF-8(NetBeans默认编码是UTF-8,而eclipse是GBK)
 
事件监听机制(理解)
        A:事件源
        B:事件
        C:事件处理
        D:事件监听
    适配器模式(理解)
        A:接口
        B:抽象适配器类
        C:实现类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值