原文: http://zetcode.com/tutorials/javaswingtutorial/basicswingcomponents/
Swing 组件是应用的基本构建块。 Swing 具有广泛的各种组件,包括按钮,复选框,滑块和列表框。
在 Swing 教程的这一部分中,我们将介绍JButton,JLabel,JTextField和JPasswordField。
JButton
JButton正在实现按钮。 如果用户单击该动作,则用于触发该动作。
显示文字和图标
JButton可以显示文本,图标或两者。
ImageIconButtonEx.java
package com.zetcode;import javax.swing.GroupLayout;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JComponent;import javax.swing.JFrame;import java.awt.EventQueue;public class ImageIconButtonEx extends JFrame {public ImageIconButtonEx() {initUI();}private void initUI() {var saveIcon = new ImageIcon("src/resources/save.png");var homeIcon = new ImageIcon("src/resources/home.png");var quitBtn = new JButton("Quit");var saveBtn = new JButton(saveIcon);var homeBtn = new JButton("Home", homeIcon);createLayout(quitBtn, saveBtn, homeBtn);setTitle("JButtons");setLocationRelativeTo(null);setDefaultCloseOperation(EXIT_ON_CLOSE);}private void createLayout(JComponent... arg) {var pane = getContentPane();var gl = new GroupLayout(pane);pane.setLayout(gl);gl.setAutoCreateContainerGaps(true);gl.setAutoCreateGaps(true);gl.setHorizontalGroup(gl.createSequentialGroup().addComponent(arg[0]).addComponent(arg[1]).addComponent(arg[2]));gl.setVerticalGroup(gl.createParallelGroup().addComponent(arg[0]).addComponent(arg[1]).addComponent(arg[2]));gl.linkSize(arg[0], arg[1], arg[2]);pack();}public static void main(String[] args) {EventQueue.invokeLater(() -> {var ex = new ImageIconButtonEx();ex.setVisible(true);});}}
该示例显示了三个按钮:一个显示文本,一个显示图标,一个同时显示文本和图标。
var saveIcon = new ImageIcon("src/main/resources/save.png");
许多组件可以用图标修饰。 为此,我们使用ImageIcon类。
var quitBtn = new JButton("Quit");
此JButton构造器将文本作为参数。
var saveBtn = new JButton(saveIcon);
在此JButton构造器中,我们传递一个图标。
JButton homeBtn = new JButton("Home", homeIcon);
此按钮显示文本和图标。
gl.linkSize(arg[0], arg[1], arg[2]);
使用GroupLayout的linkSize()方法,使按钮大小相同。

