前面介绍的所有Java代码,都只能通过日志观察运行情况,就算编译成class文件,也必须在命令行下面运行,这样的程序无疑只能给开发者做调试用,不能拿给一般人使用。因为普通用户早已习惯在窗口界面上操作,哪里还会跑去命令行自讨苦吃呢?所以Java代码写得再好,也得有个软件界面与用户交互,并将程序的处理结果显示在界面上。众所周知,移动开发的Android平台,采用的便是Java语言,此时Java代码的执行结果可直接显示到手机屏幕。对于电脑来说,Java也提供了桌面程序的图形开发工具,它们主要有三组工具包,分别是源于Java1的AWT、Java2引入的Swing、集成进Java8的JavaFX,每组工具包都自成体系,均能实现图形界面的开发功能。
以最早的AWT为例,它的全称是“Abstract Window Toolkit”,意即抽象窗口工具包。AWT依赖于Java程序所在的操作系统,它的图形函数与宿主系统的图形函数是一一对应的,当Java程序通过AWT绘制图形界面的时候,其实底层仍然调用了操作系统的图形库。当然,由于各种操作系统的图形库不尽相同,某个系统提供的图形函数可能在另一个系统并不存在,因此为了让Java程序兼容不同的操作系统,AWT不得不牺牲部分功能以实现“一次编译,到处运行”的愿景。AWT固然砍掉了一些功能,反而使得它相对纯粹,更适合初学者入门桌面程序开发。
比如要在Window上显示一个窗口界面,利用AWT实现的话只需如下几行代码:

import java.awt.Frame;

//演示一个最简单的窗口
public class TestSimple { public static void main(String[] args) {
Frame frame = new Frame(); // 创建一个窗口对象
frame.setVisible(true); // 必须设置为true,否则看不见
}
}

运行以上的测试代码,可在屏幕左上角找到如下图所示的小窗口:


显然这个小窗口非常原始,只有一个Java图标以及最小化、最大化、关闭三个按钮,而且Java图标与最小化按钮还挤到一块了。由此可见,这个原始窗口尚不具备正常软件的基础功能,包括但不限于下列几点:
1、左上角的程序图标右边,应当显示程序名称;
2、除了窗口顶部的三个按钮,还要拥有下方的一块窗口主体界面;
3、窗口启动后的初始位置位于屏幕中央比较合适,方便用户迅速找到它;
上述的几点功能也挺容易实现,只要调用Frame对象的对应方法即可,下面便是Frame类的常用方法说明:
setTitle:设置窗口标题。或者在Frame的构造方法中直接填写标题文字也行。
setSize:设置窗口的宽度和高度。设置之后程序就有了指定宽高的窗口界面。
setLocationRelativeTo:设置窗口的相对位置。当传入的参数值为null时,窗口启动后将显示在屏幕中央。
setResizable:是否允许调整窗口大小。默认允许通过拖动边界来改变窗口大小,该方法设置为false则禁止调整窗口大小。
setBackground:设置窗口的背景色。窗口默认背景为白色。
setVisible:是否允许窗口可见。窗口默认是看不到的,所以必须设置为true才能看到窗口。
接着在代码中补充这些方法调用,完善后的代码例子如下所示:

public class TestFrame {

	public static void main(String[] args) {
final Frame frame = new Frame("测试窗口"); // 创建一个窗口对象
frame.setSize(400, 200); // 必须设置宽高,否则没有窗体
//frame.setTitle("222"); // 设置窗口标题,否则窗口无标题
frame.setLocationRelativeTo(null);// 将窗口居中。若无该方法,窗口将位于屏幕左上角
//frame.setResizable(false); // 禁止调整窗口大小。默认允许调整窗口尺寸
frame.setBackground(Color.GREEN); // 设置窗口背景色。默认白色
frame.setVisible(true); // 必须设置为true,否则看不见
}
}

运行上面的完善代码,发现屏幕中央弹出了一块绿油油的程序界面:


哇哦,原来Java开发桌面程序也不难嘛,很容易就鼓捣出了一个有头有脸的窗口。尽管这个窗口界面还很简单,但它毕竟比命令行好看多了,你瞧,按住标题栏可以拖动窗口,单击最小化按钮可以让它缩小至任务栏,单击最大化按钮可以让它扩大到整个屏幕,单击叉号按钮可以……。等等,点了叉号按钮居然没有关闭窗口,这是怎么回事?不应该呀,正常单击叉号按钮都会自动关闭窗口,难道是系统抽风了?AWT之所以没在单击叉号后自动关窗,是因为考虑到此时可能需要额外处理某些事务,例如以下几点场景:
1、要不要弹出温馨提示,避免用户不小心点了叉号?
2、关窗相当于强行杀死程序,那么在程序结束之前,是否先释放占用的资源?
3、单击叉号难道必须叫程序退出运行吗?像360系列软件,单击它的叉号,结果躲到了Window右下角的任务栏小图标,其实并未退出运行,就跟单击了最小化按钮一样。
如此琢磨起来,既然单击叉号还有这么多学问,就得由程序员去接管叉号的单击事件了,AWT只负责监听叉号按钮的单击动作,至于单击之后该让程序做何操作,全凭开发者自由发挥。具体到代码实现,则需调用窗口对象的addWindowListener方法,给该窗口添加事件监听器,一旦接收到窗口关闭动作,就触发监听器的windowClosing方法。那么自定义的关窗代码,即可填入此处的windowClosing方法,下面是点击叉号便自行关窗的补充代码:

		frame.addWindowListener(new WindowAdapter() { // 为窗口注册监听器,实现窗口关闭功能
public void windowClosing(WindowEvent e) { // 点击了窗口右上角的叉号按钮
frame.dispose(); // 关闭窗口
}
});

  

