四. 文本输入框、密码输入框
文本输入框包括两种,单行文本输入框 (jtextfield) 和多行文本输入框 (jtextarea)。密码输入框则只有一种 (jpasswordfield)。jpasswordfield 是 jtextfield 的子类,它们的主要区别是 jpasswordfield 不会显示出用户输入的东西,而只会显示出程序员设定的一个固定字符,比如 '*'。
下面的示例图和代码是 jtextfield、jpasswordfield 和 jtextarea 的示例:
/**
* testtexts.java
* @author fancy
*/
import javax.swing.*;
import javax.swing.event.*;
public class testtexts extends jframe {
private jlabel label = new jlabel("status");
private jtextfield textfield;
private jpasswordfield pwdfield;
private jtextarea textarea;
public testtexts() {
super("test texts");
setdefaultcloseoperation(exit_on_close);
getcontentpane().setlayout(new java.awt.flowlayout());
textfield = new jtextfield(15);
/* 监听文本光标移动事件 */
textfield.addcaretlistener(new caretlistener() {
public void caretupdate(caretevent e) {
// 如果改变了内容,就可以即时更新 label 显示的内容
label.settext(textfield.gettext());
}
});
pwdfield = new jpasswordfield(15);
pwdfield.setechochar('#');
textarea = new jtextarea(5, 15);
textarea.setlinewrap(true);
getcontentpane().add(textfield);
getcontentpane().add(pwdfield);
getcontentpane().add(textarea);
getcontentpane().add(label);
setsize(200, 200);
}
public static
void main(string[] args) {
testtexts tt = new testtexts();
tt.show();
}
}
上例中,我们构造了一个宽度为 15 个字符的单行文本框 (textfield = new jtextfield(15);),并使用 addcaretlistener 方法添加了一个 caretlistener (textfield.addcaretlistener ...)。caretlistener 监听文本光标的移动事件。当用户使用键盘、鼠标等移动了文本光标在 jtextfield 中的位置时触发这个事件。我们需要重载 caretupdate(caretevent e) 对事件进行处理 (public void caretupdate(caretevent e) ...)。这样,我们可以在这里做类似 vb 中 textbox 的 onchange 事件中做的事情。
jtextfield 有 5 个构造方法,常用其中的四个:
jtextfield()
jtextfield(int columns),如上例 textfield = new jtextfield(15);
jtextfield(string text)
jtextfield(string text, int columns)
其中,参数 text 是单行文本框的初始内容,而 columns 指定了单行文本框的宽度,以字符为单位。jtextfield 中的文本内容可以用 gettext() 方法获得。也可以用 settext 方法指定 jtextfield 中的文本内容。
jpasswordfield 是 jtextfield 的子类,其构造方法也是类似的。jpasswordfield 提供了 setechochar(char ch) 方法设置为了隐藏密码而显示的字符,默认为 '*' 字符,上例中则设置为了 '#' 字符 (pwdfield.setechochar('#');)。与 jtextfield 一样,jpasswordfield 也用 gettext 方法和 settext 获得或者设置文本内容 (当然在用户界面上是隐藏的)。
jtextfield 是单行文本框,不能显示多行文本,如果想要显示多行文本,就只好使用多行文本框 jtextarea 了。jtextarea 有六个构造方法,常用的也是四个:
jtextarea()
jtextarea(int rows, int columns)
jtextarea(string text)
jtextarea(string text, int rows, int columns)
text 为 jtextarea 的初始化文本内容;rows 为 jtextarea 的高度,以行为单位;columns 为 jtextarea 的宽度,以字符为单位。如上例中就构造了一个高 5 行,宽 15 个字符的多行文本框 (textarea = new jtextarea(5, 15);)。
多行文本框默认是不会自动折行的 (不过可以输入回车符换行),我们可以使用 jtextarea 的 setlinewrap 方法设置是否允许自动折行。setlinewrap(true) 是允许自动折行,setlinewrap(false) 则是不允许自动折行。多行文本框会根据用户输入的内容自动扩展大小,不信,自己做个实验――如果不自动折行,那么多行文本框的宽度由最长的一行文字确定的;如果行数据超过了预设的行数,则多行文本框会扩展自身的高度去适应。换句话说,多行文本框不会自动产生滚动条。怎么办?后面讲到滚动窗格 (jscrollpane) 的时候,你就知道了。
多行文本框里文本内容的获得和设置,同样可以使用 gettext 和 settext 两个方法来完成。
五. 窗格、滚动窗格和布局管理
窗格 (jpanel) 和滚动窗格 (jscrollpane) 在图形用户界面设计中大量用于各种组件在窗口上的布置和安排。这里所谓的布置和安排,就是布局 (layout),因此不得不先说说布局。
将加入到容器(通常为窗口等) 的组件按照一定的顺序和规则放置,使之看起来更美观,这就是布局。布局由布局管理器 (layout manager) 来管理。那么,我们在什么时候应该使用布局管理器?应用选择哪种布局管理器?又该怎样使用布局管理器呢?
往往,我们设计一个窗口,其中是要添加若干组件的。为了管理好这些管理的布局,我们就要使用布局管理器。比如说,设计一个简单的编辑器,这个编辑器中只需要放置两个按钮和一个多行文本框。这些组件是让 java 自己任意安排呢?还是按照一定的位置关系较规范的安排呢?当然应该选择后者。那么,为了按照一定的位置关系安排这些组件,我们就需要用到布局管理器了。
然后我们遇到了一个选择题――使用哪种布局管理器。为此,我们首先要知道有些什么布局管理器,它们的布局特点是什么。常用的布局管理器有: flowlayout、borderlayout、gridlayout、boxlayout 等,其中 flowlayout 和 borderlayout 最常用,本文主要也就只谈谈这两种布局管理器。下面列表说明它们的布局特点:
就上述的编辑器为例,如果选用 flowlayout,那么两个按钮和一个多行文本框就会排列在一行――当然这是窗口足够宽的情况;如果窗口稍窄一些,则可能分两行排列,第一行有两个按钮,而第二行是多行文本框――这是最理想的情况;如果窗口再窄一些,就可能分三行排列,第一行和第二行分别放置一个按钮,第三行放置多行文本框。因此,如果窗口大小可以改变,那么三个组件的位置关系也可能随着窗口大小的变化而变化。所以,flowlayout 不适用。其实上面所举的例程中,大部分都是用的 flowlayout,那是因为我们没有要求组件的布局。
如果选用 borderlayout 的情况又如何呢?我们可以试着加入一个窗格 (jpanel,稍后讲解),并将两个按钮放置在其中,然后将这个窗格加入到 borderlayout 的北部 (即上部);再将多行文本框加入到 borderlayout 中部。结果类似使用 flowlayout 的第二种可能,是最理想的情况。而且,如果改变窗口大小,它们的位置关系仍然是北-中的关系,不会随之改变。
剩下的两种布局管理器,加以窗格 (jpanel) 的配合,也能够很好的安排上述编辑器所需的三个组件。但是由于它们的使用稍为复杂一些,所以就不讲了。下面就讲讲如何使用 flowlayout 和 borderlayout。
任何布局管理器,都需要用在容器上,比如 jframe 的 content pane 和下面要说的 jpanel 都是容器。容器组件提供了一个 setlayout 方法,就是用来改变其布局管理器的。默认情况下,jframe 的 content pane 使用的是 borderlayout,而 jpanel 使用的是 flowlayout。但不管怎样,我们都可以调用它们的 setlayout 方法来改变其布局管理器。比如上述的编辑器中,我们要让窗口 (jframe 对象,假设为 frame) 使用 borderlayout,就可以使用 frame.getcontentpane().setlayout(new borderlayout()); 来改变其布局管理器为一个新的 borderlayout 对象。
然后,我们对布局管理器的直接操作就结束了,剩下的只需要往容器里添加组件。如果使用 flowlayout,我们只需要使用容器的 add(component c) 方法添加组件就行了。但是,如果使用 borderlayout 就不一样了,因为要指定是把组件添加到哪个区域啊。那我们就使用容器的 add(component c, object o) 方法添加组件,该方法的第二个参数就是指明添加到的区域用的。例如,上述编辑器中要添加一个多行文本框到 borderlayout 的中部,就可以用 frame.getcontentpane().add(new jtextarea(5, 15), borderlayout.center) 来实现。
borderlayout 的五个区域分别是用下列五个常量来描述的:
borderlayout.east 东
borderlayout.south 南
borderlayout.west 西
borderlayout.north 北
borderlayout.center 中
刚才已经提到了使用 jpanel。jpanel 作为一个容器,可以包容一些组件,然后将这个 jpanel 对象作为一个组件添加到另一个容器 (称作父容器) 中。这个功能有什么好处呢?
上面不是提到 borderlayout 的一个区域中只能添加一个组件吗?但是我们的编辑器需要添加两个按钮到它的北部,怎么办?上面的例子中,我们就是用的一个 jpanel 包容了这两个按钮,然后再将这个 jpanel 对象作为一个组件添加到设置布局管理器为 borderlayout 的 content pane 中。
上面说到各布局管理器的布局特点的时候,几乎每一种都是一个区域只能添加一个组件,那我们想添加多个组件到一个区域的时候,就要用到 jpanel 了。如果还没有明白,稍后看一段程序可能更易于理解。
闽公网安备 35060202000074号