图:JButtons
带有助记符的JButton
助记符该键与外观的无鼠标修饰符(通常为 Alt)结合使用时,如果焦点位于该按钮的祖先窗口内的某个位置,它将激活该按钮。
ButtonMnemonicEx.java
package com.zetcode;import javax.swing.GroupLayout;import javax.swing.JButton;import javax.swing.JComponent;import javax.swing.JFrame;import javax.swing.JOptionPane;import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent;public class ButtonMnemonicEx extends JFrame implements ActionListener {public ButtonMnemonicEx() {initUI();}private void initUI() {var showBtn = new JButton("Show");showBtn.addActionListener(this);showBtn.setMnemonic(KeyEvent.VK_S);createLayout(showBtn);setTitle("JButton");setLocationRelativeTo(null);setDefaultCloseOperation(EXIT_ON_CLOSE);}private void createLayout(JComponent... arg) {var pane = getContentPane();var gl = new GroupLayout(pane);pane.setLayout(gl);gl.setAutoCreateContainerGaps(true);gl.setAutoCreateGaps(true);gl.setHorizontalGroup(gl.createSequentialGroup().addComponent(arg[0]).addGap(250));gl.setVerticalGroup(gl.createParallelGroup().addComponent(arg[0]).addGap(150));pack();}@Overridepublic void actionPerformed(ActionEvent e) {JOptionPane.showMessageDialog(this, "Button clicked","Information", JOptionPane.INFORMATION_MESSAGE);}public static void main(String[] args) {EventQueue.invokeLater(() -> {var ex = new ButtonMnemonicEx();ex.setVisible(true);});}}
此示例中的按钮可以通过单击鼠标或 Alt + S 键盘快捷键来激活。
public class ButtonMnemonicEx extends JFrame implements ActionListener
ButtonMnemonicEx类实现ActionListener; 它必须覆盖actionPerformed()方法,在该方法中,我们将激活按钮后执行的代码放入其中。
var showBtn = new JButton("Show");showBtn.addActionListener(this);
创建一个新的JButton。 我们使用addActionListener()方法向按钮添加一个动作监听器。
showBtn.setMnemonic(KeyEvent.VK_S);
setMnemonic()设置助记键; 带下划线的"S"字符。
@Overridepublic void actionPerformed(ActionEvent e) {JOptionPane.showMessageDialog(this, "Button clicked","Information", JOptionPane.INFORMATION_MESSAGE);}
当通过单击鼠标或通过快捷方式激活按钮时,将显示带有JOptionPane.showMessageDialog()的消息对话框。
JLabel
JLabel是显示文本和/或图像的简单组件。 它不响应输入事件。
显示文字
以下示例显示文本。
LabelEx.java
package com.zetcode;import javax.swing.GroupLayout;import javax.swing.JComponent;import javax.swing.JFrame;import javax.swing.JLabel;import java.awt.Color;import java.awt.EventQueue;import java.awt.Font;public class LabelEx extends JFrame {public LabelEx() {initUI();}private void initUI() {var lyrics = "<html>It's way too late to think of<br>" +"Someone I would call now<br>" +"And neon signs got tired<br>" +"Red eye flights help the stars out<br>" +"I'm safe in a corner<br>" +"Just hours before me<br>" +"<br>" +"I'm waking with the roaches<br>" +"The world has surrendered<br>" +"I'm dating ancient ghosts<br>" +"The ones I made friends with<br>" +"The comfort of fireflies<br>" +"Long gone before daylight<br>" +"<br>" +"And if I had one wishful field tonight<br>" +"I'd ask for the sun to never rise<br>" +"If God leant his voice for me to speak<br>" +"I'd say go to bed, world<br>" +"<br>" +"I've always been too late<br>" +"To see what's before me<br>" +"And I know nothing sweeter than<br>" +"Champaign from last New Years<br>" +"Sweet music in my ears<br>" +"And a night full of no fears<br>" +"<br>" +"But if I had one wishful field tonight<br>" +"I'd ask for the sun to never rise<br>" +"If God passed a mic to me to speak<br>" +"I'd say stay in bed, world<br>" +"Sleep in peace</html>";var label = new JLabel(lyrics);label.setFont(new Font("Serif", Font.PLAIN, 14));label.setForeground(new Color(50, 50, 25));createLayout(label);setTitle("No Sleep");setLocationRelativeTo(null);setDefaultCloseOperation(EXIT_ON_CLOSE);}private void createLayout(JComponent... arg) {var pane = getContentPane();var gl = new GroupLayout(pane);pane.setLayout(gl);gl.setAutoCreateContainerGaps(true);gl.setHorizontalGroup(gl.createSequentialGroup().addComponent(arg[0]));gl.setVerticalGroup(gl.createParallelGroup().addComponent(arg[0]));pack();}public static void main(String[] args) {EventQueue.invokeLater(() -> {var ex = new LabelEx();ex.setVisible(true);});}}
在我们的示例中,我们显示了 Cardigans 的歌曲的歌词。 我们可以在JLabel组件中使用 HTML 标签。 我们使用<br>标签来分隔行。
var label = new JLabel(lyrics);label.setFont(new Font("Serif", Font.PLAIN, 14));
在这里,我们创建一个标签组件。 我们选择纯衬线字体并将其高度设置为 14px。
pack();
pack()方法将调整窗口大小,以便标签组件以其首选大小显示。