更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(一百一十七)AWT窗口的更多相关文章

  1. Java开发笔记(九十七)利用Runnable启动线程

    前面介绍了线程的基本用法,按理说足够一般的场合使用了,只是每次开辟新线程,都得单独定义专门的线程类,着实开销不小.注意到新线程内部真正需要开发者重写的仅有run方法,其实就是一段代码块,分线程启动之后 ...

  2. Java开发笔记(八十七)随机访问文件的读写

    前面介绍了字符流读写文件的两种方式,包括文件字符流和缓存字符流,但是它们的写操作都存在一个问题:不管是write方法还是append方法,都只能从文件开头写入,而不能追加到文件末尾或者在文件中间某个位 ...

  3. Java开发笔记(二十七)数值包装类型

    方法的出现缘起优化代码结构,但它的意义并不局限于此,正因为有了方法定义,编程语言才更像一门能解决实际问题的工具,而不仅仅是只能用于加减乘除的计算器.在数学的发展过程中,为了表示四则运算,人们创造了加减 ...

  4. Java开发笔记(三十七)利用正则串分割字符串

    前面介绍了处理字符串的常用方法,还有一种分割字符串的场景也很常见,也就是按照某个规则将字符串切割为若干子串.分割规则通常是指定某个分隔符,根据字符串内部的分隔符将字符串进行分割,例如逗号.空格等等都可 ...

  5. Java开发笔记(四十七)关键字this的用法

    前面介绍了类的基本定义,包括成员属性.成员方法.构造方法几个组成要素,可谓是具备了类的完整封装形态.不过在进行下一阶段的学习之前,有必要梳理一下前述的类定义代码,看看是否存在哪些需要优化的地方.首先观 ...

  6. Java开发笔记(五十七)因抽象方法而产生的抽象类

    前面介绍了类的常见用法,令人感叹面向对象的强大,几乎日常生活中的所有事物,都可以抽象成Java的基类及其子类.然而抽象操作也有副作用,就是某个抽象而来的行为可能是不确定的,比如半夜鸡叫,如果是公鸡则必 ...

  7. Java开发笔记(六十七)清单:ArrayList和LinkedList

    前面介绍了集合与映射两类容器,它们的共同特点是每个元素都是唯一的,并且采用二叉树方式的类型还自带有序性.然而这两个特点也存在弊端:其一,为啥内部元素必须是唯一的呢?像手机店卖出了两部Mate20,虽然 ...

  8. Java开发笔记(七十七)使用Optional规避空指针异常

    前面在介绍清单用法的时候,讲到了既能使用for循环遍历清单,也能通过stream流式加工清单.譬如从一个苹果清单中挑选出红苹果清单,采取for循环和流式处理都可以实现.下面是通过for循环挑出红苹果清 ...

  9. Java开发笔记(序)章节目录

    现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...

随机推荐

  1. selenium模块及类组织关系

    问题:webdriver子模块中为什么可以直接使用类Chrome.ChromeOptions.Firefox.FirefoxProfile... 在webdriver的__init__.py文件中已经 ...

  2. 10-Flutter移动电商实战-使用FlutterSwiper制作轮播效果

    1.引入flutter_swiper插件 flutter最强大的siwiper, 多种布局方式,无限轮播,Android和IOS双端适配. 好牛X得介绍,一般敢用“最”的一般都是神级大神,看到这个介绍 ...

  3. BZOJ 3166: [Heoi2013]Alo 链表+可持久化trie

    链表这个东西非常好用啊 ~ code: #include <bits/stdc++.h> #define N 50010 #define inf 2000400000 #define se ...

  4. 75: libreoj #10028 双向宽搜

    $des$ 实现一个bfs $sol$ 写了一个双向bfs #include <bits/stdc++.h> using namespace std; #define Rep(i, a, ...

  5. (15)Go错误处理

    1.erro(一般错误) package main import ( "errors" "fmt" ) func div(a, b int) (res int) ...

  6. Noip2019暑期训练1

    题目名称 时空定位 棋子移动 高精度乘法 数独游戏 存盘文件名 location piece mul sudoku 输入文件名 location.in piece.in mul.in sudoku.i ...

  7. 「2019-8-13提高模拟赛」树 (tree)

    传送门 Description 你有一个 \(n\)个点的树,第 \(i\)个点的父亲是\(p_i\).每个点有一个权值 \(t_i\) 和一个颜色黑或者白.所有点一开始都是白色. 你要进行 \(m\ ...

  8. restframework之节流

    基本思路(原生Django而言): 在django2.x中,若出现节流(访问频率控制)的需求,我们首先想到的是使用一个字典(dict类型)来存储所有IP地址的访问时间记录,这是针对于匿名用户(IP)而 ...

  9. Cesium学习笔记-工具篇20-PrimitiveTexture自定义渲染-贴图【转】

    前几篇博客我们了解了自定义点.线.面绘制,这篇我们接着学习cesium自定义纹理贴图.我们完成点线面的绘制,只是绘制出了对象的框架,没有逼真的外观.逼真外观是需要设置材质来实现:Material . ...

  10. word 转 pdf,c#代码

    通过使用 C# 控制 office 软件 com 组件转 pdf 1 word 转 pdf 方案二:可以使用 netoffice 进行转换 参考文档:https://netoffice.io/docu ...