黑马程序员——java基础---GUI、正则表达式
一、GUI概述
GUI(GraphicalUser Interface): 又称图形用户界面,是计算机用户与计算机交互的一种方式。
用户与计算机交互的两种方式:
1、GUI(Graphical User Interface):图形用户接口,用图形方式,来显示计算机操作界面,方便直观。
2、CLI(Command LineUser Interface):命令行用户接口,即常见的Dos命令行操作,须记住一些命令,操作不直观。
Java提供的GUI对象都存在于java.Awt和javax.Swing两个包中:
1、java.Awt(Abstract Window Toolkit):即抽象窗口工具包,调用本地系统方法实现功能,属重量级控件。
2、javax.Swing包:在AWT的基础上建立的一套图形界面系统,有更多的组件,且完全由java实现,属轻量级控件。
各组件关系图:
——>布局管理器:对容器中组件排序方式的布局管理。
常见的有五种:
1、FlowLayout:流式布局管理器,从左到右的顺序排列。Panel默认的布局管理器。
2、BorderLayout:边界布局管理器,东,南,西,北,中。Frame默认的布局管理器。
3、GridLayout:网格布局管理器,规则的矩阵。
4、CardLayout:卡片布局管理器,选项卡。
5、GridBagLayout:网格包布局管理器,非规则的矩阵。
如果需要同时用到多种布局方式,可先用Panel进行区域划分,然后再在各自区域中选择布局方式。
简单的窗体创建步骤:
1、创建Frame窗体:
Frame f = new Frame("my Frame");//可设置标题,即窗体名字
2、对窗体进行基本设置:如大小,位置,布局等:
f.setSize(int wight,int hight);//窗体大小设置
f.setLocation(int x,int y);//窗体显示位置设置,横纵坐标
f.setBounds(int x,int y,int wight,int hight),也可以直接用这个方法对大小和位置设置
f.setLayout(Layout layout),参数为指定的布局管理器,如FlowLayout
3、定义组件:
Button b = new Button(“my Button”);//可设置组件的名称
4、将组件通过add方法添加到窗体中:
f.add(b);//将按钮组件添加进窗体
5、让窗体显示:
f.setVisible(boolean b);//通过设置参数是true还是false是否显示窗体
代码示例:
1 class FrameDemo{ 2 public static void main(String[] args){ 3 Frame f = new Frame("my frame"); 4 f.setSize(500, 400); //设置宽和高 5 f.setLocation(400, 200);//设置距离左边和上边的距离 6 f.setLayout(new FlowLayout());//设置流式布局 7 Button but = new Button("我是按钮"); 8 f.add(but);//将按钮添加到窗体中 9 f.setVisible(true);//使窗体可见 10 } 11 }
二、事件监听机制
图形化界面创建好了以后,如果不加事件监听及处理,那么它就只是一个界面而已,并不能实现人机之间的交互。
事件监听机制组成:
1、事件源:即图形界面各组件。
2、事件:每一个事件源都有自己特有的对应事件和共性事件。
3、监听器:将可以触发某一个事件的动作(不只一个动作)都已经封装到了监听器中。
4、事件处理:引发事件后对产生的动作进行处理
其中的前三项在java中都已经定义好。可以直接获取其对象来使用。
监听流程示意图:
事件监听的步骤:
1、确定事件源(容器或组件)。
2、通过事件源对象的addXXXListener()方法将侦听器注册到该事件源上。
3、该方法中接收XXXListener的子类对象,或者XXXListener的子类XXXAdapter的子类对象。一般用匿名内部类来表示。
4、覆盖XXXListener的方法。在覆盖方法的时候,方法的参数一般是XXXEvent类型的变量接收。事件触发后会把事件打包成对象传递给该变量。
示例代码:
1 public class FrameDemo{ 2 //定义该图形中所需的组件的引用。 3 private Frame f; 4 private Button but; 5 FrameDemo(){ 6 init(); 7 } 8 9 public void init(){ 10 f = new Frame("my frame"); 11 //对frame进行基本设置。 12 f.setBounds(300,100,600,500); 13 f.setLayout(new FlowLayout()); 14 15 but = new Button("my button"); 16 //将组件添加到frame中 17 f.add(but); 18 //加载一下窗体上事件。 19 myEvent(); 20 //显示窗体; 21 f.setVisible(true); 22 } 23 private void myEvent(){ 24 f.addWindowListener(new WindowAdapter(){ 25 public void windowClosing(WindowEvent e) 26 { 27 System.exit(0); 28 } 29 }); 30 31 but.addActionListener(new ActionListener(){ 32 public void actionPerformed(ActionEvent e) 33 { 34 System.out.println("退出,按钮干的"); 35 System.exit(0); 36 } 37 }); 38 } 39 public static void main(String[] args){ 40 new FrameDemo(); 41 } 42 }
注意:
1、事件触发后会将事件打包成对象传递给覆写方法中参数的变量。(其中包括事件源对象,通过getSource()或者getComponent()获取。)
2、若用子类实现WindowListener接口,就需要覆盖其中的7个方法,可只用到其中的关闭动作,其他动作未用到,但却必须重写全部。因为WindowLister的子类WindowAdapter已经实现此接口,并覆盖了其中所有方法。那么只需继承WindowAdapter,覆盖需要的方法即可。
3、明确事件,并对事件进行处理,其实,添加什么监听器就需要添加什么事件。
——>对话框:Dialog是一个带标题和边界的顶层窗口,边界一般用于从用户处获得某种形式的输入。也就是对话框,当用户操作不当等情况,系统需要告诉用户时,就用这种形式。当然它也是窗体,所以需要设置大小,显示与否等。
显示目录下信息代码:
1 import java.awt.*; 2 import java.awt.event.*; 3 import java.io.*; 4 5 class WindowTest { 6 // 定义组件 7 private Frame f; 8 private TextField tf; 9 private Button but; 10 private TextArea ta; 11 private Dialog d; 12 private Label lab; 13 private Button okBut; 14 15 WindowTest() { 16 init(); 17 } 18 19 public void init() { 20 // 创建组件对象 21 f = new Frame("my window"); 22 f.setBounds(300, 100, 600, 500); 23 f.setLayout(new FlowLayout()); 24 25 tf = new TextField(60); 26 but = new Button("转到"); 27 ta = new TextArea(25, 70); 28 d = new Dialog(f, "提示信息-self", true); 29 30 d.setBounds(400, 200, 240, 150); 31 d.setLayout(new FlowLayout()); 32 lab = new Label(); 33 okBut = new Button("确定"); 34 35 d.add(lab); 36 d.add(okBut); 37 38 f.add(tf); 39 f.add(but); 40 f.add(ta); 41 42 myEvent(); 43 f.setVisible(true); 44 } 45 46 // 添加事件 47 private void myEvent() { 48 // 确定按钮活动监听 49 okBut.addActionListener(new ActionListener() { 50 public void actionPerformed(ActionEvent e) { 51 d.setVisible(false); 52 } 53 }); 54 // 对话框窗口监听 55 d.addWindowListener(new WindowAdapter() { 56 public void windowClosing(WindowEvent e) { 57 d.setVisible(false); 58 } 59 }); 60 // 文本框键盘监听 61 tf.addKeyListener(new KeyAdapter() { 62 public void keyPressed(KeyEvent e) { 63 if (e.getKeyCode() == KeyEvent.VK_ENTER) 64 showDir(); 65 } 66 }); 67 68 // 按钮活动监听 69 but.addActionListener(new ActionListener() { 70 public void actionPerformed(ActionEvent e) { 71 showDir(); 72 73 } 74 }); 75 76 // 窗口监听 77 f.addWindowListener(new WindowAdapter() { 78 public void windowClosing(WindowEvent e) { 79 System.exit(0); 80 } 81 }); 82 } 83 84 // 列出目录 85 private void showDir() { 86 String dirPath = tf.getText(); 87 88 File dir = new File(dirPath); 89 90 if (dir.exists() && dir.isDirectory()) { 91 ta.setText(""); 92 String[] names = dir.list(); 93 for (String name : names) { 94 ta.append(name + "\r\n"); 95 } 96 } else { 97 String info = "您输入的信息:" + dirPath + "是错误的。请重输"; 98 lab.setText(info); 99 d.setVisible(true); 100 } 101 } 102 103 public static void main(String[] args) { 104 new WindowTest(); 105 } 106 }
菜单的继承体系图:Menu中可以添加Menu也可以添加MenuItem。
简单记事本代码:
1 package filetools; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.io.*; 6 7 public class MenuTest { 8 // 定义组件 9 private Frame f; 10 private MenuBar bar; 11 private TextArea ta; 12 private Menu fileMenu; 13 private MenuItem openItem, saveItem, closeItem; 14 private FileDialog openDia, saveDia; 15 private File file; 16 17 MenuTest() { 18 init(); 19 } 20 21 public void init() { 22 //穿件组建对象并进行基本设置 23 f = new Frame("my window"); 24 f.setBounds(300, 100, 650, 600); 25 26 bar = new MenuBar(); 27 ta = new TextArea(); 28 fileMenu = new Menu("文件"); 29 openItem = new MenuItem("打开"); 30 saveItem = new MenuItem("保存"); 31 closeItem = new MenuItem("退出"); 32 33 fileMenu.add(openItem); 34 fileMenu.add(saveItem); 35 fileMenu.add(closeItem); 36 bar.add(fileMenu); 37 38 f.setMenuBar(bar); 39 openDia = new FileDialog(f, "我要打开", FileDialog.LOAD); 40 saveDia = new FileDialog(f, "我要保存", FileDialog.SAVE); 41 f.add(ta); 42 myEvent(); 43 f.setVisible(true); 44 } 45 46 //定义事件 47 private void myEvent() { 48 //保存条目活动监听 49 saveItem.addActionListener(new ActionListener() { 50 public void actionPerformed(ActionEvent e) { 51 if (file == null) { 52 saveDia.setVisible(true); 53 String dirPath = saveDia.getDirectory(); 54 String fileName = saveDia.getFile(); 55 if (dirPath == null || fileName == null) 56 return; 57 file = new File(dirPath, fileName); 58 } 59 try { 60 BufferedWriter bufw = new BufferedWriter(new FileWriter( 61 file)); 62 String text = ta.getText(); 63 bufw.write(text); 64 bufw.close(); 65 } catch (IOException ex) { 66 throw new RuntimeException(); 67 } 68 } 69 }); 70 // 打开条目活动监听 71 openItem.addActionListener(new ActionListener() { 72 public void actionPerformed(ActionEvent e) { 73 openDia.setVisible(true); 74 String dirPath = openDia.getDirectory(); 75 String fileName = openDia.getFile(); 76 if (dirPath == null || fileName == null) 77 return; 78 ta.setText(""); 79 file = new File(dirPath, fileName); 80 try { 81 BufferedReader bufr = new BufferedReader(new FileReader( 82 file)); 83 String line = null; 84 while ((line = bufr.readLine()) != null) { 85 ta.append(line + "\r\n"); 86 } 87 bufr.close(); 88 } catch (IOException ex) { 89 throw new RuntimeException("读取失败"); 90 } 91 } 92 }); 93 // 关闭条目活动监听 94 closeItem.addActionListener(new ActionListener() { 95 public void actionPerformed(ActionEvent e) { 96 System.exit(0); 97 } 98 }); 99 f.addWindowListener(new WindowAdapter() { 100 public void windowClosing(WindowEvent e) { 101 System.exit(0); 102 } 103 }); 104 } 105 106 public static void main(String[] args) { 107 new MenuTest(); 108 } 109 }
三、正则表达式
概念:符合一定规则的表达式。
作用:用于专门操作字符串。
特点:用一些特定的符号来表示一些代码操作,这样可以简化书写。
好处:可以简化对字符串的复杂操作。
缺点:符合定义越多,正则越长,阅读性越差。
常见规则:
1、字符类
[abc]:表示a、b或 c
[^abc]:表示任何字符,除了 a、b或 c
[a-zA-Z]:表示a到 z或 A 到 Z
[a-d[m-p]]:表示a到 d或 m 到 p([a-dm-p](并集))
[a-z&&[def]]:d、e或 f(交集)
[a-z&&[^bc]]:表示a到 z,除了 b和 c:[ad-z](减去)
[a-z&&[^m-p]]:表示a到 z,而非 m到 p:[a-lq-z](减去)
2、预定义字符
. : 任何字符(与行结束符可能匹配也可能不匹配)
\d:数字:[0-9]
\D:非数字: [^0-9]
\s:空白字符:[ \t\n\x0B\f\r]
\S:非空白字符:[^\s]
\w:单词字符:[a-zA-Z_0-9]
\W:非单词字符:[^\w]
3、边界匹配符
^:行的开头
$ :行的结尾
\b:单词边界
\B:非单词边界
\A:输入的开头
\G:上一个匹配的结尾
\Z:输入的结尾,仅用于最后的结束符(如果有的话)
\z:输入的结尾
4、Greedy数量词
X? :X出现一次或一次也没有
X*:X出现零次或多次
X+: X出现一次或多次
X{n}:X恰好 n次
X{n,}:X至少 n次
X{n,m}X:至少 n次,但是不超过 m 次
5、组和捕获
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组:
1、((A)(B(C)))
2、\A
3、(B(C))
4、(C)
组零始终代表整个表达式,在替换中常用$匹配组的内容。
操作方法:
1、匹配:matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。
2、切割:split()。
3、替换:replaceAll(regex,str)。如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。
4、获取:将字符串中的符合规则的子串取出。
操作步骤:
1、将正则表达式封装成对象。
2、让正则对象和要操作的字符串相关联。
3、关联后,获取正则匹配引擎。
4、通过引擎对符合规则的子串进行操作,比如取出。
邮件地址校验代码:
1 //需求:对邮件地址进行校验。 2 class CheckMail{ 3 public static void main(String[] args){ 4 String mail = "123a809bc@sina.com.cn"; 5 String regex = "\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";//较为精确 6 regex = "\\w+@\\w+(\\.\\w+)+";//相对不太精确的匹配。 7 boolean b = mail.matches(regex); 8 System.out.println(b); 9 } 10 }
网络爬虫代码:
1 /* 网络爬虫 2 实际上是一个功能,用于搜集网络上的指定信息 3 需求:可用于收集邮箱,qq号等之类的信息。 4 */ 5 import java.net.*; 6 import java.util.regex.*; 7 import java.io.*; 8 class Spider{ 9 public static void main(String[] args)throws Exception{ 10 //getFileMail(); 11 getWebMail(); 12 } 13 //获取网页中mail 14 public static void getWebMail()throws Exception{ 15 //封装网页地址 16 URL url = new URL("http://tieba.baidu.com/p/1390896758"); 17 //连接服务器 18 URLConnection conn = url.openConnection(); 19 //带缓冲区的网页读取流 20 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 21 String line = null; 22 //定义匹配邮件地址的正则表达式 23 String regex = "\\w+@\\w+(\\.\\w+)+"; 24 Pattern p = Pattern.compile(regex);//封装正则表达式 25 //读取网页数据 26 while ((line = br.readLine()) != null){ 27 //正则关联数据 28 Matcher m = p.matcher(line); 29 //寻找匹配邮箱 30 while (m.find()){ 31 System.out.println(m.group());//输出匹配邮箱 32 } 33 } 34 } 35 36 //获取指定文档中的邮件地址。使用获取功能。Pattern Matcher 37 public static void getFileMail()throws Exception{ 38 //将文件封装成对象 39 File file = new File("E:\\Java Study\\Practice\\day25\\mail.txt"); 40 //创建带缓冲区的读取流 41 BufferedReader br = new BufferedReader(new FileReader(file)); 42 String line = null; 43 44 //定义正则表达式 45 String regex = "\\w+@[a-zA-Z]+(\\.[a-zA-z]+)+"; 46 //创建Pattern对象,封装正则表达式 47 Pattern p = Pattern.compile(regex); 48 49 //读取文件中数据 50 while ((line = br.readLine()) != null){ 51 //关流字符串 52 Matcher m = p.matcher(line); 53 while (m.find())//寻找匹配的字符串 54 System.out.println(m.group());//输出匹配的字符串 55 } 56 } 57 }