java:还要不要学java swing与awt和awt啊

讲真,swing和awt有必要学吗?【java吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:636,036贴子:
讲真,swing和awt有必要学吗?收藏
楼主渣渣二本,学校开的java课程,书上通篇swing跟awt!容器框架,反射,注解什么都没有!之前看到说swing跟awt前途不大,大神来说说看法吧!附带课本,个人觉得这课本不咋的!比之前自学的差太多了
java,亚马逊网上书城,满59元免运费,好书不间断!700多万种中外正版精品图书一网打尽!买java,就上Z.CN!正版图书,天天低价特惠,让您挚爱阅读!
有人吗??
随便看看,大概了解一下就好
没必要学就不学呗
学校的书籍基本上比市面上书本的晚3年
完全没必要看,这不是java的强项
完全有必要,学java不是为了工作而是为了装逼,好的界面才会。。。
楼主哪所大学?
刚开就这么难,真的学的好吗
swing是什么来着。。。原谅我的无知
了解会做就够了。
要炸了,妈的线程,文件流,网络通信全是建立在swing跟awt上的垃圾课本
如果以后想做Web开发就没必要学
登录百度帐号推荐应用Swing的SwingWorker学习 - 不懂就是不懂 - ITeye博客
博客分类:
一开始使用swing的时候就了解过这个东西.在项目中应用的时候.发现edt操作不能在SwingWorker线程中执行.(这里的edt操作包括什么呢?我以前做的时候只要有new这个关键字.就执行不了..现在就可以了)
一直以为是swing的规范.有很多的限制.最后就没再看这个东西.直到有一天看到这篇文章
首先赞一下.作者写的非常详细.而且提供了demo.于是我下载了demo,开始读代码.最后终于搞定了这个东东.
于是自己做了个例子.首先是课前准备
EDT是啥米呀在Java中,键盘输入、鼠标点击或者应用程序本身产生的请求会被封装成一个事件,放进一个事件队列中,java.awt.EventQueue对象负责从这个队列中取出事件并派发它们。而EventQueue的派发有一个单独的线程管理,这个线程叫做事件派发线程(Event Dispatch Thread),也就是EDT。此外,Swing的绘制请求也是通过EDT来派发的。
这里就简单提下.关于更详细的介绍请看原文
这里帖下关键代码
private void button_getDataActionPerformed(java.awt.event.ActionEvent evt) {
//清除表格数据
table_data.setModel(new javax.swing.table.DefaultTableModel(
new Object[][]{},
new String[]{
"id", "parent_id", "node_name"
//如果要查看EDT阻塞效果
if (checkbox_edt.isSelected()) {
//在不采用SwingWorker的时候下面这句你会发现不起作用,因为这是一个EDT事件.
//只有处理完了这个事件之后.别的改变组件状态的时间才会被执行.这就是EDT阻塞
label_busy.setVisible(true);//设置载入label显示
Thread.sleep(5000);//睡眠5秒
} catch (InterruptedException ex) {
ex.printStackTrace();
setData();
label_busy.setVisible(false);//设置载入label消失
} else {//使用SwingWroker
table_data.setEnabled(false);//设置表格不可用
button_getData.setEnabled(false);//设置按钮不可用
label_busy.setVisible(true);//设置载入label显示
new SwingWorker&DefaultTableModel, Void&() {
protected DefaultTableModel doInBackground() throws Exception {
System.out.println("开始执行后台方法...");
JLabel jLabel = new JLabel();//测试在非EDT线程中创建组件.我以前做的总是不可以.现在好了.
Thread.sleep(5000);//睡眠5秒.因为效果不太明显
return getData();//返回取到的数据
protected void done() {
System.out.println("后台方法运行结束");
table_data.setEnabled(true);
button_getData.setEnabled(true);
label_busy.setVisible(false);
获取doInBackground方法的返回值
table_data.setModel(get());//用get()方法取到上面取得的值
} catch (Exception ex) {
ex.printStackTrace();
}.execute();
我在回家的路上想起来上次出现edt操作不能在SwingWorker线程中执行这个问题.
是由于用了开源皮肤Substance的问题.回家一试.果真如此..
把运行的代码
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TestFrame frame = new TestFrame();
frame.setVisible(true);
public static void main(String args[]) {
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
UIManager.setLookAndFeel(new SubstanceBusinessBlueSteelLookAndFeel());
} catch (Exception e) {
System.out.println("Substance Raven Graphite failed to initialize");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TestFrame frame = new TestFrame();
frame.setVisible(true);
添加substance.jar包..
org.jvnet.substance.api.UiThreadingViolationException: Component creation must be done on Event Dispatch Thread
at org.jvnet.substance.utils.SubstanceCoreUtilities.testComponentCreationThreadingViolation(SubstanceCoreUtilities.java:2368)
at org.jvnet.substance.SubstanceLabelUI.createUI(SubstanceLabelUI.java:68)
at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:36)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:243)
at javax.swing.UIDefaults.getUI(UIDefaults.java:751)
at javax.swing.UIManager.getUI(UIManager.java:1016)
at javax.swing.JLabel.updateUI(JLabel.java:256)
at javax.swing.JLabel.&init&(JLabel.java:145)
at javax.swing.JLabel.&init&(JLabel.java:216)
at test.TestFrame$2.doInBackground(TestFrame.java:186)
at test.TestFrame$2.doInBackground(TestFrame.java:181)
at javax.swing.SwingWorker$1.call(SwingWorker.java:278)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at javax.swing.SwingWorker.run(SwingWorker.java:317)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
不知道是什么原因....为什么java默认的皮肤可以..开源的就不可以呢...
上面的代码是一个按钮点击事件中执行的代码.
详细的例子请见附件
数据库用的是derby.
描述: 源码和数据库文件不包括jar
下载次数: 239
描述: 完整的NetBeans项目
下载次数: 479
论坛回复 /
(7 / 12028)
看下org.jvnet.substance.utils.SubstanceCoreUtilities类下的testComponentCreationThreadingViolation()和testComponentStateChangeThreadingViolation()方法就明白了,它做了一个判断,将这两个方法的内容注释掉就不会有异常信息了。
谢谢解答..回头看看
这种问题的根本原因是:Java Swing不是线程安全的,原因有二个,一个是效率因素,另一个是线程安全的UI工具包通常容易创建出倾向于死锁的程序。
通常在Swing中使用线程有两个简单原则:
1、非常耗时的动作要在一个单独的线程中执行,而不要在事件分派线程(EDT)中执行。
2、在任何线程中都不要碰Swing组件,除了时间分派线程。
要在耗时的线程中操作Swing组件,需要借助EventQueue中的两个静态方法向事件分派线程发送一个事件,从而通知事件分派线程执行对于Swing组件的操作。
上述的原则,对于Java Swing多线程应用是非常非常重要的。
谢谢解答.我现在的疑问是为什么java默认的皮肤可以,开源的那个不可以呢?难道java默认的皮肤绘制组件的时候不碰swing组件?开源的就碰?
不光是swing,凡是牵扯到gui的,例如c#也存在这个问题!!
您说的是edt操作不能在非EDT事件中执行的问题吗?那为什么java默认的皮肤可以呢?开源的那个不可以..
浏览: 199853 次
来自: 北京
[b][b][b][b][b][b][/b][/b][/b][ ...
根据你的配置, 注解事务似乎无效呢?
兰帝威武[color=brown][/color]用户名:Java_maidou
文章数:27
访问量:3690
注册日期:
阅读量:1297
阅读量:3317
阅读量:448147
阅读量:1133115
51CTO推荐博文
今天总结的几个组件吧!感觉好几天没有写了从和说起吧,这是个拥有很多丰富的方法的类的包,可以创建窗体、设置窗体可见、窗体、窗体关闭方式、窗体大小以及位置等等的方法、同时要是用窗体就需要建立一个画布,然后与窗体绑定,将一些组件增添到画布中去,这样就可以使用一些组件完成一些基本的功能,同时需要为组件添加监听,才能触发事件完成相应的功能,由于组件与组件有差别,即许多对应的名字不一样,且用法也会有出入,毕竟有自己的一套,但是要想学好的界面,个人小小的认为还是可以先把的研究研究再说吧在中有JButton、JFrame、JLabel、JPanel、SwingConstants等等的已经封装好的类,所以我们只需要会如何使用便可以了,同样在awt中有、、、Image等等类,个人认为可以先看一下布局方式,下面先看一个东西南北中的布局吧:package my01;
import java.awt.BorderL
import java.awt.C
import java.awt.event.ActionE
import java.awt.event.ActionL
import javax.swing.JB
import javax.swing.JF
import javax.swing.JL
import javax.swing.JP
import javax.swing.SwingC
public class Graphics extends JFrame{
JButton south = new JButton("south");
JButton west = new JButton("west");
JButton north = new JButton("north");
JButton east = new JButton("east");
JLabel center = new JLabel("center",SwingConstants.CENTER);
JButton[] jb = new JButton[]{west,north,east,south};
public Graphics(){
JPanel pnBasic = new JPanel();
pnBasic.setColor.PINK);
pnBasic.setLayout(new BorderLayout());
for(int i=0;i&jb.i++){
jb[i].addActionListener(new ButtonMonitor());
pnBasic.add(south,BorderLayout.SOUTH);
pnBasic.add(west,BorderLayout.WEST);
pnBasic.add(north,BorderLayout.NORTH);
pnBasic.add(east,BorderLayout.EAST);
pnBasic.add(center,BorderLayout.CENTER);
setContentPane(pnBasic);
setTitle("东西南北");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200,200);
setVisible(true);
public class ButtonMonitor implements ActionListener{
public void actionPerformed(ActionEvent e) {
if(e.getSource() == jb[0]){
center.setText("West");
}else if(e.getSource() == jb[1]){
center.setText("north");
}else if(e.getSource() == jb[2]){
center.setText("east");
}else if(e.getSource() == jb[3]){
center.setText("south");
public static void main(String[] args) {
new Graphics();
} & &运行结果如下显示: & &下面根据这个大框的主体布局增加了一些图片的处理,给按钮添加了监听,让其完成图片的显示,在其中又用到了cardLayout的图片显示布局:package my01;
import java.awt.BorderL
import java.awt.CardL
import java.awt.GridL
import java.awt.I
import java.awt.event.ActionE
import java.awt.event.ActionL
import javax.swing.ImageI
import javax.swing.JB
import javax.swing.JF
import javax.swing.JL
import javax.swing.JP
public class Graphics1 extends JFrame {
private CardLayout lyC
JPanel pnBasic = new JPanel();
JPanel jp1 = new JPanel();
JPanel jp2 = new JPanel();
JButton btnLast = new JButton();
JButton btnNow = new JButton();
JButton btnNext = new JButton();
public Graphics1(){
pnBasic.setLayout(new BorderLayout());
lyCard = new CardLayout();
jp1.setLayout(lyCard);
JLabel[] jlArrShow = new JLabel[7];
for(int i=0;i&jlArrShow.i++){
jlArrShow[i] = new JLabel();
ImageIcon icon = new ImageIcon("assets/logo/"+(i+1)+".png");
jlArrShow[i].setIcon(icon);
jp1.add(i+"",jlArrShow[i]);
pnBasic.add(jp1,BorderLayout.CENTER);
jp2.setLayout(new GridLayout(1,3));
String[] strArr = {"last","now","next"};
JButton[] btnArr = new JButton[strArr.length];
for(int i=0;i&btnArr.i++){
btnArr[i] = new JButton(strArr[i]);
btnArr[i].addActionListener(new ButtonMonitor());
jp2.add(btnArr[i]);
pnBasic.add(jp2,BorderLayout.SOUTH);
setContentPane(pnBasic);
ImageIcon icon = new ImageIcon("assets/icon24.png");
Image image = icon.getImage();
setIconImage(image);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("picture");
setBounds(200,200,400,400);
setVisible(true);
public class ButtonMonitor implements ActionListener{
public void actionPerformed(ActionEvent e) {
JButton btnClick = (JButton) e.getSource();
String strBtnTxt = btnClick.getText();
if("last".equalsIgnoreCase(strBtnTxt)){
lyCard.previous(jp1);
}else if("now".equalsIgnoreCase(strBtnTxt)){
lyCard.first(jp1);
lyCard.show(jp1, 2+"");
}else if("next".equalsIgnoreCase(strBtnTxt)){
lyCard.next(jp1);
public static void main(String[] args) {
new Graphics1();
} & 输出效果如下: & &对应的按钮也可有相应的布局如上面的流式布局,点击上面的按钮图片会相应的改变,如果frame中要添加的东西很多,如数组,还有一些并列的许多属性时,可以封装出一个实体类,那样操作会更加简单,这一点是老师提供的宝贵意见,等以后弄出来再补上吧!对于更深一步的优化以后学会了再说吧,今天就只能少说点啦
了这篇文章
类别:未分类┆阅读(0)┆评论(0)历史&&&Internet上有许多围绕这一争论的故事。你可能已经听说过它们中的大多数了,其中之一有助于让你理清头绪,让我们就从这里开始,Amy Fowler是Swing阵营的一个倡导者。
回到上个世纪90年代,曾几何时有3家庞大的Smalltalk公司——IBM、Parc-Place和 Digitalk。在90年代初期3家公司的市场份额大致相等,生活是美好的。Parc-Place采用仿窗口部件(emulated widgets)的设计(即Swing的设计),IBM和Digitalk则采用原生窗口部件(native widgets)。后来IBM压倒了另外两家,因此他们打算合并成一家,假设叫做Parc-Place Digitalk。随后当他们试图将他们的产品融合到一个叫做Jigsaw的计划中时爆发了一场大战,计划由于政治原因失败了(开发人员实际上已经能让它运转起来),就因为原生和仿造两派的死战。&&&& Amy赢得了精神上的胜利,不过IBM赢得了他们所有的生意,因为这两家公司在一整年里除了吵架什么都没做。当尘埃落定之后PPD(Parc-Place Digitalk当时已改名为Objectshare,跟Windscale改名为Sellafield的原因相同——让人们淡忘之前发生的灾难)的股票价格从60美元掉到了低于1美元1股。他们因为伪报收入被NASDAQ摘牌,从此消失。
&&&&当时,AWT已经出现了。SUN当时已经建立了一套基本的可移植控件类,这些类映射到不同操作系统上的原生窗口组件(native widget),当时的AWT还满是漏洞,远不能称为可靠,还需要SUN的coder们去修补。然后Amy被雇佣了,她承诺通过轻量级方案解决所有窗口组件的问题,以此说服SUN管理层让她当了GUI开发部门的头头。随后Amy雇佣了所有她过去在Parc-Place的旧朋友,让他们来开发Swing。&&&&在IBM,VisualAge for Java最初是用Smalltalk(用的是原生窗口组件)写的,当将这些工具向Java代码库迁移时,他们需要一套窗口组件。IBM这边的开发人员都是原来搞Smalltalk的那一批人,他们对管理层要求用Swing来构建WebSphere Studio工具都非常不情愿。“Swing是个可怕的充满缺陷的怪兽“。因此开始了一个新的项目,把他们的Smalltalk原生窗口组件移植到Java上去。这个工具集后来被成为SWT,S开始是Simple的缩写,不过后来变成了Standard的缩写。这个项目获得了成功,被运用在发布的 VisualAge Micro Edition产品中。他们当时发现在Swing读事件队列的时候用了一种可能留下内存漏洞的方式,而不得不采用他们自己的查询 Windows事件队列的循环,以纠正这个错误。这促成了他们关于SWT和 AWT/Swing不能共存的决定。他们把这个工具包放到了Eclipse中,这是一个来自于早期Visual Age的工具平台。&&&&你应该已经从上述的故事中对三者的历史有了大概的了解,尤其是SWT。现在你也许会觉得,IBM创建SWT的理由是合理的而Swing应该沿用SWT采用的方式。这样的观点是片面的,当你深入了解到Java的本质之后,你会发现其实并不像你想象的那么简单。
先决条件什么才是Java本质的,影响到工具集设计的特征呢?或者说,什么才是Java GUI工具集设计的先决条件呢?
&&&&答案来自于Sun对Java的承诺之一:write once, run anywhere(一次编写,随处运行)。这是Java不同于其他语言的优势所在。在Java被创建之前,软件的跨平台性能是开发者,特别是那些希望对多平台提供支持的开发者的梦魇。在当今的生活中Internet的使用已经相当的普遍了,在世界不同角落的人们在不同的平台上工作着。软件提供商为不同的操作系统提供支持是再平凡不过的事情。Java的write-once-run-anywhere(WORA)承诺显然减轻了开发者的负担,极大地提高了软件开发的生产力。&&&&然而编写跨平台的应用程序,你必须使用支持平台无关性的标准库。这些标准库包括语言支持,公共用途,网络,I/O和GUI工具集等。所以当Sun开始设计GUI工具集的时候,首要任务就是考虑一个设计良好的平台无关的API。AWT和Swing都被小心地设计以保证平台兼容性。SWT则相反,它在设计之初并不以扩展性为原则,它为一个专有的IDE Visual Age for Java而设计,Windows作为这个IDE的首选运行环境拥有很高的优先级考量。SWT API类似于WIndows,通常它并不如Swing的扩展性好,尽管Steve Northover,SWT之父,辩称SWT是平台无关的,你可以很容易地发现许多Windows API的痕迹。区别&&&&GUI应用程序是软件的一种主要类型,所以Java的GUI库应该是标准化并被集成到JRE平台中的。然而不同的操作系统有不同的GUi风格和组件集。有一些组件在所以平台上有相似的观感。这些共有组件如按钮,标签,文本域,单选框等被称为标准组件。不同的GUI工具集提供了不同的组件集。GUI工具集总是遵循不同的原则来选择组件类型和特征以实现。考察一个工具集,有两个不同的要素:组件类型和组件特征。Terms&&&&首先让我图解两个数学概念:最大公约数和最小公倍数。如下图,三个集合代表不同的操作系统。相交的部分是最大公约数,合并的部分是最小公倍数。
现在让我们来考察Java GUI工具集AWT,SWT和Swing的组件类型和特征
&&&AWT组件集遵循最大公约数原则,即AWT只拥有所有平台上都存在的组件的公有集合。所以你在AWT中无法获取如表或树等高级组件,因为它们在某些平台上不支持。AWT的组件特征同样遵循这一原则。它只提高平台上公有的特征。例如AWT按钮不能附着图片,因为在Motif平台上,按钮是不支持图片的。
由于它低劣的组件集和特征,AWT无法吸引开发者。它是Sun不推荐使用的,只是为了确保向下兼容和支持Swing。SWT&&&&SWT最初的目标之一是为了提供比AWT更为丰富的组件集。它遵循最小公倍数原则以提供一个各个平台上包含的组件的并集。思路是如果一个组件在某个平台上包含,那么SWT就会包装它并用java代码和JNI来调用它。如果一个组件在某一平台上不存在,它就会用继承并绘制Composite的方式来模拟组件。一个SWT Composite类似于AWT的Canvas。以这种方式,SWT提供了较AWT更为丰富的组件集。值得指出的是SWT的JNI封装不同于AWT,它的模拟也不同于Swing。&&&&在组件特征方面,SWT类似于AWT。它遵循最小公倍数原则。在早期的SWT版本中,SWT按钮因为和AWT同样的原因不支持附着图片。在之后的版本中,许多缺失的特征采用模拟的方式补全。但仍有许多特征无法采用纯粹的模拟实现。SWT将组件的控制交给本地操作系统。它难以扩展。只有例如图形装饰等特征可以借助模拟绘制来自定义实现。所以严格意义上将,SWT组件的组件集和特征因其难于扩展而不如Swing来得丰富。Swing&&&&Swing是三者中最强大和灵活的。在组件类型上,它遵循最大公约数原则。由于Swing可以控制自身GUI系统的全部并有很好的可扩展和灵活性,它几乎可以创建所有你想象得到的组件。唯一的限制是它的AWT容器。在Swing中你还不能跨平台地实现真正的透明化和不规则矩形窗口,因为Swing依赖于AWT顶层容器例如Applet, Window, Frame and Dialog等。除此之外,Swing几乎实现了所有平台上的标准组件。
&&&&在组件特征上,Swing遵循最小公倍数原则。它拥有所有平台上可提供的组件特征。不仅如此,你还可以继承已有的Swing组件并添加新的特性。
&&&上面比较主要是在API级别上的。让我们将比较的焦点转移到实现细节上。Swing和SWT/AWT的区别是Swing是纯Java实现,而SWT和AWT是Java和JNI的混合。当然,它们的目标都是相同的,提供一个跨平台的APIs。然而为了达到这一点,SWT和AWT不得不牺牲一些组件和特性以提供一个通用的APIs。
&&&&一个AWT组件通常是一个包含了对等体接口类型引用的组件类。这个引用指向本地对等体实现。举java.awt.Label为例,它的对等体接口是LabelPeer。LabelPeer是平台无关的。在不同平台上,AWT提供不同的对等体类来实现LabelPeer。在Windows上,对等体类是WlabelPeer,它调用JNI来实现label的功能。这些JNI方法用C或C++编写。它们关联一个本地的label,真正的行为都在这里发生。作为整体,AWT组件由AWT组件类和AWT对等体提供了一个全局公用的API给应用程序使用。一个组件类和它的对等体接口是平台无关的。底层的对等体类和JNI代码是平台相关的。
SWT&&&&SWT也使用JNI的方法论来实现。但细节不同于AWT。SWT的拥护者听到人们拿SWT和AWT相提并论可是会很生气的,Steve Northover,SWT之父,就曾为此抱怨过。&&&&没错,它们是不同的。让我们深究SWT的代码。在SWT中,各个平台上唯一相同的部分是组件的接口,是类和方法的定义签名。所有的底层代码都是平台差异的。SWT为每个平台提供了OS类。这个类用JNI封装了许多本地APIs。SWT组件类通过把这些JNI方法黏合在一起提供一个有意义的功能。&&&&例如,在Windows上,文本域的选择是由一个系统调用处理的。这个系统调用在Windows的OS类中作为一个本地方法实现。所以在Windows平台的Text的setSelection方法中只用到了一个JNI调用。&&&&然而,在motif上,文本域的选择包含两个本地调用。SWT就在motif的OS类中实现了两个调用。所以在motif上组件类需要作两次调用来实现文本的选择。&&&&现在你应该能看出SWT和AWT的最大不同了,它们使用了不同的对等体编程方式来消除平台差异。SWT用java代码或有JNI实现的java对等体来黏合系统调用。而AWT把代码包含在对等体中,使情况复杂化了,我个人觉得SWT的方法更加明智。
&&&&到了Swing这里,一切就变得清晰和直接了。除了顶层容器,Swing的实现不依赖于具体平台。它掌管了所有的控制和资源。Swing所需要的是事件输入来驱动系统,以及承接自顶层AWT容器的图形处理,字体和颜色。普通的Swing组件可以看作是AWT容器的一块逻辑区域。它们并没有注册对等体。所有添加到同一顶层容器的Swing组件共享它的AWT对等体以获取系统资源,如字体,图形处理等。Swing将组件自己的数据结构存储在JVM的空间中。它完全由自己管理画图处理,事件分发和组件布局。
&&&&由于AWT和SWT都持有对本地组件的引用,它们必须以正确的方式释放这些引用以避免内存泄露和JVM崩溃。AWT将绝大多数资源管理任务交给系统,将开发者从单调乏味的资源管理中解救出来。然而这使得AWT的实现复杂化了。一旦它实现了,开发者很少有机会犯错误并使他们的程序崩溃。&&&&SWT用的是另一种方法。大体上,SWT让开发者自己来管理资源。它的一条著名的规则是:谁创建,谁释放。因此开发者必须谨慎地显式调用dispose方法释放每一个由他创建的组件和资源。这简化了SWT的实现模型,但把开发者摆在了因错误编码而易于造成程序崩溃这一风险之上。
模拟方式的区别
&&&Swing和SWT在它们的实现上都使用了模拟。SWT只模拟平台上缺失的组件。区别是SWT的模拟更像是AWT的Canvas实现的模拟。SWT的Composite类有它自己在操作系统中相应的对等体。它从自己的对等体中获得所有它所需要的资源如图形处理的对象,字体和颜色等。它直接从操作系统获取所有的事件并进行处理。然而,Swing组件在操作系统中没有相应的对等体。它只是一块顶层容器中的逻辑区域,实际上它从顶层容器的对等体中借用资源。Swing的事件并不是底层系统产生的事件。它们实际是由顶层容器处理AWT事件所产生的伪事件。我们会在稍后的事件部分中详细介绍它。
图形层结构
&&&&另一个不同之处是Swing组件的z-order系统是来自于AWT组件的。如上所述,Swing组件与顶层AWT容器共享一个对等体。因此,Swing组件也和顶层容器有相同的z-order。SWT和AWT组件都有不同于顶层容器的z-order,通常是高于顶层容器。故而如果AWT组件和Swing组件混合在一起的话,Swing组件将可能被AWT组件遮住。当操作系统开始更新UI的时候,顶层容器和Swing组件总是先于AWT组件绘制。当它们完成绘制,AWT组件会覆盖Swing可能绘制过的地方。因此不提倡Swing和AWT组件的混用。如果有一个浮动的Swing组件如菜单,AWT组件很可能遮盖菜单。
布局管理器
&&&&并不是三者中的所有部分都是不同的。布局管理器是一个例外。开发GUI应用程序,当容器改变大小的时候,组件需要重定位或改变大小。在传统的编程语言中,这依靠监听大小改变的事件来实现。相应的片段散落在源代码的各个角落降低了程序的可读性。Java引入了将布局代码封装的思路,称之为布局管理器。当布局管理器对象被设置到一个容器中,它自动处理大小改变的事件。当大小改变时,管理器的布局方法被调用以重定位子组件或调整它们的形状。&&&&AWT,SWT和Swing都以这样的方式来组织,而都有它们各种独特的布局管理器。由于AWT和Swing拥有一个共同的超类ponent,它们的布局管理器可以交替地使用。Look And Feel观感&&&&包括SWT和AWT在内的本地工具集并不支持Look And Feel机制。它们将组件捆绑在操作系统上,有其优势和劣势。其中的一个劣势是它们不支持可插拔的Look And Feel。将绘制处理交由操作系统完成剥夺了它们实现自定义组件Look And Feel的能力,也就使得它们无法提供这种机制。Look And Feel机制越来越成为GUI工具集中不可缺少的一部分。
&&&&Swing拥有很好的Look And Feel支持。你甚至可以动态地改变Swing应用程序的Look And Feel,鉴于AWT和SWT将组件控制完全交给操作系统处理,这是它们所无法超越的任务。我曾经听很多人抱怨过Sun在Swing上的设计。他们觉得Swing为什么不像SWT那样沿用AWT的思路呢?事实上,Look And Feel机制正是Swing走到这个方向上的原因之一。如果Swing遵循的是包装已有的组件并模拟不存在的组件的路线,那它就无法提供Look And Feel机制。因为提供Look And Feel机制是本地策略所无法完成的任务。
Graphics and Fonts图形和字体
&&&&Swing作为一个仿生系统,它的图形工具集较之AWT和SWT强大许多。Swing基于其自身系统中的两个基础组件群:Java 2D和AWT。Java 2D在Java中是强大的类库,它为高级图像处理,颜色管理,图形绘制和填充,坐标系变换和字体生成提供丰富的特性。相较之下,AWT和AWT仅对这些特性提供有限访问,它们是相对原始和低级的。
JavaBeans Specification Conformity JavaBeans规范一致性
&&&&Swing和AWT在设计之初就秉承了JavaBeans规范,它们的组件类与JavaBeans规范一致。然而SWT并没有很好的遵循这一规范。例如,在SWT的组件类中没有无参的构造器。每个组件都必须至少拥有一个单参数的构造器。这个参数就是父组件的引用。这意味着无论何时组件被创建,它都直接被添加到一棵组件树中。一个组件无法脱离于已注册的本地对等体而存在。这样,SWT就能让由编程者创建的组件在display的dispose方法被调用的时候自动被释放。
More on Resource Management更多在资源管理方面的内容
&&&&SWT的组件构造器策略可以排除某些内存泄露的可能性。AWT在资源管理方面也有类似的问题。但它采用了不同的方式解决。当AWT组件被创建的时候,相应的对等体并不会立即被创建。即便它被添加到一棵组件树,而如果这棵树还不可见,那么对等体仍不会被创建。只有当顶层容器被设为可见,这些对等体才会被创建。创建对等体的方法通常在addNotify中,它们通常递归地调用父组件的addNotify直到整棵组件树上的对等体都被创建了。当顶层容器由dispose方法销毁的时候,一个对应的方法removeNotify将会被递归地调用以释放这些对等体。这样,AWT在不由开发者介入的情况下管理了它的资源。
Event System事件系统
&&&&一个事件要求特定的动作被执行,它被作为消息由外界或系统自身发送给GUI系统。这些事件包括来自计算机设备如鼠标键盘和网络端口的I/O中断,以及GUI系统的逻辑事件触发,比如一个按钮的ActionEvent事件。
Single-Threaded vs Multiple-Threaded 单线程 vs 多线程
事件分发遵循两种不同的模型。单线程分发模型和多线程分发模型。
&&&&在单线程分发模型中,一个事件从队列中抽出并在同一个线程中被立即处理。事件处理后,紧跟着的下一个事件再被抽出并继续下一轮的循环。在多线程分发模型中,从队列中获取事件的线程启动另一个被称作任务线程的线程,并把事件交给它处理。而获取事件的线程并不等待处理线程的结束。它简单的获取下一个线程并分发它。&&&&事件处理通常涉及应用程序的数据变化。而且这些数据经常是组件需要显示的。多线程分发很容易产生同步问题,它产生多个可能互相干扰的事件处理线程。在一个稳定的GUI系统中,组件应该能够保持视图与模型间的同步。由于同步问题的出现,多线程模型要求开发者拥有更多并发编程的经验。而对于普通编程人员,造成同步错误是很容易的。因此许多GUI系统并不使用这一模型。
&&&单线程模型通过强制事件序列化地被处理提供了实际上的同步。AWT,SWT和Swing 都采用了这一模型来分发事件。但单线程模型也会有它自己的问题。其中之一就是线程专注。既然所有的事件都在一个线程中被分发,如果其中的一个事件的处理费时过久,将会拖延下一个事件的抽取和执行。如果有一个PAINT事件被延后,那么在屏幕上就会呈现为无法响应。这经常使用户感觉到软件很慢。许多这样的低效程序是由于开发者的经验不足造成的。他们的做法是将耗时任务填充到监听器方法中。由于这种错误的编程方式在Swing中大量被使用而尤为突出,这也是它慢而丑陋的坏名声的由来之一。实际上,如果你懂得使用线程,Swing应用程序可以表现出很高的响应度。Thread Safety线程安全
&&&&上述问题的解决方案是启动一个单独的工作者线程来完成耗时处理,这样就能把事件分发线程释放处理以继续运作。如多线程模型中所做的那样,然而这同样会引入在多线程模型中出现的同步问题。许多GUI工具集都有自己先天性的机制来解决这一问题,例如,在组件树上的组合锁。开发者不需要为如何安全编程而操心。这样的工具集被成为线程安全的。AWT就是其中之一。&&&&然而,由于不必要的同步使得建立这样的GUI系统过于负责并造成了额外的开销。因此,Swing和SWT被设计为非线程安全的,这意味着开发者必须谨慎地实现他们的多线程任务。SWT和Swing在运行时线程安全行为上有一个小小的区别。SWT总是检查改变组件的操作是否在事件分发线程上执行。这样,开发者就能够发现同步问题。而Swing不这样,这是Swing的一个不知之初,这其实并不难实现。Event Dispatching Thread事件分发线程&&&&AWT读取操作系统中的基本事件并在java代码中处理它们。AWT事件分发线程被命名为?AWT-{OS}-Thread。这个线程由AWT系统隐式启动。当AWT应用程序启动时,这个线程在背后启动,在操作系统上抽取和移除事件。当诸如按钮动作这样的逻辑事件被触发时,它传递给注册在按钮上的操作监听器。开发者也能为AWT组件编写鼠标,键盘和绘制事件的事件监听器。这通常通过扩展AWT Canvas组件来完成。这一组件支持了所有已提供的事件,而且你可以通过重写事件处理方法,实现一个自定义的组件。&&&&然而,在Swing中,这是一个不同的线程。Swing把AWT事件作为自身事件系统的一个输入。它获取AWT事件并做一些初始化处理,产生一个对应的Swing事件并把它放到自己的事件队列上。Swing也有自己的事件分发线程,通常命名为EventQueue-0。这个线程从事件队列中抽取Swing事件,就如同AWT从操作系统中抽取那样。然后它把事件分发给目标组件。通常事件首先被分发给组件的顶层容器,然后由顶层容器的dispatch方法处理,它可能被再分发或重定向到一个Swing组件,在那里继续由自己的监听器进行处理。&&&&例如,当一个鼠标移过一个JButton或JFrame时,一个指向JFrame的AWT事件在AWT线程上触发。AWT线程检查它是否需要作更多的处理,然后把它包装成一个Swing的MouseEvent对象并把它添加到EventQueue队列中。当获得MouseEvent事件后,EventQueue-0抽取这个事件并判断出目标Swing组件。这里,这个组件是JButton。然后它产生了一个包含相对坐标位置和事件源的新的MouseEvent重定向到这个JButton上,然后调用这个JButton的dispatch以继续分发。JButton的dispatch过滤事件给特定的方法最终实现由鼠标监听器在该点上的分发的点击。&&&&SWT更类似于AWT。唯一的区别是它要求开发者显式地书写事件循环代码。然而底层的实现细节是不同于AWT的。看看SWT的读取和分发事件代码,它会让你想起MFC的代码风格。
Event Listener事件监听器
&&&AWT,SWT和Swing都有相似的事件监听器模型。它们都使用观察者模式,组件和监听器的连接方式是把监听器添加到组件上,这组成了一个对象网络的模型。当事件被触发并分发给组件,组件调用它的监听器以处理事件。一个监听器也可以继续分发事件给后续的处理,或产生一个新的事件并把它广播到网络中的其他节点上。基本上有两种不同的广播事件方式。一种是同步调用监听器。另一种是异步地将事件发送回队列,它将在新一轮的事件分发中被分发出去。
&&&&除了直接发送给队列的方式,Swing还有一些其他的分发异步事件的方法。其中之一是调用SwingUtilities 或EventQueue 的invokeLater,这一方法包装一个Runnable对象到事件中并把它发送给事件队列。这确保了Runnable的run方法能在事件分发线程上执行,保证了线程安全。实际上,Swing的Timer好SwingWorker基于这一机制实现。SWT也有相应的发送异步事件的方式。它的invokeLater的对应方法是display.asyncExec,它以一个Runnable对象作为参数。
我从一个技术层面给出了他们优劣势上的一个清单,以结束本文。
AWT是Sun不推荐使用的工具集。然而它在许多非桌面环境如移动或嵌入式设备中有着自己的优势。
更少的内存。它对运行在有限环境中的GUI程序的开发,是合适的。
1.更少的启动事件。由于AWT组件是本地由操作系统实现的。绝大多数的二进制代码已经在如系统启动的时候被预装载了,这降低了它的启动事件。
2.更好的响应。由于本地组件由操作系统渲染。3.从java 1.x时代就为JRE支持的标准GUI工具集,你不用单独安装它,你不用担心平台差异的问题。
4.成熟稳定的。它能够正常工作并很少使你的程序崩溃。
然而,事物都有它们不好的一面。让我们来例数它吧。1. 更少的组件类型。表和树这些重要的组件缺失了。它们是桌面应用程序中普遍使用的。
2.缺乏丰富的组件特征。按钮不支持图片附着。这很明显是它遵循的设计原则造成的。
3.不支持Look And Feel。AWT被设计为使用本地组件。因此,它依赖系统来提供Look And Feel支持。如果目标系统并不支持这一特性,那么AWT将无法改变它的Look And Feel。
4.无扩展性。AWT的组件是本地组件。JVM中的AWT类实例实际只是包含本地组件的引用。唯一的扩展点是AWT的Canvas组件,你可以从零开始创建自定义组件。然而无法继承和重用一个已有的AWT组件。
SWT&&&SWT有如下优势:
1.丰富的组件类型。SWT提供了种类繁多的组件,从基础组件如按钮和标签到高级的表格和树。
2.相对的丰富组件特性。尽管SWT也遵循最大公倍数原则,它采用模拟的方式重新设计了对更多组件特性的支持。所以同AWT相比,它有着相对丰富的组件特性。
3.更快的响应时间。基于和AWT同样的原因,SWT组件包装了本地组件,由操作系统实现渲染。操作系统通常对渲染处理做了优化,保存GUI二进制代码为标准库,减少了内存的使用,提高了响应性能。
4.更少的内存消耗。既然操作系统为本地组件提供了优化,这一点就容易理解了。
不足之处:
&&&&1.不在JRE的标准库中。因此你必须将它和你的程序捆绑在一起,并为你所要支持的每个操作系统创建单独的安装程序。
2.不够成熟和稳定。SWT因其设计上的一些缺陷,如资源管理,Windows友好等,被认为是不稳定的。它可以在Windows上表现得很好,但在其他操作系统上,它经常是不稳定且容易崩溃的。这很大程度上是因为它把资源管理交给开发者来处理,而并不是所有的开发人员能够正确地处理这些。
3.在非Windows平台下的性能不高。如同第2点提到的,SWT被设计为与Windows API相协调的,这导致了在非Windows平台上的性能问题,糟糕的UI感官,不稳定甚至内存泄露。
4.无Look And Feel 支持。和AWT同样的原因。
5.不可扩展,和AWT同样的原因。在SWT中你可以通过有限的方式扩展一个组件,例如,监听PAINT事件并添加自定义绘图到组件上,但鉴于你只能控制绘制处理的一部分,这是十分有限的。你也只能在操作系统绘制完组件后补充,这并不能很好支持自定义。许多应用程序在自定义行为上有很高的要求。
SWING&&&&Swing是三者中最强大的GUI工具集。它和另外两者相比同样有自己的优劣势。
1、丰富的组件类型。Swing提供了非常广泛的标准组件。这些组件和SWT一样丰富。基于它良好的可扩展性,除了标准组件,Swing还提供了大量的第三方组件。许多商业或开源的Swing组件库在开发多年后都已经可以方便地获取了。2、丰富的组件特性。Swing不仅包含了所有平台上的特性,它还支持根据程序所运行的平台来添加额外特性。Swing组件特性遵循特定原则,易于扩展,因此能够提供较SWT和AWT更多的功能。3、好的组件API模型支持。Swing遵循MVC模式,这是一种非常成功的设计模式。它的API成熟并设计良好。经过多年的演化,Swing组件APIs变得越来越强大,灵活和可扩展。它的API设计被认为是最成功的GUI API之一。较之SWT和AWT更面向对象,也更灵活而可扩展。4、出色的Look And Feel支持。MVC设计模型允许Swing分离组件视图和它的数据模型。它有高级的UI委托来将UI渲染委托给UI类。这些类被注册到一个展现特定的Look And Feel的对象上。已经有上百个Look And Feel 可以提高各种各样的GUI风格。你甚至可以基于其他人的成果编写组件的Look And Feel 。5、标准的GUI库。Swing和AWT一样是JRE中的标准库。因此,你不用单独地将它们随你的应用程序一起分发。它们是平台无关的,所以你不用担心平台兼容性。6、成熟稳定。Swing已经开发出来7年之久了。在Java5之后它变得越来越成熟稳定。由于它是纯Java实现的,不会有SWT的兼容性问题。Swing在每个平台上都有相同的性能,不会有明显的性能差异。7、可扩展和灵活性。Swing完全在Java空间中实现。它可以控制它所需要的一起。Swing基于MVC的结构使得它可以发挥Java作为一门面向对象语言的优势。它提供了许多扩展组件的方法。让我们来列举一下:A.继承已有组件;B.靠复合组件的方式扩展。C.从零开始使用JComponent编写自定义组件;D.使用渲染器和编辑器机制扩展复制的Swing组件,如JList,JComboBox,JTable,JTree等;E.基于已有Look And Feel 或从零开始创建新的Look And Feel;F.使用LayeredPane,GlassPane或拖放机制开发高级的组件,例如浮动的固定组件,自定义弹出窗口,自定义菜单等。8、总体上良好的性能。Swing的速度是其为人诟病的一点。然而随着JRE的开发,Swing的性能如今已经有了很大的提高。特别是Java5之后,Swing的总体速度能够接近本地小控件系统。
一个GUI的速度总是从两个方面被衡量:响应时间和数据反馈时间。
&&&&响应事件指从事件任务出现到组件更新UI的这段时间。例如按下一个按钮,拖动一个组件,改变一个多标签面板等。在这个方面本地组件总能比模拟组件有更好的响应。AWT和SWT通常比Swing表现出更好的响应时间。然而事实并非总是如此。这取决于操作系统。如果本地组件没有被良好的实现,那结果就是相反的。例如Windows开发了不错的GUI库,而Linux平台通常差得较远。SWT可能在Windows上表现得比Swing好,而在Linux上表现得比Swing差。也就是说,AWT/SWT的性能决定于底层平台。随着JRE的开发,Swing的响应性能能够随着JVM的优化,更好的实现方式,以及图形硬件加速而得到长足的改进。在Windows上,Java6的Swing可以媲美SWT的性能。在非Windows环境中,Swing可以表现出更好的响应时间。&&&&&数据输送时间是指用于将应用程序数据传递给UI组件所需要的时间。例如,一个学生管理系统要求从数据库中装载学生信息并在一个表格中显示出来。花费在从内存到表格组件的数据传递时间被称为数据输送时间.在这个方面,Swing通常比其他二者的性能更好。或许当数据量不大的情况下并不明显。但当海量的数据被输送给表格的时候,这一点就显而易见了。为了理解这一点,提醒你注意JVM和本地操作系统是两个分离的运行时环境。由于JNI的调用在两个环境中跨越式地发生,通常比一个普通的Java调用花费更长的时间。通常这包含两个处理。一个是Java数据结构转换为本地数据结构,另一个是方法返回时的本地数据结构转换为Java对象。其他的性能开销暂时忽略不计。当一个大范围数组的数据从本地组件中输送过来,大量反复的JNI调用将极大地拖垮性能。
&&&&&Swing的另一个优势是它有许多的组件模型以提高输送的性能。例如TableModel被映射为两个维度上的数组。这样,在Swing组件中甚至不需要进行数据方式的转换。Swing直接将应用程序数据显示在屏幕上,节省了在数据转换上所花费的事件。
Swing也有不足之处:
&&&&&比AWT和SWT更多的内存消耗。Swing自己实现了所有组件。因此,它在运行时装载了大量的类。一些其他的问题来源于小的可变对象的创建,如Rectangle,Point,这些对象基于同步的考虑通常不可重用。Java在堆上创建所以对象。小的对象通常导致了额外的堆空间消耗。许多小的对象较之大对象更难以有效地被垃圾回收。因此,Swing应用程序通常无法及时回收大而小的对象。这种情况的普遍就会导致性能下降。&&&&更多的启动时间。现在JVM已经快得多了。许多人甚至扬言它可以媲美C++的实现。但多数的Java应用程序还是看上去很慢。实际上,Java性能的很多问题来源于类装载机制。这是一个I/O操作,故而能够明显地降低Java应用程序的速度。也许这是每个动态链接系统中都要面对的问题吧。Swing通常包含了上千个Swing类的使用,在Swing应用程序可以显示它的主窗口之前,它比AWT或SWT装载了多得多的类。这严重降低了Swing的启动时间。这种问题也许会相对好一点如果Swing的类是以共享系统库的方式预加载的。&&&&&&&上述的比较总的来说是技术上的总结。相对其他方面的因素也会影响你对一个工具集的选择。例如,文档,支持,学习曲线和社区等,但既然我们关注的是技术层面,就不在这里讲的太多了。
阅读排行榜

我要回帖

更多关于 awt和swing 的文章

 

随机推荐