• JAVA AWT


    AWT

      在Java 1.1中一个显著的改变就是完善了新AWT的创新。大多数的改变围绕在Java 1.1中使用的新事件模型:老的事件模型是糟糕的、笨拙的、非面向对象的,而新的事件模型可能是我所见过的最优秀的。难以理解一个如此糟糕的(老的AWT)和一个如此优秀的(新的事件模型)程序语言居然出自同一个集团之手。新的考虑事件的方法看来中止了,因此争议不再变成障碍,从而轻易进入我们的意识里;相反,它是一个帮助我们设计系统的工具。它同样是Java Beans的精华,我们会在本章后面部分进入讲述。
      新的方法设计对象做为“事件源”和“事件接收器”以代替老AWT的非面向对象串联的条件语句。正象我们将看到的内部类的用途是集成面向对象的原始状态的新事件。另外,事件现在被描绘为在一个类体系以取代单一的类并且我们可以创建自己的事件类型。
      
    新的事件模型
      在新的事件模型的组件可以开始一个事件。每种类型的事件被一个个别的类所描绘。当事件开始后,它受理一个或更多事件指明“接收器”。因此,事件源和处理事件的地址可以被分离
      每个“接收器”都是执行特定的接收器类型接口的类对象。因此作为一个程序开发者,我们所要做的是创建“接收器对象”并且在被激活事件的组件中进行注册。event-firing组件调用一个addXXXListener()方法来完成注册,以描述XXX事件类型接受。我们可以容易地了解到以addListened名的方法通知我们任何的事件类型都可以被处理,如果我们试图接收事件我们会发现编译时我们的错误。Java Beans同样使用这种addListener名的方法去判断那一个程序可以运行。
      我们所有的事件逻辑将装入到一个接收器类中。当我们创建一个接收器类时唯一的一点限制是必须执行专用的接口。我们可以创建一个全局接收器类,这种情况在内部类中有助于被很好地使用,不仅仅是因为它们提供了一个理论上的接收器类组到它们服务的UI或业务逻辑类中,但因为事实是一个内部类维持一个句柄到它的父对象,提供了一个很好的通过类和子系统边界的调用方法。
    一个简单的例子将使这一切变得清晰明确。同时思考本章前部Button2.java例子与这个例子的差异。

    //: Button2New.java
    // Capturing button presses
    import java.awt.*;
    import java.awt.event.*; // Must add this
    import java.applet.*;
    
    public class Button2New extends Applet {
      Button
        b1 = new Button("Button 1"),
        b2 = new Button("Button 2");
      public void init() {
        b1.addActionListener(new B1());                //b1为事件源  new B1为接收器对象
        b2.addActionListener(new B2());             //addXXXListener注册到“事件组件”
    add(b1); 
    add(b2);
    }
    class B1 implements ActionListener {             //接收器类
        public void actionPerformed(ActionEvent e) {
          getAppletContext().showStatus("Button 1");
        }
      }
      class B2 implements ActionListener {
        public void actionPerformed(ActionEvent e) {
          getAppletContext().showStatus("Button 2");
        }
      }
      /* 老的AWT方式:
      public boolean action(Event evt, Object arg) {
        if(evt.target.equals(b1))                    //所有的事件源被统一集中处理  
          getAppletContext().showStatus("Button 1");
        else if(evt.target.equals(b2))                  //发生了什么
          getAppletContext().showStatus("Button 2");          //怎样处理
        // Let the base class handle it:
        else 
          return super.action(evt, arg);
        return true; // We've handled it here
      }
      */
    } ///:~


    我们可比较两种方法,老的代码在左面作为注解。在init()方法里,只有一个改变就是增加了下面的两行:
        b1.addActionListener(new B1());    
        b2.addActionListener(new B2());
      按钮按下时,addActionListener()通知按钮对象被激活。B1和B2类都是执行接口ActionListener的内部类。这个接口包括一个单一的方法actionPerformed()(这意味着当事件激活时,这个动作将被执行)。注意actionPreformed()方法不是一个普通事件,说得更恰当些是一个特殊类型的事件,ActionEvent。如果我们想提取特殊ActionEvent的信息,因此我们不需要故意去测试和下溯造型自变量。
      对编程者来说重写事件actionPerformed()十分的简单。它是一个可以调用的方法。同老的action()方法比较,老的方法我们必须指出发生了什么和适当的动作,同样,我们会担心调用基础类action()的版本并且返回一个值去指明是否被处理。在新的事件模型中,我们知道所有事件测试推理自动进行,因此我们不必指出发生了什么;我们刚刚表示发生了什么,它就自动地完成了。如果我们还没有提出用新的方法覆盖老的方法,我们会很快提出。

      在这里介绍一下程序片、视窗应用。

    程序片:

      程序片的局限,出于安全缘故,程序片十分受到限制,并且有很多的事我们都不能做。您一般会问:程序片看起来能做什么,传闻它又能做什么:扩展浏览器中WEB页的功能。自从作为一个网上冲浪者,我们从未真正想了解是否一个WEB页来自友好的或者不友好的站点,我们想要一些可以安全地行动的代码。所以我们可能会注意到大量的限制:
      (1) 一个程序片不能接触到本地的磁盘。这意味着不能在本地磁盘上写和读,我们不想一个程序片通过WEB页面阅读和传送重要的信息。写是被禁止的,当然,因为那将会引起病毒的侵入。当数字签名生效时,这些限制会被解除。
      (2) 程序片不能拥有菜单。(注意:这是规定在Swing中的)这可能会减少关于安全和关于程序简化的麻烦。我们可能会接到有关程序片协调利益以作为WEB页面的一部分的通知;而我们通常不去注意程序片的范围。这儿没有帧和标题条从菜单处弹出,出现的帧和标题条是属于WEB浏览器的。也许将来设计能被改变成允许我们将浏览器菜单和程序片菜单相结合起来——程序片可以影响它的环境将导致太危及整个系统的安全并使程序片过于的复杂。
      (3) 对话框是不被信任的。在Java中,对话框存在一些令人难解的地方。首先,它们不能正确地拒绝程序片,这实在是令人沮丧。如果我们从程序片弹出一个对话框,我们会在对话框上看到一个附上的消息框“不被信任的程序片”。这是因为在理论上,它有可能欺骗用户去考虑他们在通过WEB同一个老顾客的本地应用程序交易并且让他们输入他们的信用卡号。在看到AWT开发的那种GUI后,我们可能会难过地相信任何人都会被那种方法所愚弄。但程序片是一直附着在一个Web页面上的,并可以在浏览器中看到,而对话框没有这种依附关系,所以理论上是可能的。因此,我们很少会见到一个使用对话框的程序片。
    在较新的浏览器中,对受到信任的程序片来说,许多限制都被放宽了(受信任程序片由一个信任源认证)。
    涉及程序片的开发时,还有另一些问题需要考虑:
      ■程序片不停地从一个适合不同类的单独的服务器上下载。我们的浏览器能够缓存程序片,但这没有保证。在Java 1.1版中的一个改进是JAR(Java ARchive)文件,它允许将所有的程序片组件(包括其它的类文件、图像、声音)一起打包到一个的能被单个服务器处理下载的压缩文件。“数字签字”(能校验类创建器)可有效地加入每个单独的JAR文件。
      ■因为安全方面的缘故,我们做某些工作更加困难,例如访问数据库和发送电子邮件。另外,安全限制规则使访问多个主机变得非常的困难,因为每一件事都必须通过WEB服务器路由,形成一个性能瓶颈,并且单一环节的出错都会导致整个处理的停止。
      ■浏览器里的程序片不会拥有同样的本地应用程序运行的控件类型。例如,自从用户可以开关页面以来,在程序片中不会拥有一个形式上的对话框。当用户对一个WEB页面进行改变或退出浏览器时,对我们的程序片而言简直是一场灾难——这时没有办法保存状态,所以如果我们在处理和操作中时,信息会被丢失。另外,当我们离开一个WEB页面时,不同的浏览器会对我们的程序片做不同的操作,因此结果本来就是不确定的。

    程序片的优点
      如果能容忍那些限制,那么程序片的一些优点也是非常突出的,尤其是在我们构建客户/服务器应用或者其它网络应用时:
      ■没有安装方面的争议。程序片拥有真正的平台独立性(包括容易地播放声音文件等能力)所以我们不需要针对不同的平台修改代码也不需要任何人根据安装运行任何的“tweaking”。事实上,安装每次自动地将WEB页连同程序片一起,因此安静、自动地更新。在传统的客户机/服务器系统中,建立和安装一个新版本的客户端软件简直就是一场恶梦。
      ■因为安全的原因创建在核心Java语言和程序片结构中,我们不必担心坏的代码而导致毁坏某人的系统。这样,连同前面的优点,可使用Java(可从JavaScript和VBScript中选择客户端的WEB编程工具)为所谓的Intrant(在公司内部使用而不向Internet转移的企业内部网络)客户机/服务器开发应用程序。
      ■由于程序片是自动同HTML集成的,所以我们有一个内建的独立平台文件系统去支持程序片。这是一个很有趣的方法,因为我们惯于拥有程序文件的一部分而不是相反的拥有文件系统。

    视窗化应用
      出于安全的缘故,我们会看到在程序片我们的行为非常的受到限制。我们真实地感到,程序片是被临时地加入在WEB浏览器中的,因此,它的功能连同它的相关知识,控件都必须加以限制。但是,我们希望Java能制造一个开窗口的程序去运行一些事物,否则宁愿安放在一个WEB页面上,并且也许我们希望它可以运行一些可靠的应用程序,以及夸张的实时便携性。在这本书前面的章节中我们制造了一些命令行应用程序,但在一些操作环境中(例如:Macintosh)没有命令行。所以我们有很多的理由去利用Java创建一个设置窗口,非程序片的程序。这当然是一个十分合理的要求。
      一个Java设置窗口应用程序可以拥有菜单和对话框(这对一个程序片来说是不可能的和很困难的),可是如果我们使用一个老版本的Java,我们将会牺牲本地操作系统环境的外观和感受。JFC/Swing库允许我们制造一个保持原来操作系统环境的外观和感受的应用程序。如果我们想建立一个设置窗口应用程序,它会合理地运作,同样,如果我们可以使用最新版本的Java并且集合所有的工具,我们就可以发布不会使用户困惑的应用程序。如果因为一些原因,我们被迫使用老版本的Java,请在毁坏以建立重要的设置窗口的应用程序前仔细地考虑。

     用Java 1.1 AWT制作窗口和程序片
      我们经常都需要创建一个类,使其既可作为一个窗口调用,亦可作为一个程序片调用。为做到这一点,只需为程序片简单地加入一个main()即可,令其在一个Frame(帧)里构建程序片的一个实例。作为一个简单的示例,下面让我们来看看如何对Button2New.java作一番修改,使其能同时作为应用程序和程序片使用:

    //: Button2NewB.java
    // An application and an applet
    import java.awt.*;
    import java.awt.event.*; // Must add this
    import java.applet.*;
    
    public class Button2NewB extends Applet {    //程序片
      Button
        b1 = new Button("Button 1"),
        b2 = new Button("Button 2");
      TextField t = new TextField(20);
      public void init() {
        b1.addActionListener(new B1());
        b2.addActionListener(new B2());
        add(b1);
        add(b2);
        add(t);
      }
      class B1 implements ActionListener {
        public void actionPerformed(ActionEvent e) {
          t.setText("Button 1");
        }
      }
      class B2 implements ActionListener {
        public void actionPerformed(ActionEvent e) {
          t.setText("Button 2");
        }
      }
      // To close the application:
      static class WL extends WindowAdapter {
        public void windowClosing(WindowEvent e) {
          System.exit(0);
        }
      }
      // A main() for the application:
      public static void main(String[] args) {        //视窗应用
        Button2NewB applet = new Button2NewB();
        Frame aFrame = new Frame("Button2NewB");
        aFrame.addWindowListener(new WL());
        aFrame.add(applet, BorderLayout.CENTER);
        aFrame.setSize(300,200);
        applet.init();
        applet.start();
        aFrame.setVisible(true);
      }
    } ///:~


    内部类WL和main()方法是加入程序片的唯一两个元素,程序片剩余的部分则原封未动。事实上,我们通常将WL类和main()方法做一结小的改进复制和粘贴到我们自己的程序片里(请记住创建内部类时通常需要一个外部类来处理它,形成它静态地消除这个需要)。我们可以看到在main()方法里,程序片明确地初始化和开始,因为在这个例子里浏览器不能为我们有效地运行它。当然,这不会提供全部的浏览器调用stop()和destroy()的行为,但对大多数的情况而言它都是可接受的。如果它变成一个麻烦,我们可以:
    (1) 使程序片句柄为一个静态类(以代替局部可变的main()),然后:
    (2) 在我们调用System.exit()之前在WindowAdapter.windowClosing()中调用applet.stop()和applet.destroy()。
    注意最后一行:
      aFrame.setVisible(true);
    这是Java 1.1 AWT的一个改变。show()方法不再被支持,而setVisible(true)则取代了show()方法。当我们在本章后面部分学习Java Beans时,这些表面上易于改变的方法将会变得更加的合理。
    这个例子同样被使用TextField修改而不是显示到控制台或浏览器状态行上。在开发程序时有一个限制条件就是程序片和应用程序我们都必须根据它们的运行情况选择输入和输出结构。
    这里展示了Java 1.1 AWT的其它小的新功能。我们不再需要去使用有错误倾向的利用字符串指定BorderLayout定位的方法。当我们增加一个元素到Java 1.1版的BorderLayout中时,我们可以这样写:
    aFrame.add(applet, BorderLayout.CENTER);
    我们对位置规定一个BorderLayout的常数,以使它能在编译时被检验(而不是对老的结构悄悄地做不合适的事)。这是一个显著的改善,并且将在这本书的余下部分大量地使用。

    将窗口接收器变成匿名类
    任何一个接收器类都可作为一个匿名类执行,但这一直有个意外,那就是我们可能需要在其它场合使用它们的功能。但是,窗口接收器在这里仅作为关闭应用程序窗口来使用,因此我们可以安全地制造一个匿名类。然后,main()中的下面这行代码:
    aFrame.addWindowListener(new WL());
    会变成:

    aFrame.addWindowListener(new WindowAdapter() {      //创建匿名类接收器对象,aFrame为事件源
        public void windowClosing(WindowEvent e) {
          System.exit(0);
        }
      });


    这有一个优点就是它不需要其它的类名。我们必须对自己判断是否它使代码变得易于理解或者更难。不过,对本书余下部分而言,匿名内部类将通常被使用在窗口接收器中。

    将程序片封装到JAR文件里
      一个重要的JAR应用就是完善程序片的装载。在Java 1.0版中,人们倾向于试法将它们的代码填入到单个的程序片类里,因此客户只需要单个的服务器就可适合下载程序片代码。但这不仅使结果凌乱,难以阅读(当然维护也然)程序,但类文件一直不能压缩,因此下载从来没有快过。
    JAR文件将我们所有的被压缩的类文件打包到一个单个儿的文件中,再被浏览器下载。现在我们不需要创建一个糟糕的设计以最小化我们创建的类,并且用户将得到更快地下载速度。
    仔细想想上面的例子,这个例子看起来像Button2NewB,是一个单类,但事实上它包含三个内部类,因此共有四个。每当我们编译程序,我会用这行代码打包它到一个JAR文件:
      jar cf Button2NewB.jar *.class
    这是假定只有一个类文件在当前目录中,其中之一来自Button2NewB.java(否则我们会得到特别的打包)。
    现在我们可以创建一个使用新文件标签来指定JAR文件的HTML页,如下所示:

    <head><title>Button2NewB Example Applet</title></head>
    <body>
      <applet code="Button2NewB.class" 
              archive="Button2NewB.jar" 
              width=200 height=150>
      </applet>
    </body>


    与HTML文件中的程序片标记有关的其他任何内容都保持不变。

  • 相关阅读:
    ffmpeg显示视频
    眼见为实(1):C++基本概念在编译器中的实现
    在Windows系统上实现轻量级的线程间及进程间消息队列
    Intellij IDEA 2017 debug断点调试技巧与总结详解篇
    redis 全局命令 查看所有的键,删除键,检查键是否存在,获取过期时间,键的数据结构类型
    java.security.InvalidKeyException: IOException : Short read of DER length
    RSA解密报错java.security.spec.InvalidKeySpecException的解决办法
    IntelliJ IDEA全局内容搜索和替换
    RSA加密/解密 Decryption error异常解决
    java rsa 解密报:javax.crypto.BadPaddingException: Decryption error
  • 原文地址:https://www.cnblogs.com/jiangzhaowei/p/7155887.html
Copyright © 2020-2023  润新知