图:JLabel
显示图标
JLabel可用于显示图像。
LabelEx2.java
package com.zetcode;import javax.swing.GroupLayout;import javax.swing.ImageIcon;import javax.swing.JComponent;import javax.swing.JFrame;import javax.swing.JLabel;import java.awt.EventQueue;public class LabelEx2 extends JFrame {public LabelEx2() {initUI();}private void initUI() {var lbl1 = new JLabel(new ImageIcon("src/resources/cpu.png"));var lbl2 = new JLabel(new ImageIcon("src/resources/drive.png"));var lbl3 = new JLabel(new ImageIcon("src/resources/laptop.png"));var lbl4 = new JLabel(new ImageIcon("src/resources/player.png"));createLayout(lbl1, lbl2, lbl3, lbl4);setTitle("Icons");setLocationRelativeTo(null);setDefaultCloseOperation(EXIT_ON_CLOSE);}private void createLayout(JComponent... arg) {var pane = getContentPane();var gl = new GroupLayout(pane);pane.setLayout(gl);gl.setAutoCreateContainerGaps(true);gl.setAutoCreateGaps(true);gl.setHorizontalGroup(gl.createSequentialGroup().addComponent(arg[0]).addComponent(arg[1]).addComponent(arg[2]).addComponent(arg[3]));gl.setVerticalGroup(gl.createParallelGroup().addComponent(arg[0]).addComponent(arg[1]).addComponent(arg[2]).addComponent(arg[3]));pack();}public static void main(String[] args) {EventQueue.invokeLater(() -> {var ex = new LabelEx2();ex.setVisible(true);});}}
在示例中,我们使用JLabel组件显示四个图标。
var lbl1 = new JLabel(new ImageIcon("src/main/resources/cpu.png"));
JLabel将ImageIcon作为参数。 图标是固定大小的图像。 ImageIcon从 GIF,JPEG 或 PNG 图像绘制图标。

