分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
59.java编程思想——创建窗口和程序片 Swing
当我们的工作方法在AWT 中发生了巨大的改变后(如果可以回忆起很久以前,当Java 第
一次面世时SUN 公司曾声明Java 是一种“稳定,牢固”的编程语言),可能一直有Java 还不十分的成熟的感觉。的确,现在Java 拥有一个不错的事件模型以及一个优秀的组件复用设计——JavaBeans。但GUI 组件看起来还相当的原始,笨拙以及相当的抽象。
Swing 库在Java 1.1 之后面世,因此我们可以自然而然地假设它是Java1.2 的一部分。可是,它是设计为作为一个补充在Java 1.1 版中工作的。这样,我们就不必为了享用好的UI组件库而等待我们的平台去支持Java 1.2 版了。如果Swing 库不是我们的用户的Java 1.1 版所支持的一部分,并且产生一些意外,那他就可能真正的需要去下载Swing库了。
Swing 包含所有我们缺乏的组件是一个大库,但在某些方面它为任务被设计得相应的复杂——如果任何事都是简单的,我们不必编写更多的代码但同样设法运行我们的代码逐渐地变得更加的复杂。这意味着一个容易的入口,如果我们需要它我们得到它的强大力量。
Swing 相当的深奥,不会去试图让读者理解,但会介绍它的能力和Swing 简单地使我们着手使用库。有意识的使用这一切变得简单。如果我们需要运行更多的,这时Swing 能或许能给我们所想要的,如果我们愿意深入地研究,可以从SUN 公司的在线文档中获取更多的资料。
1 S w i n g 有哪些优点
当我们开始使用Swing 库时,会注意到它在技术上向前迈出了巨大的一步。Swing 组件是Bean,因此他们可以支持Bean 的任何开发环境中使用。Swing 提供了一个完全的UI 组件集合。因为速度的关系,所有的组件都很小巧的(没有“重量级”组件被使用),Swing 为了轻便在Java 中整个被编写。最重要的是我们会希望Swing 被称为“正交使用”;一旦我们采用了这种关于库的普遍的办法我们就可以在任何地方应用它们。这主要是因为Bean 的命名规则,大多数的时候在我编写这些程序例子时我可以猜到方法名并且第一次就将它拼写正确而无需查找任何事物。这无疑是优秀库设计的品质证明。另外,我们可以广泛地插入组件到其它的组件中并且事件会正常地工作。
键盘操作是自动被支持的——我们可以使用Swing 应用程序而不需要鼠标,但我们不得不做一些额外的编程工作(老的AWT 中需要一些可怕的代码以支持键盘操作)。滚动被毫不费力地支持——我们简单地将我们的组件到一个JScrollPane 中,同样我们再增加它到我们的窗体中即可。其它的特征,例如工具提示条只需要一行单独的代码就可执行。
Swing 同样支持一些被称为“可插入外观和效果”的事物,这就是说UI 的外观可以在不同的平台和不同的操作系统上被动态地改变以符合用户的期望。它甚至可以创造我们自己的外观和效果。
2 方便的转换
如果我们长期艰苦不懈地利用Java 1.1 版构建我们的UI,我们并不需要扔掉它改变到Swing 阵营中来。幸运的是,库被设计得允许容易地修改——在很多情况下我们可以简单地放一个“J”到我们老AWT 组件的每个类名前面即可。
2.1 代码
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
publicclass JButtonDemo extends Applet {
JButton b1 =new JButton("JButton 1"),b2 = new JButton("JButton 2");
JTextField t =new JTextField(20);
publicvoidinit() {
ActionListener al = new ActionListener() {
publicvoid actionPerformed(ActionEvent e) {
String name = ((JButton) e.getSource()).getText();
t.setText(name +"Pressed");
}
};
b1.addActionListener(al);
add(b1);
b2.addActionListener(al);
add(b2);
add(t);
}
publicstaticvoidmain(Stringargs[]){
JButtonDemo applet =new JButtonDemo();
JFrame frame =new JFrame("TextAreaNew");
frame.addWindowListener(new WindowAdapter() {
publicvoid windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.getContentPane().add(applet, BorderLayout.CENTER);
frame.setSize(300, 100);
applet.init();
applet.start();
frame.setVisible(true);
}
} /// :~
这是一个新的输入语句,但此外任何事物除了增加了一些“J”外,看起都像这Java 1.1 版的AWT。同样,不恰当的用add()方法增加到Swing JFrame 中,除此之外我们必须像上面看到的一样先准备一些“content pane”。我们可以容易地得到Swing 一个简单的改变所带来的好处。
3 显示框架
尽管程序片和应用程序都可以变得很重要,但如果在任何地方都使用它们就会变得混乱和毫无用处。余下部分取代它们的是一个Swing 程序例子的显示框架:
3.1 代码
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
publicclass Show {
publicstaticvoidinFrame(JPaneljp,intwidth,intheight){
String title =jp.getClass().toString();
// Remove the word "class":
if (title.indexOf("class") != -1)
title =title.substring(6);
JFrame frame =new JFrame(title);
frame.addWindowListener(new WindowAdapter() {
publicvoid windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.getContentPane().add(jp, BorderLayout.CENTER);
frame.setSize(width,height);
frame.setVisible(true);
}
} /// :~
那些想显示它们自己的类将从JPanel 处继承并且随后为它们自己增加一些可视化的组件。最后,它们创建一个包含下面这一行程序的main():
Show.inFrame(new MyClass(), 500,300);
最后的两个自变量是显示的宽度和高度。注意JFrame 的标题是用RTTI 产生的。
4 工具提示
几乎所有我们利用来创建我们用户接口的来自于JComponent 的类都包含一个称为setToolTipText(string)的方法。因此,几乎任何我们所需要表示的(对于一个对象jc 来说就是一些来自JComponent 的类)都可以安放在窗体中:
jc.setToolTipText("Mytip");
并且当鼠标停在JComponent 上一个超过预先设置的一个时间,一个包含我们的文字的小框就会从鼠标下弹出。
5 边框
JComponent 同样包括一个称为setBorder()的方法,该方法允许我们安放一些各种各样有趣的边框到一些可见的组件上。下面的程序例子利用一个创建JPanel 并安放边框到每个例子中的被称为showBorder()的方法,示范了一些有用的不同的边框。同样,它也使用RTTI 来找我们使用的边框名(剔除所有的路径信息),然后将边框名放到面板中间的JLable里:
5.1 代码
import java.awt.*;
importjava.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
publicclass Borders extends JPanel {
static JPanel showBorder(Borderb) {
JPanel jp =new JPanel();
jp.setLayout(new BorderLayout());
String nm =b.getClass().toString();
nm = nm.substring(nm.lastIndexOf('.') + 1);
jp.add(new JLabel(nm, JLabel.CENTER), BorderLayout.CENTER);
jp.setBorder(b);
returnjp;
}
public Borders() {
setLayout(new GridLayout(2, 4));
add(showBorder(new TitledBorder("Title")));
add(showBorder(new EtchedBorder()));
add(showBorder(new LineBorder(Color.blue)));
add(showBorder(new MatteBorder(5, 5, 30,30, Color.green)));
add(showBorder(newBevelBorder(BevelBorder.RAISED)));
add(showBorder(newSoftBevelBorder(BevelBorder.LOWERED)));
add(showBorder(new CompoundBorder(new EtchedBorder(),new LineBorder(Color.red))));
}
publicstaticvoidmain(Stringargs[]){
Show.inFrame(new Borders(), 500, 300);
}
} /// :~
例子都使用TitledBorder,但我们可以注意到其余的边框也同样易于使用。能创建我们自己的边框并安放它们到按钮、标签等等内——任何来自JComponent 的东西。
6 按钮
Swing 增加了一些不同类型的按钮,并且它同样可以修改选择组件的结构:所有的按钮、复选框、单选钮,甚至从AbstractButton 处继承的菜单项(这是因为菜单项一般被包含在其中,它可能会被改进命名为“AbstractChooser”或者相同的什么名字)。我们会注意使用菜单项的简便,下面的例子展示了不同类型的可用的按钮:
6.1 代码
importjava.awt.*;
importjava.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.border.*;
publicclass Buttons extends JPanel {
JButton jb =new JButton("JButton");
BasicArrowButtonup = newBasicArrowButton(BasicArrowButton.NORTH),
down =new BasicArrowButton(BasicArrowButton.SOUTH),right = newBasicArrowButton(BasicArrowButton.EAST),
left =new BasicArrowButton(BasicArrowButton.WEST);
public Buttons() {
add(jb);
add(new JToggleButton("JToggleButton"));
add(new JCheckBox("JCheckBox"));
add(new JRadioButton("JRadioButton"));
JPanel jp =new JPanel();
jp.setBorder(new TitledBorder("Directions"));
jp.add(up);
jp.add(down);
jp.add(left);
jp.add(right);
add(jp);
}
publicstaticvoidmain(Stringargs[]){
Show.inFrame(new Buttons(), 300, 200);
}
} /// :~
JButton 看起来像AWT 按钮,但它没有更多可运行的功能(像我们后面将看到的如加入图像等)。在com.sun.java.swing.basic 里,有一个更合适的BasicArrowButton按钮,但怎样测试它呢?有两种类型的“指针”恰好请求箭头按钮使用:Spinner 修改一个中断值,并且StringSpinner 通过一个字符串数组来移动(当它到达数组底部时,甚至会自动地封装)。ActionListeners 附着在箭头按钮上展示它使用的这些相关指针:因为它们是Bean,我们将期待利用方法名,正好捕捉并设置它们的值。
当我们运行这个程序例子时,我们会发现触发按钮保持它最新状态,开或时关。但复选框和单选钮每一个动作都相同,选中或没选中(它们从JToggleButton 处继承)。
7 按钮组
如果我们想单选钮保持“异或”状态,我们必须增加它们到一个按钮组中,这几乎同老AWT 中的方法相同但更加的灵活。在下面将要证明的程序例子是,一些AbstruactButton能被增加到一个ButtonGroup 中。
为避免重复一些代码,这个程序利用映射来生不同类型的按钮组。这会在makeBPanel中看到,makeBPanel创建了一个按钮组和一个JPanel,并且为数组中的每个String 就是makeBPanel 的第二个自变量增加一个类对象,由它的第一个自变量进行声明:
7.1 代码
importjava.awt.*;
importjava.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.lang.reflect.*;
publicclass ButtonGroups extends JPanel {
static String[]ids= { "June","Ward","Beaver",
"Wally","Eddie","Lumpy",};
static JPanel makeBPanel(ClassbClass, String[] ids){
ButtonGroup bg =new ButtonGroup();
JPanel jp =new JPanel();
String title =bClass.getName();
title =title.substring(title.lastIndexOf('.') + 1);
jp.setBorder(new TitledBorder(title));
for (inti = 0; i < ids.length; i++) {
AbstractButton ab = new JButton("failed");
try {
// Get the dynamic constructor method
// that takes a String argument:
Constructor ctor = bClass.getConstructor(new Class[] {String.class });
// Create a new object:
ab = (AbstractButton)ctor.newInstance(new Object[] {ids[i] });
} catch (Exceptionex) {
System.out.println("can't create "+bClass);
}
bg.add(ab);
jp.add(ab);
}
returnjp;
}
public ButtonGroups() {
add(makeBPanel(JButton.class,ids));
add(makeBPanel(JToggleButton.class,ids));
add(makeBPanel(JCheckBox.class,ids));
add(makeBPanel(JRadioButton.class,ids));
}
publicstaticvoidmain(Stringargs[]){
Show.inFrame(new ButtonGroups(), 500,300);
}
} /// :~
边框标题由类名剔除了所有的路径信息而来。AbstractButton 初始化为一个JButton,JButtonr 的标签发生“失效”,因此如果我们忽略这个异常信息,我们会在屏幕上一直看到这个问题。getConstructor()方法产生了一个通过getConstructor()方法安放自变量数组类型到类数组的构建器对象,然后所有我们要做的就是调用newInstance(),通过它一个数组对象包含我们当前的自变量——在这种例子中,就是ids数组中的字符串。
这样增加了一些更复杂的内容到这个简单的程序中。为了使“异或”行为拥有按钮,我们创建一个按钮组并增加每个按钮到我们所需的组中。当我们运行这个程序时,我们会注意到所有的按钮除了JButton 都会向我们展示“异或”行为。
8 图标
我们可在一个JLable 或从AbstractButton 处继承的任何事物中使用一个图标(包括JButton,JCheckbox,JradioButton及不同类型的JMenuItem)。利用JLables 的图标十分的简单容易(我们会在随后的一个程序例子中看到)。下面的程序例子探索了我们可以利用按钮的图标和它们的衍生物的其它所有方法。
我们可以使用任何我们需要的GIF 文件,但在这个例子中使用的这个GIF 文件是这本书编码发行的一部分。为了打开一个文件和随之带来的图像,简单地创建一个图标并分配它文件名。从那时起,我们可以在程序中使用这个产生的图标。
8.1 代码
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.*;
publicclass Facesextends JPanel {
staticIcon[]faces = { newImageIcon("face0.gif"),newImageIcon("face1.gif"),newImageIcon("face2.gif"),
newImageIcon("face3.gif"),newImageIcon("face4.gif"), };
JButton jb =newJButton("JButton",faces[3]),jb2 =newJButton("Disable");
booleanmad = false;
publicFaces() {
jb.addActionListener(newActionListener() {
publicvoidactionPerformed(ActionEvent e) {
if (mad) {
jb.setIcon(faces[3]);
mad =false;
} else {
jb.setIcon(faces[0]);
mad =true;
}
jb.setVerticalAlignment(JButton.TOP);
jb.setHorizontalAlignment(JButton.LEFT);
}
});
jb.setRolloverEnabled(true);
jb.setRolloverIcon(faces[1]);
jb.setPressedIcon(faces[2]);
jb.setDisabledIcon(faces[4]);
jb.setToolTipText("Yow!");
add(jb);
jb2.addActionListener(newActionListener() {
publicvoidactionPerformed(ActionEvent e) {
if (jb.isEnabled()){
jb.setEnabled(false);
jb2.setText("Enable");
} else {
jb.setEnabled(true);
jb2.setText("Disable");
}
}
});
add(jb2);
}
publicstatic voidmain(Stringargs[]) {
Show.inFrame(newFaces(), 300, 200);
}
} ///:~
一个图标可以在许多的构建器中使用,但我们可以使用setIcon()方法增加或更换图标。这个例子同样展示了当事件发生在JButton(或者一些AbstractButton)上时,为什么它可以设置各种各样的显示图标:当JButton被按下时,当它被失效时,或者“滚过”时(鼠标从它上面移动过但并不击它)。我们会注意到那给了按钮一种动画的感觉。
注意工具提示条也同样增加到按钮中。
9 菜单
菜单在Swing 中做了重要的改进并且更加的灵活——例如,我们可以在几乎程序中任何地方使用他们,包括在面板和程序片中。语法同它们在老的AWT 中是一样的,并且这样使出现在老AWT 的在新的Swing 也出现了:我们必须为我们的菜单艰难地编写代码,并且有一些不再作为资源支持菜单(其它事件中的一些将使它们更易转换成其它的编程语言)。另外,菜单代码相当的冗长,有时还有一些混乱。下面的方法是放置所有的关于每个菜单的信息到对象的二维数组里(这种方法可以放置我们想处理的任何事物到数组里),这种方法在解决这个问题方面领先了一步。这个二维数组被菜单所创建,因此它首先表示出菜单名,并在剩余的列中表示菜单项和它们的特性。我们会注意到数组列不必保持一致——只要我们的代码知道将发生的一切事件,每一列都可以完全不同。
9.1 代码
import java.awt.*;