使用的教材是java核心技术卷1,我将跟着这本书的章节同时配合视频资源来进行学习基础java知识。
现在终于可以开始介绍Swing用户界面组件了o首先,介绍具有用户输入和编辑文本功能的组件。文本域(JTextField)和文本区(JTextArea)组件用于获取文本输人。文本域只能接收单行文本的输人,而文本区能够接收多行文本的输人。JPassword也只能接收单行文本的输人,但不会将输入的内容显示出来。
这三个类都继承于JTextComponent类。由于JTextComponent是一个抽象类,所以不能够构造这个类的对象。另外,在Java中常会看到这种情况。在査看API文档时,发现自己正在寻找的方法实际上来自父类JTextComponent,而不是来自派生类自身。例如,在一个文本域和文本区内获取(get)、设置(set)文本的方法实际上都是JTextComponent类中的方法。
把文本域添加到窗口的常用办法是将它添加到面板或者其他容器中,这与添加按钮完全一样:
JPanel panel= new JPanel();
JTextField textField =new JTextField("Default input", 20);
panel.add(textField);
这段代码将添加一个文本域,同时通过传递字符串“Defaultinput”进行初始化。构造器的第二个参数设置了文本域的宽度。在这个示例中,宽度值为20“列”。但是,这里所说的列不是一个精确的测量单位。一列就是在当前使用的字体下一个字符的宽度。如果希望文本域最多能够输人n个字符,就应该把宽度设置为n列。在实际中,这样做效果并不理想,应该将最大输人长度再多设1~2个字符。列数只是给AWT设定首选(preferred)大小的一个提示。如果布局管理器需要缩放这个文本域,它会调整文本域的大小。在JTextField的构造器中设定的宽度并不是用户能输人的字符个数的上限。用户可以输入一个更长的字符串,但是当文本长度超过文本域长度时输人就会滚动。用户通常不喜欢滚动文本域,因此应该尽量把文本域设置的宽一些。如果需要在运行时重新设置列数,可以使用setColumns方法。
通常情况下,希望用户在文本域中键入文本(或者编辑已经存在的文本)。文本域一般初始为空白。只要不为JTextField构造器提供字符串参数,就可以构造一个空白文本域:
JTextField textField =new JTextField(20);
可以在任何时候调用setText方法改变文本域中的内容。这个方法是从前面提到的JTextComponent中继承而来的。例如:
textField.setTextH("Hello!");
并且,在前面已经提到,可以调用 getText方法来获取用户键人的文本。这个方法返回用户输人的文本。如果想要将getText方法返回的文本域中的内容的前后空格去掉,就应该调用trim方法,如果想要改变显示文本的字体,就调用 setFont方法。
标签是容纳文本的组件,它们没有任何的修饰(例如没有边缘),也不能响应用户输入。可以利用标签标识组件。例如:与按钮不同,文本域没有标识它们的标签要想用标识符标识这种不带标签的组件,应该
1)用相应的文本构造一个JLabel组件。
2)将标签组件放置在距离需要标识的组件足够近的地方,以便用户可以知道标签所标识的组件。
JLabel的构造器允许指定初始文本和图标,也可以选择内容的排列方式。可以用SwingConstants接口中的常量来指定排列方式。在这个接口中定义了几个很有用的常量,如LEFT、RIGHT、CENTER、NORTH、EAST等。JLabel是实现这个接口的一个Swing类。因此,可以指定右对齐标签:
JLabel label=new JLabel("Username:",SwingConstants.RIGHT);
或者
JLabel label=new JLabel("Username:",3Label.RIGHT);
利用setText和setlcon方法可以在运行期间设置标签的文本和图标。与其他组件一样,标签也可以放置在容器中。这就是说,可以利用前面介绍的技巧将标签放置在任何需要的地方。
密码域是一种特殊类型的文本域。为了避免有不良企图的人看到密码,用户输入的字符不显示出来。每个输人的字符都用回显字符(echocharacter)表示,典型的回显字符是星号(*)。Swing提供了JPasswordField类来实现这样的文本域。密码域是另一个应用模型-视图-控制器体系模式的例子。密码域采用与常规的文本域相同的模型来存储数据,但是,它的视图却改为显示回显字符,而不是实际的字符。
有时,用户的输人超过一行。正像前面提到的,需要使用JTextArea组件来接收这样的输入。当在程序中放置一个文本区组件时,用户就可以输人多行文本,并用ENTER键换行。每行都以一个“\n”结尾。如图显示了一个工作的文本区。
在JTextArea组件的构造器中,可以指定文本区的行数和列数。例如:
textArea=new JTextArea(8,40);//8 lines of 40 columns each
与文本域一样。出于稳妥的考虑,参数columns应该设置得大一些。另外,用户并不受限于输人指定的行数和列数。当输人过长时,文本会滚动。还可以用setColumns方法改变列数,用setRows方法改变行数。这些数值只是首选大小一布局管理器可能会对文本区进行缩放。如果文本区的文本超出显示的范围,那么剩下的文本就会被剪裁掉。可以通过开启换行特性来避免裁剪过长的行:
textArea.setLineWrap(true)://long lines are wrapped
换行只是视觉效果;文档中的文本没有改变,在文本中并没有插入“\n”字符。
在Swing中,文本区没有滚动条。如果需要滚动条,可以将文本区插人到滚动窗格(scrollpane)中。
textArea = new JTextArea( 8, 40 ) ;
JScrollPane scrollPane = new JScratlPane( textArea ) ;
现在滚动窗格管理文本区的视图。如果文本超出了文本区可以显示的范围,滚动条就会自动地出现,并且在删除部分文本后,当文本能够显示在文本区范围内时,滚动条会再次自动地消失。滚动是由滚动窗格内部处理的,编写程序时无需处理滚动事件。
这是一种为任意组件添加滚动功能的通用机制,而不是文本区特有的。也就是说,要想为组件添加滚动条,只需将它们放人一个滚动窗格中即可。
下面的程序展示了各种文本组件。这个程序只是简单地显示了一个文本域、一个密码域和一个带滚动条的文本区。文本域和密码域都使用了标签。点击“Insert”会将组件中的内容插入到文本区中。
/**
*@author zzehao
*/
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;
public class MenuFrame extends JFrame
{
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
private Action saveAction;
private Action saveAsAction;
private JCheckBoxMenuItem readonlyItem;
private JPopupMenu popup;
//动作
class TestAction extends AbstractAction
{
public TestAction( String name )
{
super( name );
}
@Override
public void actionPerformed(ActionEvent e)
{
System.out.println( getValue( Action.NAME ) + " selected." );
}
}
public MenuFrame()
{
setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
//File是一级菜单
JMenu fileMenu = new JMenu("File");
//File下面的二级菜单有:New, Open, Save, Save As, Exit
fileMenu.add(new TestAction("New"));
//给Open菜单项添加快捷键
JMenuItem openItem = fileMenu.add(new TestAction("Open"));
openItem.setAccelerator(KeyStroke.getKeyStroke("ctrl 0"));
//将一个分隔符行添加到File菜单中
fileMenu.addSeparator();
//给Save菜单项添加快捷键
saveAction = new TestAction("Save");
JMenuItem saveItem = fileMenu.add(saveAction);
saveItem.setAccelerator(KeyStroke.getKeyStroke("ctrl S"));
//添加Save As菜单项
saveAsAction = new TestAction("Save As");
fileMenu.add(saveAsAction);
fileMenu.addSeparator();
//添加Exit菜单项
fileMenu.add(new AbstractAction("Exit") {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
//==============================================
//readonlyItem是复选框菜单项
readonlyItem = new JCheckBoxMenuItem( "Read-only" );
readonlyItem.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
//表示勾选了Read-only复选框,就不能点击Save或者Save As菜单项了
boolean saveOk = !readonlyItem.isSelected();
saveAction.setEnabled(saveOk);
saveAsAction.setEnabled(saveOk);
}
});
//group是单选按钮组;其中有Insert和Overtype两个单选按钮,即选了其中一个,另一个就会失选; 设定insert初始被选中
ButtonGroup group = new ButtonGroup();
JRadioButtonMenuItem isertItem = new JRadioButtonMenuItem("Insert");
isertItem.setSelected(true);
JRadioButtonMenuItem overtypeItem = new JRadioButtonMenuItem("Overtype");
group.add(isertItem);
group.add(overtypeItem);
//Edit是一级菜单项,下面包括了Cut, Copy, Paste, Options 4个二级菜单项
//Options是二级菜单项,下面又包括readonlyItem,isertItem,overtypeItem3个三级菜单项
Action cutAction = new TestAction("Cut");
cutAction.putValue(Action.SMALL_ICON, new ImageIcon("cut.gif"));
Action copyAction = new TestAction("Copy");
copyAction.putValue(Action.SMALL_ICON, new ImageIcon("copy.gif"));
Action pasteAction = new TestAction("Paste");
pasteAction.putValue(Action.SMALL_ICON, new ImageIcon("paste.gif"));
JMenu editMenu = new JMenu("Edit");
editMenu.add(cutAction);
editMenu.add(copyAction);
editMenu.add(pasteAction);
JMenu optionMenu = new JMenu("Options");
optionMenu.add(readonlyItem);
optionMenu.addSeparator();;
optionMenu.add(isertItem);
optionMenu.add(overtypeItem);
editMenu.addSeparator();
editMenu.add(optionMenu);
//=============================================
//Help是一级菜单项,下面有Index, About两个二级菜单项
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic('H');//给H字母添加快捷键;可以ALT+H唤醒Help菜单
JMenuItem indexItem = new JMenuItem("Index");
indexItem.setMnemonic('I');
helpMenu.add(indexItem);
Action aboutAction = new TestAction("About");
//给字母A添加快捷键,即直接按A就能唤醒About菜单项;前提是Help已经唤醒
aboutAction.putValue(Action.MNEMONIC_KEY, new Integer('A'));
helpMenu.add(aboutAction);
//菜单栏,将所有一级菜单项放入其中
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(helpMenu);
//弹出菜单;/点击鼠标右键,弹出菜单
popup = new JPopupMenu();
popup.add(cutAction);
popup.add(copyAction);
popup.add(pasteAction);
JPanel panel = new JPanel();
//点击鼠标右键,弹出菜单
panel.setComponentPopupMenu(popup);
add(panel);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new MenuFrame();//初始化窗口
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置:关闭窗口,则程序退出
frame.setVisible(true);//显示窗口
}
});
}
}
运行的结果是: