Java编程思想第4版[中文版](PDF格式)-第125部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
add(sb);
}
public static void main(String args'') {
Show。inFrame(new Progress();200;150);
}
} ///:~
JProgressBar 十分简单,但 JSlider 却有许多选项,例如方法、大或小的记号标签。注意增加一个带标题的
边框是多么的容易。
13。19。13 树
使用一个JTree 可以简单地像下面这样表示:
add(new JTree(
new Object'' {〃this〃; 〃that〃; 〃other〃}));
这个程序显示了一个原始的树状物。树状物的 API 是非常巨大的,可是——当然是在Swing 中的巨大。它表
明我们可以做有关树状物的任何事,但更复杂的任务可能需要不少的研究和试验。幸运的是,在库中提供了
一个妥协:“默认的”树状物组件,通常那是我们所需要的。因此大多数的时间我们可以利用这些组件,并
且只在特殊的情况下我们需要更深入的研究和理解。
下面的例子使用了“默认”的树状物组件在一个程序片中显示一个树状物。当我们按下按钮时,一个新的子
树就被增加到当前选中的结点下(如果没有结点被选中,就用根结节):
//: Trees。java
// Simple Swing tree example。 Trees can be made
// vastly more plex than this。
package c13。swing;
import java。awt。*;
import java。awt。event。*;
import javax。swing。*;
import javax。swing。tree。*;
// Takes an array of Strings and makes the first
// element a node and the rest leaves:
class Branch {
DefaultMutableTreeNode r;
public Branch(String'' data) {
r = new DefaultMutableTreeNode(data'0');
for(int i = 1; i 《 data。length; i++)
r。add(new DefaultMutableTreeNode(data'i'));
}
public DefaultMutableTreeNode node() {
return r;
}
}
public class Trees extends JPanel {
480
…………………………………………………………Page 482……………………………………………………………
String'''' data = {
{ 〃Colors〃; 〃Red〃; 〃Blue〃; 〃Green〃 };
{ 〃Flavors〃; 〃Tart〃; 〃Sweet〃; 〃Bland〃 };
{ 〃Length〃; 〃Short〃; 〃Medium〃; 〃Long〃 };
{ 〃Volume〃; 〃High〃; 〃Medium〃; 〃Low〃 };
{ 〃Temperature〃; 〃High〃; 〃Medium〃; 〃Low〃 };
{ 〃Intensity〃; 〃High〃; 〃Medium〃; 〃Low〃 };
};
static int i = 0;
DefaultMutableTreeNode root; child; chosen;
JTree tree;
DefaultTreeModel model;
public Trees() {
setLayout(new BorderLayout());
root = new DefaultMutableTreeNode(〃root〃);
tree = new JTree(root);
// Add it and make it take care of scrolling:
add(new JScrollPane(tree);
BorderLayout。CENTER);
// Capture the tree's model:
model =(DefaultTreeModel)tree。getModel();
JButton test = new JButton(〃Press me〃);
test。addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
if(i 《 data。length) {
child = new Branch(data'i++')。node();
// What's the last one you clicked?
chosen = (DefaultMutableTreeNode)
tree。getLastSelectedPathponent();
if(chosen == null) chosen = root;
// The model will create the
// appropriate event。 In response; the
// tree will update itself:
model。insertNodeInto(child; chosen; 0);
// This puts the new node on the
// currently chosen node。
}
}
});
// Change the button's colors:
test。setBackground(Color。blue);
test。setForeground(Color。white);
JPanel p = new JPanel();
p。add(test);
add(p; BorderLayout。SOUTH);
}
public static void main(String args'') {
Show。inFrame(new Trees();200;500);
}
} ///:~
最重要的类就是分支,它是一个工具,用来获取一个字符串数组并为第一个字符串建立一个
481
…………………………………………………………Page 483……………………………………………………………
DefaultMutableTreeNode 作为根,其余在数组中的字符串作为叶。然后 node()方法被调用以产生“分支”的
根。树状物类包括一个来自被制造的分支的二维字符串数组,以及用来统计数组的一个静态中断 i。
DefaultMutableTreeNode 对象控制这个结节,但在屏幕上表示的是被JTree 和它的相关
(DefaultTreeModel)模式所控制。注意当JTree 被增加到程序片时,它被封装到JScrollPane 中——这就
是它全部提供的自动滚动。
JTree 通过它自己的模型来控制。当我们修改这个模型时,模型产生一个事件,导致JTree 对可以看见的树
状物完成任何必要的升级。在 init()中,模型由调用getModel()方法所捕捉。当按钮被按下时,一个新的分
支被创建了。然后,当前选择的组件被找到(如果没有选择就是根)并且模型的 insertNodeInto()方法做所
有的改变树状物和导致它升级的工作。
大多数的时候,就像上面的例子一样,程序将给我们在树状物中所需要的一切。不过,树状物拥有力量去做
我们能够想像到的任何事——在上面的例子中我们到处都可看到“default (默认)”字样,我们可以取代我
们自己的类来获取不同的动作。但请注意:几乎所有这些类都有一个具大的接口,因此我们可以花一些时间
努力去理解这些错综复杂的树状物。
13。19。14 表格
和树状物一样,表格在 Swing 相当的庞大和强大。它们最初有意被设计成以 Java 数据库连结(JDBC,在15
章有介绍)为媒介的“网格”数据库接口,并且因此它们拥有的巨大的灵活性,使我们不再感到复杂。无
疑,这是足以成为成熟的电子数据表的基础条件而且可能为整本书提供很好的根据。但是,如果我们理解这
个的基础条件,它同样可能创建相关的简单的 Jtable。
JTable 控制数据的显示方式,但 TableModel 控制它自己的数据。因此在我们创建JTable 前,应先创建一个
TableModel。我们可以全部地执行 TableModel 接口,但它通常从 helper 类的AbstractTableModel 处简单地
继承:
//: Table。java
// Simple demonstration of JTable
package c13。swing;
import java。awt。*;
import java。awt。event。*;
import javax。swing。*;
import javax。swing。table。*;
import javax。swing。event。*;
// The TableModel controls all the data:
class DataModel extends AbstractTableModel {
Object'''' data = {
{〃one〃; 〃two〃; 〃three〃; 〃four〃};
{〃five〃; 〃six〃; 〃seven〃; 〃eight〃};
{〃nine〃; 〃ten〃; 〃eleven〃; 〃twelve〃};
};
// Prints data when table changes:
class TML implements TableModelListener {
public void tableChanged(TableModelEvent e) {
for(int i = 0; i 《 data。length; i++) {
for(int j = 0; j 《 data'0'。length; j++)
System。out。print(data'i''j' + 〃 〃);
System。out。println();
}
}
}
DataModel() {
addTableModelListener(new TML());
}
482
…………………………………………………………Page 484……………………………………………………………
public int getColumnCount() {
return data'0'。length;
}
public int getRowCount() {
return data。length;
}
public Object getValueAt(int row; int col) {
return data'row''col';
}
public void
setValueAt(Object val; int row; int col) {
data'row''col' = val;
// Indicate the change has happened:
fireTableDataChanged();
}
public boolean
isCellEditable(int row; int col) {
return true;
}
};
public class Table extends JPanel {
public Table() {
setLayout(new BorderLayout());
JTable table = new JTable(new DataModel());
JScrollPane scrollpane =
JTable。createScrollPaneForTable(table);
add(scrol lpane; BorderLayout。CENTER);
}
public static void main(String args'') {
Show。inFrame(new Table();200;200);
}
} ///:~
DateModel 包括一组数据,但我们同样能从其它的地方得到数据,例如从数据库中。构建器增加了一个
TableModelListener 用来在每次表格被改变后打印数组。剩下的方法都遵循Bean 的命名规则,并且当
JTable 需要在 DateModel 中显示信息时调用。AbstractTableModel 提供了默认的 setValueAt()和
isCellEditable()方法以防止修改这些数据,因此如果我们想修改这些数据,就必须过载这些方法。
一旦我们拥有一个TableModel,我们只需要将它分配给JTable构建器即可。所有有关显示,编辑和更新的
详细资料将为我们处理。注意这个程序例子同样将 JTable 放置在 JScrollPane 中,这是因为JScrollPane 需
要一个特殊的JTable 方法。
13。19。15 卡片式对话框
在本章的前部,向我们介绍了老式的CardLayout,并且注意到我们怎样去管理我们所有的卡片开关。有趣的
是,有人现在认为这是一种不错的设计。幸运的是,Swing 用 JTabbedPane 对它进行了修补,由JTabbedPane
来处理这些卡片,开关和其它的任何事物。对比CardLayout 和JTabbedPane,我们会发现惊人的差异。
下面的程序例子十分的有趣,因为它利用了前面例子的设计。它们都是做为JPanel 的衍生物来构建的,因此
这个程序将安放前面的每个例子到它自己在JTabbedPane 的窗格中。我们会看到利用RTTI 制造的程序十分的
小巧精致:
//: Tabbed。java
// Using tabbed panes
483
…………………………………………………………Page 485……………………………………………………………
package c13。swing;
import java。awt。*;
import javax。swing。*;
import javax。swing。border。*;
public class Tabbed extends JPanel {
static Object'''' q = {
{ 〃Felix〃; Borders。class };
{ 〃The Professor〃; Buttons。class };
{ 〃Rock Bottom〃; ButtonGroups。class };
{ 〃Theodore〃; Faces。class };
{ 〃Simon〃; Menus。class };
{ 〃Alvin〃; Popup。class };
{ 〃Tom〃; Listbo。class };
{ 〃Jerry〃; Progress。class };
{ 〃Bugs〃; Trees。class };
{ 〃Daffy〃; Table。class };
};
static JPanel makePanel(Class c) {
String title = c。getName();
title = title。substring(
title。lastIndexOf('。') + 1);
JPanel sp = null;
try {
sp = (JPanel)c。newInstance();
} catch(Exception e) {
System。out。println(e);
}
sp。setBorder(new TitledBorder(title));
return sp;
}
public Tabbed() {
setLayout(new BorderLayout());
JTabbedPane tabbed = new JTabbedPane();
for(int i = 0; i 《 q。length; i++)
tabbed。addTab((String)q'i''0';
makePanel((