14.2 Swing的常见组件
上一节会开窗口了,这一节把能摆进窗口的家伙们认全:文本家族(标签/输入框/密码框/多行框)、按钮家族(按钮/复选/单选)、选择家族(下拉/列表)——组件的用法高度统一:setText 摆内容、getText 拿内容、setEnabled 管死活。本节组件还是"死的",14.3 装上监听才活。
一、组件也讲"家族":先分类再记名
Swing 常用组件十来个,死记硬背容易乱——按长得像、干得像分三大家族,一个家族一桌:
| 家族 | 组件 | 一句话职责 |
|---|---|---|
| 文本家族 | JLabel |
标签,只显示字,不收输入 |
JTextField |
单行输入框(用户名、搜索框) | |
JPasswordField |
密码框,输啥都显示 ● |
|
JTextArea |
多行文本域(简介、留言板) | |
| 按钮家族 | JButton |
按钮,点了干活(逻辑在 14.3) |
JCheckBox |
复选框,可多选(兴趣爱好) | |
JRadioButton |
单选按钮,必须配 ButtonGroup 才互斥 | |
| 选择家族 | JComboBox |
下拉框(选省份、选年份) |
JList |
列表框,一列选项摊开给你挑 |
记法:类名前缀 J = Swing 组件(14.1 的家谱),后缀就是它的人设——PasswordField 管密码,ComboBox 是"可编辑的下拉"。
二、通用三板斧:一半的方法不用背
组件再多,高频操作就三个,几乎所有组件通用:
txtName.setText("波仔"); // 摆内容进去(输入框、标签都能用)
String name = txtName.getText(); // 拿用户输的内容(返回 String)
btnOK.setEnabled(false); // 禁用:变灰、点不动(true 恢复)
setText/getText:内容进出的正门。JLabel只能 set,输入框两样都行。setEnabled(false):把组件"灰掉"。注册协议没同意时注册按钮是灰的——就是它。
把这三个练熟,一半的组件 API 已经到手。
三、文本家族:四个框,一个红牌
JLabel lbl = new JLabel("用户名:"); // 标签:只显示
JTextField txt = new JTextField(15); // 单行:15 列宽
JPasswordField pwd = new JPasswordField(15); // 密码:显示 ●
JTextArea area = new JTextArea(4, 15); // 多行:4 行 15 列
拿密码框内容不能用 getText()(官方标记过时),要用:
char[] pw = pwd.getPassword(); // 返回字符数组,不是 String!
String s = new String(pw); // 想按字符串用,先包一层
返回值类型是 char[]——数组那章(2.7)的老朋友。为什么这么设计?字符串在内存里长期赖着不走(6.2 常量池),数组用完可以清零,密码不留痕更安全。新手记住结论即可:密码框用 getPassword(),转 new String(...)。
四、按钮家族:复选天生自由,单选必须收编
JCheckBox cbAgree = new JCheckBox("我同意协议");
JCheckBox cbEmail = new JCheckBox("订阅邮件"); // 两个复选互不干扰
JRadioButton rbMale = new JRadioButton("男");
JRadioButton rbFemale = new JRadioButton("女");
ButtonGroup group = new ButtonGroup(); // 1. 造一个"单选组"
group.add(rbMale); // 2. 把按钮收编进组
group.add(rbFemale); // 收编后才互斥!
- JCheckBox:天生自由,各勾各的,互不影响。
- JRadioButton:不收编时各自为政,能同时选中两个——必须丢进同一个
ButtonGroup才会"选了 A 自动取消 B"。
它是个"看不见的管理员":只负责让组内按钮互斥,不负责把它们摆到界面上。摆位置还是老老实实 add 进面板。忘了 add,按钮就真没了;只 add 忘了收编,两个单选能同时亮。
判断选没选:isSelected() 返回 boolean;代码代勾:setSelected(true)。
五、选择家族:JComboBox 下拉框
JComboBox<String> box = new JComboBox<>();
box.addItem("湖北省");
box.addItem("湖南省");
box.addItem("广东省");
Object item = box.getSelectedItem(); // 拿选中的项,返回 Object
String province = (String) item; // 想按 String 用,强转(4.4 的老账)
选项在运行时动态添加(addItem),取值 getSelectedItem() 返回 Object——和 9.3 反射造对象、10.5 读对象一个套路:容器不知道里面装的啥,取出来你自己认。
六、动手:Demo27 注册表单(静态版)
import javax.swing.*;
public class Demo27 {
public static void main(String[] args) {
JFrame frame = new JFrame("注册新账号");
frame.setSize(360, 280);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblName = new JLabel("用户名");
JTextField txtName = new JTextField(12);
JLabel lblPwd = new JLabel("密码");
JPasswordField pwd = new JPasswordField(12);
JCheckBox cbAgree = new JCheckBox("我同意注册协议");
JButton btnOK = new JButton("注册");
btnOK.setEnabled(false); // 协议没勾,先灰掉
JPanel panel = new JPanel(); // 面板:先把组件都装进板子
panel.add(lblName);
panel.add(txtName);
panel.add(lblPwd);
panel.add(pwd);
panel.add(cbAgree);
panel.add(btnOK);
frame.add(panel); // 板子再进窗口
frame.setVisible(true);
}
}
跑起来:窗口里整整齐齐摆着用户名、密码、协议勾选和灰色的注册按钮——虽然点注册还没反应,但"脸"已经搭完了。怎么让勾了协议按钮变亮、点了注册弹窗提示,就是 14.3 事件监听的戏。
Demo27 里组件是按 add 顺序一行流排的,想摆成"标签左、输入框右"的表格样子,要靠布局管理器(setLayout)——本节只认识这个词,具体下节展开。
七、动手实验(3 个 × 30 秒)
造两个 JRadioButton,直接 add 进面板(不进 ButtonGroup):两个能同时选中——单选按钮名不副实,收编才互斥。
把 Demo27 里 btnOK.setEnabled(false) 那行的 false 改 true 再对比:false 时按钮灰字、鼠标点上去没任何反馈。这就是"协议未同意"的标准交互。
对 JPasswordField 调 getText():编译通过但划删除线(过时 API 警告),IDEA 会提示改用 getPassword()。跟着提示走,顺手看一眼返回值类型——char[]。
八、五个常见误区
过时 API(有删除线警告),正确姿势 getPassword() 返回 char[],要字符串就 new String(pw)。
不收编 = 各选各的,两个 JRadioButton 能同时亮。group.add(rb) 一个都不能少。
它只管互斥。组件上屏永远靠 add,ButtonGroup 加不加都不影响显示。
返回 Object,要 (String) 强转——直接赋值给 String 编译都不过(4.4 的老规矩)。
检查两件事:①add 到窗口的内容面板/板子上了吗;②窗口 setVisible(true) 了吗。组件和窗口,谁没上台谁隐身。
九、自测题
文本家族:JLabel 只显示 / JTextField 单行 / JPasswordField 密码● / JTextArea 多行;按钮家族:JButton 点击干活 / JCheckBox 多选 / JRadioButton 单选;选择家族:JComboBox 下拉 / JList 列表。
setText() 摆内容、getText() 拿内容、setEnabled(false) 禁用置灰。绝大多数组件通用。
getPassword(),返回 char[] 不是 String——设计原因是密码用完可清零、不留常量池痕迹;要 String 就 new String(pw)。
没收编进 ButtonGroup 就各自为政。group.add(rb) 把它们收进同一个组,组内自动互斥;但 ButtonGroup 不管摆放,上屏仍要 add。
参考骨架:
JRadioButton rbM = new JRadioButton("男");
JRadioButton rbF = new JRadioButton("女");
ButtonGroup g = new ButtonGroup();
g.add(rbM); g.add(rbF);
JComboBox<String> box = new JComboBox<>();
box.addItem("湖北省"); box.addItem("湖南省"); box.addItem("广东省");
JTextArea area = new JTextArea(3, 12);
panel.add(rbM); panel.add(rbF); panel.add(box); panel.add(area);
自检:单选收编了吗?下拉的泛型 <String> 写了吗?按钮还是灰的吗?——界面搭完,就差让它"活"了。
十、下一步学什么
- ☑ 14.3 布局管理器 ✅ —— 点此复习:组件为什么"自己排队"、FlowLayout/BorderLayout/GridLayout 三位排版师傅、Demo28 排版版注册表单
- ☐ 14.4(按教材顺序) —— 报个标题接着走:大概率 事件监听(4.7 Lambda 老主场,让注册按钮点着有反应)。等你报标题。
相关笔记
- 第十四章 图形用户界面/14.1 Swing概述:开窗五步与套娃结构——本节的组件全都住在这个套娃里
- 第四章 面向对象(下)/4.4 多态:getSelectedItem() 返回 Object 要强转——同一个老规矩
- 第二章 Java编程基础/2.7 数组:getPassword() 返回 char[],数组老朋友
- 第六章 Java API/6.2 字符串类:new String(char[]) 转字符串;常量池解释密码为何用数组
- 第四章 面向对象(下)/4.7 函数式编程:14.3 事件监听的写法主场