标签:released bool 特征 tla open 字符 field 那是 lpm
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 公司的在线文档中获取更多的资料。
当我们开始使用Swing 库时,会注意到它在技术上向前迈出了巨大的一步。Swing 组件是Bean,因此他们可以支持Bean 的任何开发环境中使用。Swing 提供了一个完全的UI 组件集合。因为速度的关系,所有的组件都很小巧的(没有“重量级”组件被使用),Swing 为了轻便在Java 中整个被编写。最重要的是我们会希望Swing 被称为“正交使用”;一旦我们采用了这种关于库的普遍的办法我们就可以在任何地方应用它们。这主要是因为Bean 的命名规则,大多数的时候在我编写这些程序例子时我可以猜到方法名并且第一次就将它拼写正确而无需查找任何事物。这无疑是优秀库设计的品质证明。另外,我们可以广泛地插入组件到其它的组件中并且事件会正常地工作。
键盘操作是自动被支持的——我们可以使用Swing 应用程序而不需要鼠标,但我们不得不做一些额外的编程工作(老的AWT 中需要一些可怕的代码以支持键盘操作)。滚动被毫不费力地支持——我们简单地将我们的组件到一个JScrollPane 中,同样我们再增加它到我们的窗体中即可。其它的特征,例如工具提示条只需要一行单独的代码就可执行。
Swing 同样支持一些被称为“可插入外观和效果”的事物,这就是说UI 的外观可以在不同的平台和不同的操作系统上被动态地改变以符合用户的期望。它甚至可以创造我们自己的外观和效果。
如果我们长期艰苦不懈地利用Java 1.1 版构建我们的UI,我们并不需要扔掉它改变到Swing 阵营中来。幸运的是,库被设计得允许容易地修改——在很多情况下我们可以简单地放一个“J”到我们老AWT 组件的每个类名前面即可。
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
public class JButtonDemo extends Applet {
JButton b1 = new JButton("JButton 1"), b2 = new JButton("JButton 2");
JTextField t = new JTextField(20);
public voidinit() {
ActionListener al = new ActionListener() {
public void 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);
}
public staticvoidmain(String args[]){
JButtonDemo applet = new JButtonDemo();
JFrame frame = new JFrame("TextAreaNew");
frame.addWindowListener(new WindowAdapter() {
public void 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 一个简单的改变所带来的好处。
尽管程序片和应用程序都可以变得很重要,但如果在任何地方都使用它们就会变得混乱和毫无用处。余下部分取代它们的是一个Swing 程序例子的显示框架:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Show {
public staticvoidinFrame(JPanel jp,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() {
public void 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 产生的。
几乎所有我们利用来创建我们用户接口的来自于JComponent 的类都包含一个称为setToolTipText(string)的方法。因此,几乎任何我们所需要表示的(对于一个对象jc 来说就是一些来自JComponent 的类)都可以安放在窗体中:
jc.setToolTipText("Mytip");
并且当鼠标停在JComponent 上一个超过预先设置的一个时间,一个包含我们的文字的小框就会从鼠标下弹出。
JComponent 同样包括一个称为setBorder()的方法,该方法允许我们安放一些各种各样有趣的边框到一些可见的组件上。下面的程序例子利用一个创建JPanel 并安放边框到每个例子中的被称为showBorder()的方法,示范了一些有用的不同的边框。同样,它也使用RTTI 来找我们使用的边框名(剔除所有的路径信息),然后将边框名放到面板中间的JLable里:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class Borders extends JPanel {
static JPanel showBorder(Border b) {
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);
return jp;
}
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))));
}
public staticvoidmain(String args[]){
Show.inFrame(new Borders(), 500, 300);
}
} /// :~
例子都使用TitledBorder,但我们可以注意到其余的边框也同样易于使用。能创建我们自己的边框并安放它们到按钮、标签等等内——任何来自JComponent 的东西。
Swing 增加了一些不同类型的按钮,并且它同样可以修改选择组件的结构:所有的按钮、复选框、单选钮,甚至从AbstractButton 处继承的菜单项(这是因为菜单项一般被包含在其中,它可能会被改进命名为“AbstractChooser”或者相同的什么名字)。我们会注意使用菜单项的简便,下面的例子展示了不同类型的可用的按钮:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.border.*;
public class Buttons extends JPanel {
JButton jb = new JButton("JButton");
BasicArrowButton up = new BasicArrowButton(BasicArrowButton.NORTH),
down = new BasicArrowButton(BasicArrowButton.SOUTH), right = new BasicArrowButton(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);
}
public staticvoidmain(String args[]){
Show.inFrame(new Buttons(), 300, 200);
}
} /// :~
JButton 看起来像AWT 按钮,但它没有更多可运行的功能(像我们后面将看到的如加入图像等)。在com.sun.java.swing.basic 里,有一个更合适的BasicArrowButton按钮,但怎样测试它呢?有两种类型的“指针”恰好请求箭头按钮使用:Spinner 修改一个中断值,并且StringSpinner 通过一个字符串数组来移动(当它到达数组底部时,甚至会自动地封装)。ActionListeners 附着在箭头按钮上展示它使用的这些相关指针:因为它们是Bean,我们将期待利用方法名,正好捕捉并设置它们的值。
当我们运行这个程序例子时,我们会发现触发按钮保持它最新状态,开或时关。但复选框和单选钮每一个动作都相同,选中或没选中(它们从JToggleButton 处继承)。
如果我们想单选钮保持“异或”状态,我们必须增加它们到一个按钮组中,这几乎同老AWT 中的方法相同但更加的灵活。在下面将要证明的程序例子是,一些AbstruactButton能被增加到一个ButtonGroup 中。
为避免重复一些代码,这个程序利用映射来生不同类型的按钮组。这会在makeBPanel中看到,makeBPanel创建了一个按钮组和一个JPanel,并且为数组中的每个String 就是makeBPanel 的第二个自变量增加一个类对象,由它的第一个自变量进行声明:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.lang.reflect.*;
public class ButtonGroups extends JPanel {
static String[] ids= { "June","Ward","Beaver",
"Wally", "Eddie","Lumpy",};
static JPanel makeBPanel(Class bClass, 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 (int i = 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 (Exception ex) {
System.out.println("can‘t create "+ bClass);
}
bg.add(ab);
jp.add(ab);
}
return jp;
}
public ButtonGroups() {
add(makeBPanel(JButton.class, ids));
add(makeBPanel(JToggleButton.class, ids));
add(makeBPanel(JCheckBox.class, ids));
add(makeBPanel(JRadioButton.class, ids));
}
public staticvoidmain(String args[]){
Show.inFrame(new ButtonGroups(), 500,300);
}
} /// :~
边框标题由类名剔除了所有的路径信息而来。AbstractButton 初始化为一个JButton,JButtonr 的标签发生“失效”,因此如果我们忽略这个异常信息,我们会在屏幕上一直看到这个问题。getConstructor()方法产生了一个通过getConstructor()方法安放自变量数组类型到类数组的构建器对象,然后所有我们要做的就是调用newInstance(),通过它一个数组对象包含我们当前的自变量——在这种例子中,就是ids数组中的字符串。
这样增加了一些更复杂的内容到这个简单的程序中。为了使“异或”行为拥有按钮,我们创建一个按钮组并增加每个按钮到我们所需的组中。当我们运行这个程序时,我们会注意到所有的按钮除了JButton 都会向我们展示“异或”行为。
我们可在一个JLable 或从AbstractButton 处继承的任何事物中使用一个图标(包括JButton,JCheckbox,JradioButton及不同类型的JMenuItem)。利用JLables 的图标十分的简单容易(我们会在随后的一个程序例子中看到)。下面的程序例子探索了我们可以利用按钮的图标和它们的衍生物的其它所有方法。
我们可以使用任何我们需要的GIF 文件,但在这个例子中使用的这个GIF 文件是这本书编码发行的一部分。为了打开一个文件和随之带来的图像,简单地创建一个图标并分配它文件名。从那时起,我们可以在程序中使用这个产生的图标。
import java.awt.*;
importjava.awt.event.*;
importjavax.swing.*;
public class 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");
boolean mad = false;
publicFaces() {
jb.addActionListener(newActionListener() {
public voidactionPerformed(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() {
public voidactionPerformed(ActionEvent e) {
if (jb.isEnabled()){
jb.setEnabled(false);
jb2.setText("Enable");
} else {
jb.setEnabled(true);
jb2.setText("Disable");
}
}
});
add(jb2);
}
public static voidmain(String args[]) {
Show.inFrame(newFaces(), 300, 200);
}
} ///:~
一个图标可以在许多的构建器中使用,但我们可以使用setIcon()方法增加或更换图标。这个例子同样展示了当事件发生在JButton(或者一些AbstractButton)上时,为什么它可以设置各种各样的显示图标:当JButton被按下时,当它被失效时,或者“滚过”时(鼠标从它上面移动过但并不击它)。我们会注意到那给了按钮一种动画的感觉。
注意工具提示条也同样增加到按钮中。
菜单在Swing 中做了重要的改进并且更加的灵活——例如,我们可以在几乎程序中任何地方使用他们,包括在面板和程序片中。语法同它们在老的AWT 中是一样的,并且这样使出现在老AWT 的在新的Swing 也出现了:我们必须为我们的菜单艰难地编写代码,并且有一些不再作为资源支持菜单(其它事件中的一些将使它们更易转换成其它的编程语言)。另外,菜单代码相当的冗长,有时还有一些混乱。下面的方法是放置所有的关于每个菜单的信息到对象的二维数组里(这种方法可以放置我们想处理的任何事物到数组里),这种方法在解决这个问题方面领先了一步。这个二维数组被菜单所创建,因此它首先表示出菜单名,并在剩余的列中表示菜单项和它们的特性。我们会注意到数组列不必保持一致——只要我们的代码知道将发生的一切事件,每一列都可以完全不同。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Menus extends JPanel {
static finalBoolean bT= newBoolean(true),bF= newBoolean(false);
// Dummy classto create type identifiers:
static classMType {
MType(int i) {
}
};
static finalMType mi= newMType(1), // Normal menu item
cb = new MType(2), // Checkbox menu item
rb = new MType(3); // Radio button menu item
JTextField t = new JTextField(10);
JLabel l = new JLabel("Icon Selected", Faces.faces[0], JLabel.CENTER);
ActionListener a1 = new ActionListener() {
public void actionPerformed(ActionEvent e) {
t.setText(((JMenuItem) e.getSource()).getText());
}
};
ActionListener a2 = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuItem mi = (JMenuItem) e.getSource();
l.setText(mi.getText());
l.setIcon(mi.getIcon());
}
};
// Store menudata as "resources":
public Object[][] fileMenu= {
// Menu name and accelerator:
{ "File", new Character(‘F‘) },
// Name type accel listener enabled
{ "New", mi, new Character(‘N‘), a1, bT }, { "Open",mi,newCharacter(‘O‘),a1,bT},
{ "Save", mi, new Character(‘S‘), a1, bF }, { "Save As",mi,newCharacter(‘A‘),a1,bF}, { null}, // Separator
{ "Exit", mi, new Character(‘x‘), a1, bT }, };
public Object[][] editMenu= {
// Menu name:
{ "Edit", new Character(‘E‘) },
// Name type accel listener enabled
{ "Cut", mi, new Character(‘t‘), a1, bT }, { "Copy",mi,newCharacter(‘C‘),a1,bT},
{ "Paste", mi, new Character(‘P‘), a1, bT }, { null }, // Separator
{ "Select All", mi, new Character(‘l‘), a1, bT }, };
public Object[][] helpMenu= {
// Menu name:
{ "Help", new Character(‘H‘) },
// Name type accel listener enabled
{ "Index", mi, new Character(‘I‘), a1, bT }, { "Using help",mi,newCharacter(‘U‘),a1,bT}, { null}, // Separator
{ "About", mi, new Character(‘t‘), a1, bT }, };
public Object[][] optionMenu = {
// Menu name:
{ "Options", new Character(‘O‘) },
// Name type accel listener enabled
{ "Option 1", cb, new Character(‘1‘), a1, bT }, { "Option 2",cb,newCharacter(‘2‘),a1,bT}, };
public Object[][] faceMenu= {
// Menu name:
{ "Faces", new Character(‘a‘) },
// Optinal last element is icon
{ "Face 0", rb, new Character(‘0‘), a2, bT, Faces.faces[0] },
{ "Face 1", rb, new Character(‘1‘), a2, bT, Faces.faces[1] },
{ "Face 2", rb, new Character(‘2‘), a2, bT, Faces.faces[2] },
{ "Face 3", rb, new Character(‘3‘), a2, bT, Faces.faces[3] },
{ "Face 4", rb, new Character(‘4‘), a2, bT, Faces.faces[4] }, };
public Object[] menuBar= { fileMenu,editMenu,faceMenu,optionMenu,helpMenu,};
static publicJMenuBar createMenuBar(Object[] menuBarData) {
JMenuBar menuBar = new JMenuBar();
for (int i = 0; i < menuBarData.length; i++)
menuBar.add(createMenu((Object[][]) menuBarData[i]));
return menuBar;
}
static ButtonGroup bgroup;
static publicJMenu createMenu(Object[][] menuData) {
JMenu menu = new JMenu();
menu.setText((String) menuData[0][0]);
menu.setMnemonic(((Character) menuData[0][1]).charValue());
// Create redundantly, in case there are
// any radio buttons:
bgroup = new ButtonGroup();
for (int i = 1; i < menuData.length; i++) {
if (menuData[i][0] == null)
menu.add(new JSeparator());
else
menu.add(createMenuItem(menuData[i]));
}
return menu;
}
static publicJMenuItem createMenuItem(Object[] data) {
JMenuItem m = null;
MType type = (MType) data[1];
if (type == mi)
m = new JMenuItem();
else if (type == cb)
m = new JCheckBoxMenuItem();
else if (type == rb) {
m = new JRadioButtonMenuItem();
bgroup.add(m);
}
m.setText((String) data[0]);
m.setMnemonic(((Character) data[2]).charValue());
m.addActionListener((ActionListener) data[3]);
m.setEnabled(((Boolean) data[4]).booleanValue());
if (data.length== 6)
m.setIcon((Icon) data[5]);
return m;
}
Menus() {
setLayout(new BorderLayout());
add(createMenuBar(menuBar), BorderLayout.NORTH);
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(t, BorderLayout.NORTH);
p.add(l, BorderLayout.CENTER);
add(p, BorderLayout.CENTER);
}
public staticvoidmain(String args[]){
Show.inFrame(new Menus(), 300, 200);
}
} /// :~
这个程序的目的是允许程序设计者简单地创建表格来描述每个菜单,而不是输入代码行来建立菜单。每个菜单都产生一个菜单,表格中的第一列包含菜单名和键盘快捷键。其余的列包含每个菜单项的数据:字符串存在在菜单项中的位置,菜单的类型,它的快捷键,当菜单项被选中时被激活的动作接收器及菜单是否被激活等信息。如果列开始处是空的,它将被作为一个分隔符来处理。
为了预防浪费和冗长的多个Boolean 创建的对象和类型标志,以下的这些在类开始时就作为static final 被创建:bT 和bF 描述Booleans 和哑类MType的不同对象描述标准的菜单项(mi),复选框菜单项(cb),和单选钮菜单项(rb)。请记住一组Object 可以拥有单一的Object 句柄,并且不再是原来的值。
这个程序例子同样展示了JLables 和JMenuItems(和它们的衍生事物)如何处理图标的。一个图标经由它的构建器置放进JLable中并当对应的菜单项被选中时被改变。
菜单条数组控制处理所有在文件菜单清单中列出的,我们想显示在菜单条上的文件菜单。我们通过这个数组去使用createMenuBar(),将数组分类成单独的菜单数据数组,再通过每个单独的数组去创建菜单。这种方法依次使用菜单数据的每一行并以该数据创建JMenu,然后为菜单数据中剩下的每一行调用createMenuItem()方法。最后,createMenuItem()方法分析菜单数据的每一行并且判断菜单类型和它的属性,再适当地创建菜单项。终于,像我们在菜单构建器中看到的一样,从表示createMenuBar(menuBar)的表格中创建菜单,而所有的事物都是采用递归方法处理的。
这个程序不能建立串联的菜单,但我们拥有足够的知识,如果我们需要的话,随时都能增加多级菜单进去。
JPopupMenu 的执行看起来有一些别扭:我们必须调用enableEvents()方法并选择鼠标事件代替利用事件接收器。它可能增加一个鼠标接收器但MouseEvent 从isPopupTrigger()处不会返回真值——它不知道将激活一个弹出菜单。另外,当我们尝试接收器方法时,它的行为令人不可思议,这或许是鼠标单击活动引起的。在下面的程序例子里一些事件产生了这种弹出行为:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Popup extends JPanel {
JPopupMenu popup = new JPopupMenu();
JTextField t = new JTextField(10);
public Popup() {
add(t);
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
t.setText(((JMenuItem) e.getSource()).getText());
}
};
JMenuItem m = new JMenuItem("Hither");
m.addActionListener(al);
popup.add(m);
m = new JMenuItem("Yon");
m.addActionListener(al);
popup.add(m);
m = new JMenuItem("Afar");
m.addActionListener(al);
popup.add(m);
popup.addSeparator();
m = new JMenuItem("Stay Here");
m.addActionListener(al);
popup.add(m);
PopupListener pl = new PopupListener();
addMouseListener(pl);
t.addMouseListener(pl);
}
class PopupListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
public staticvoidmain(String args[]){
Show.inFrame(new Popup(), 200, 150);
}
} /// :~
相同的ActionListener 被加入每个JMenuItem 中,使其能从菜单标签中取出文字,并将文字插入JTextField。
列表框和组合框在Swing 中工作就像它们在老的AWT 中工作一样,但如果我们需要它,它们同样被增加功能。另外,它也更加的方便易用。例如,JList 中有一个显示String 数组的构建器(奇怪的是同样的功能在JComboBox 中无效!)。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ListCombo extendsJPanel {
publicListCombo() {
setLayout(newGridLayout(2, 1));
JListlist = new JList(ButtonGroups.ids);
add(newJScrollPane(list));
JComboBoxcombo = new JComboBox();
for(int i = 0; i < 100; i++)
combo.addItem(Integer.toString(i));
add(combo);
}
publicstatic void main(String args[]) {
Show.inFrame(newListCombo(), 200, 200);
}
} /// :~
最开始的时候,似乎有点儿古怪的一种情况是JLists 居然不能自动提供滚动特性——即使那也许正是我们一直所期望的。增加对滚动的支持变得十分容易,就像上面示范的一样——简单地将JList 封装到JScrollPane 即可,所有的细节都自动地为我们照料到了。
滑杆用户能用一个滑块的来回移动来输入数据,在很多情况下显得很直观(如声音控制)。进程条从“空”到“满”显示相关数据的状态,因此用户得到了一个状态的透视。我最喜爱的有关这的程序例子简单地将滑动块同进程条挂接起来,所以当我们移动滑动块时,进程条也相应的改变:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
public class Progress extendsJPanel {
JProgressBarpb = new JProgressBar();
JSlidersb = new JSlider(JSlider.HORIZONTAL, 0, 100, 60);
publicProgress() {
setLayout(newGridLayout(2, 1));
add(pb);
sb.setValue(0);
sb.setPaintTicks(true);
sb.setMajorTickSpacing(20);
sb.setMinorTickSpacing(5);
sb.setBorder(newTitledBorder("Slide Me"));
pb.setModel(sb.getModel());// Share model
add(sb);
}
publicstatic void main(String args[]) {
Show.inFrame(newProgress(), 200, 150);
}
} /// :~
JProgressBar 十分简单,但JSlider 却有许多选项,例如方法、大或小的记号标签。注意增加一个带标题的边框是多么的容易。
使用一个JTree 可以简单地像下面这样表示:
add(new JTree(
new Object[] {"this","that", "other"}));
这个程序显示了一个原始的树状物。树状物的API 是非常巨大的,可是——当然是在Swing 中的巨大。它表明我们可以做有关树状物的任何事,但更复杂的任务可能需要不少的研究和试验。幸运的是,在库中提供了一个妥协:“默认的”树状物组件,通常那是我们所需要的。因此大多数的时间我们可以利用这些组件,并且只在特殊的情况下我们需要更深入的研究和理解。
下面的例子使用了“默认”的树状物组件在一个程序片中显示一个树状物。当我们按下按钮时,一个新的子树就被增加到当前选中的结点下(如果没有结点被选中,就用根结节):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!希望你也加入到我们人工智能的队伍中来!https://www.cnblogs.com/captainbed
标签:released bool 特征 tla open 字符 field 那是 lpm
原文地址:https://www.cnblogs.com/swncz/p/10148409.html