图:显示图标
JTextField
JTextField是一个文本组件,允许编辑一行非格式化文本。
JTextFieldEx.java
package com.zetcode;import javax.swing.GroupLayout;import javax.swing.JComponent;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JTextField;import javax.swing.event.DocumentEvent;import javax.swing.event.DocumentListener;import javax.swing.text.BadLocationException;import java.awt.EventQueue;import java.util.logging.Level;import java.util.logging.Logger;public class JTextFieldEx extends JFrame {private JLabel lbl;public JTextFieldEx() {initUI();}private void initUI() {var field = new JTextField(15);lbl = new JLabel();field.getDocument().addDocumentListener(new MyDocumentListener());createLayout(field, lbl);setTitle("JTextField");setLocationRelativeTo(null);setDefaultCloseOperation(EXIT_ON_CLOSE);}private class MyDocumentListener implements DocumentListener {private String text;@Overridepublic void insertUpdate(DocumentEvent e) {updateLabel(e);}@Overridepublic void removeUpdate(DocumentEvent e) {updateLabel(e);}@Overridepublic void changedUpdate(DocumentEvent e) {}private void updateLabel(DocumentEvent e) {var doc = e.getDocument();int len = doc.getLength();try {text = doc.getText(0, len);} catch (BadLocationException ex) {Logger.getLogger(JTextFieldEx.class.getName()).log(Level.WARNING, "Bad location", ex);}lbl.setText(text);}}private void createLayout(JComponent... arg) {var pane = getContentPane();var gl = new GroupLayout(pane);pane.setLayout(gl);gl.setAutoCreateContainerGaps(true);gl.setAutoCreateGaps(true);gl.setHorizontalGroup(gl.createParallelGroup().addComponent(arg[0]).addComponent(arg[1]).addGap(250));gl.setVerticalGroup(gl.createSequentialGroup().addComponent(arg[0], GroupLayout.DEFAULT_SIZE,GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent(arg[1]).addGap(150));pack();}public static void main(String[] args) {EventQueue.invokeLater(() -> {var ex = new JTextFieldEx();ex.setVisible(true);});}}
在示例中,输入JTextField的文本立即显示在标签组件中。
var field = new JTextField(15);
创建了新的JTextField。 该参数是列数。 请注意,此值不会设置字段中允许的字符数。 该值用于计算字段的首选宽度。
field.getDocument().addDocumentListener(new MyDocumentListener());
我们将文档监听器添加到JTextField。 getDocument()方法获取与编辑器关联的模型。 每个 Swing 组件都有一个模型,用于管理其状态或数据。
@Overridepublic void insertUpdate(DocumentEvent e) {updateLabel(e);}@Overridepublic void removeUpdate(DocumentEvent e) {updateLabel(e);}
insertUpdate()和removeUpdate()方法调用updateLabel()方法,该方法从文本字段复制文本并将其设置为标签组件。
@Overridepublic void changedUpdate(DocumentEvent e) {}
我们对changeUpdate()方法不感兴趣。 仅在样式化文档中生成此事件。
private void updateLabel(DocumentEvent e) {var doc = e.getDocument();int len = doc.getLength();try {text = doc.getText(0, len);} catch (BadLocationException ex) {Logger.getLogger(JTextFieldEx.class.getName()).log(Level.WARNING, "Bad location", ex);}lbl.setText(text);}
文档事件的getDocument()方法用于获取正在观察的文本字段的文档。 我们使用文档的getLength()方法获得字符数。 该值用于通过文档的getText()方法复制文本。 最后,使用标签的setText()方法将文本设置为标签。
gl.setVerticalGroup(gl.createSequentialGroup().addComponent(arg[0], GroupLayout.DEFAULT_SIZE,GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent(arg[1]).addGap(150));
我们不希望JTextField垂直生长; 因此,我们在垂直方向将其最大值设置为GroupLayout.PREFERRED_SIZE。

图:JTextField
JPasswordField
JPasswordField是JTextField子类,不显示用户键入的字符。
PasswordEx.java
package com.zetcode;import javax.swing.AbstractAction;import javax.swing.GroupLayout;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPasswordField;import javax.swing.JTextField;import java.awt.Component;import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.util.Arrays;import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;public class PasswordEx extends JFrame {private JTextField loginField;private JPasswordField passField;public PasswordEx() {initUI();}private void initUI() {var lbl1 = new JLabel("Login");var lbl2 = new JLabel("Password");loginField = new JTextField(15);passField = new JPasswordField(15);var submitButton = new JButton("Submit");submitButton.addActionListener(new SubmitAction());createLayout(lbl1, loginField, lbl2, passField, submitButton);setTitle("Login");setLocationRelativeTo(null);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}private class SubmitAction extends AbstractAction {@Overridepublic void actionPerformed(ActionEvent e) {doSubmitAction();}private void doSubmitAction() {var login = loginField.getText();var passwd = passField.getPassword();if (!login.isEmpty() && passwd.length != 0) {System.out.format("User %s entered %s password%n",login, String.valueOf(passwd));}Arrays.fill(passwd, '0');}}private void createLayout(Component... arg) {var pane = getContentPane();var gl = new GroupLayout(pane);pane.setLayout(gl);gl.setAutoCreateGaps(true);gl.setAutoCreateContainerGaps(true);gl.setHorizontalGroup(gl.createSequentialGroup().addGap(50).addGroup(gl.createParallelGroup().addComponent(arg[0]).addComponent(arg[1]).addComponent(arg[2]).addComponent(arg[3]).addComponent(arg[4])).addGap(50));gl.setVerticalGroup(gl.createSequentialGroup().addGap(50).addGroup(gl.createSequentialGroup().addComponent(arg[0]).addComponent(arg[1], GroupLayout.DEFAULT_SIZE,GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent(arg[2]).addComponent(arg[3], GroupLayout.DEFAULT_SIZE,GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addPreferredGap(UNRELATED).addComponent(arg[4])).addGap(50));pack();}public static void main(String[] args) {EventQueue.invokeLater(() -> {var ex = new PasswordEx();ex.setVisible(true);});}}
该示例具有一个文本字段,一个密码字段和一个按钮。 该按钮将打印用户输入的数据。
passField = new JPasswordField (15);
创建JPasswordField的实例。
var passwd = passField.getPassword();
为了安全起见,密码字段将其值存储为字符数组而不是字符串。 字符数组由getPassword()方法返回。 不推荐使用较早的getText()方法。
Arrays.fill(passwd , '0');
处理完密码后,建议将数组的元素设置为零。

图:JPasswordField
在 Java Swing 教程的这一部分中,我们介绍了基本的 Swing 组件,包括JButton,JLabel,JTextField和JPasswordField。
