原文: http://zetcode.com/tutorials/javaswingtutorial/basicswingcomponentsII/

在 Java Swing 教程的这一章中,我们将继续描述 Java Swing 组件。

Tweet

我们提到以下组件:JCheckBoxJRadioButtonJSliderJComboBoxJProgressBarJToggleButtonJListJTabbedPaneJTextAreaJTextPane

JCheckBox

JCheckBox是带有标签的框,该标签具有两种状态:开和关。 如果选中此复选框,则在复选框中用勾号表示。 复选框可用于在启动时显示或隐藏启动屏幕,切换工具栏的可见性等。

通过JCheckBox可以使用ActionListenerItemListener。 通常使用后一种选项。 ItemListener是用于接收项目事件的接口。 对处理项目事件感兴趣的类,例如观察者,实现此接口。 使用组件的addItemListener()方法向组件注册观察者对象。 发生项目选择事件时,将调用观察者的itemStateChanged()方法。

CheckBoxEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JCheckBox;
  4. import javax.swing.JComponent;
  5. import javax.swing.JFrame;
  6. import java.awt.EventQueue;
  7. import java.awt.event.ItemEvent;
  8. import java.awt.event.ItemListener;
  9. public class CheckBoxEx extends JFrame
  10. implements ItemListener {
  11. public CheckBoxEx() {
  12. initUI();
  13. }
  14. private void initUI() {
  15. var cb = new JCheckBox("Show title", true);
  16. cb.addItemListener(this);
  17. createLayout(cb);
  18. setSize(280, 200);
  19. setTitle("JCheckBox");
  20. setLocationRelativeTo(null);
  21. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  22. }
  23. @Override
  24. public void itemStateChanged(ItemEvent e) {
  25. int sel = e.getStateChange();
  26. if (sel == ItemEvent.SELECTED) {
  27. setTitle("JCheckBox");
  28. } else {
  29. setTitle("");
  30. }
  31. }
  32. private void createLayout(JComponent... arg) {
  33. var pane = getContentPane();
  34. var gl = new GroupLayout(pane);
  35. pane.setLayout(gl);
  36. gl.setAutoCreateContainerGaps(true);
  37. gl.setHorizontalGroup(gl.createParallelGroup()
  38. .addComponent(arg[0])
  39. );
  40. gl.setVerticalGroup(gl.createSequentialGroup()
  41. .addComponent(arg[0])
  42. );
  43. }
  44. public static void main(String[] args) {
  45. EventQueue.invokeLater(() -> {
  46. var ex = new CheckBoxEx();
  47. ex.setVisible(true);
  48. });
  49. }
  50. }

我们的代码示例根据是否选中复选框来显示或隐藏窗口的标题。

  1. public class CheckBoxEx extends JFrame
  2. implements ItemListener {

我们的应用类实现ItemListener。 这意味着该类必须提供itemStateChanged()方法,在该方法中我们对项目选择事件做出反应。

  1. var checkbox = new JCheckBox("Show title", true);

JCheckBox已创建。 此构造器将文本和复选框的状态作为参数。 最初已选中该复选框。

  1. cb.addItemListener(this);

该应用类被注册为复选框选择事件的观察者。

  1. @Override
  2. public void itemStateChanged(ItemEvent e) {
  3. int sel = e.getStateChange();
  4. if (sel == ItemEvent.SELECTED) {
  5. setTitle("JCheckBox");
  6. } else {
  7. setTitle("");
  8. }
  9. }

我们调用ItemEventgetStateChange()方法来确定复选框的状态。 ItemEvent是一个语义事件,指示已选择或取消选择一项。 它被发送到注册的观察者。 根据复选框的状态,我们使用setTitle()方法显示或隐藏窗口的标题。

基本的 Swing 组件 II - 图1

图:JCheckBox

请注意复选框文本周围的蓝色矩形。 它指示此组件具有键盘焦点。 可以使用 Space 键选择和取消选中该复选框。

JRadioButton

JRadioButton允许用户从一组选项中选择一个独占选项。 它与ButtonGroup组件一起使用。

RadioButtonEx.java

  1. package com.zetcode;
  2. import javax.swing.ButtonGroup;
  3. import javax.swing.GroupLayout;
  4. import javax.swing.JComponent;
  5. import javax.swing.JFrame;
  6. import javax.swing.JLabel;
  7. import javax.swing.JRadioButton;
  8. import javax.swing.LayoutStyle;
  9. import java.awt.EventQueue;
  10. import java.awt.event.ItemEvent;
  11. import java.awt.event.ItemListener;
  12. import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
  13. public class RadioButtonEx extends JFrame
  14. implements ItemListener {
  15. private JLabel sbar;
  16. public RadioButtonEx() {
  17. initUI();
  18. }
  19. private void initUI() {
  20. var lbl = new JLabel("Difficulty");
  21. var group = new ButtonGroup();
  22. var rb1 = new JRadioButton("Easy", true);
  23. var rb2 = new JRadioButton("Medium");
  24. var rb3 = new JRadioButton("Hard");
  25. group.add(rb1);
  26. group.add(rb2);
  27. group.add(rb3);
  28. sbar = new JLabel("Selected: Easy");
  29. rb1.addItemListener(this);
  30. rb2.addItemListener(this);
  31. rb3.addItemListener(this);
  32. createLayout(lbl, rb1, rb2, rb3, sbar);
  33. setSize(350, 250);
  34. setTitle("Radio buttons");
  35. setLocationRelativeTo(null);
  36. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  37. }
  38. @Override
  39. public void itemStateChanged(ItemEvent e) {
  40. int sel = e.getStateChange();
  41. if (sel == ItemEvent.SELECTED) {
  42. var button = (JRadioButton) e.getSource();
  43. var text = button.getText();
  44. var sb = new StringBuilder("Selected: ");
  45. sb.append(text);
  46. sbar.setText(sb.toString());
  47. }
  48. }
  49. private void createLayout(JComponent... arg) {
  50. var pane = getContentPane();
  51. var gl = new GroupLayout(pane);
  52. pane.setLayout(gl);
  53. gl.setAutoCreateContainerGaps(true);
  54. gl.setHorizontalGroup(gl.createParallelGroup()
  55. .addComponent(arg[0])
  56. .addComponent(arg[1])
  57. .addComponent(arg[2])
  58. .addComponent(arg[3])
  59. .addComponent(arg[4])
  60. );
  61. gl.setVerticalGroup(gl.createSequentialGroup()
  62. .addComponent(arg[0])
  63. .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
  64. .addComponent(arg[1])
  65. .addComponent(arg[2])
  66. .addComponent(arg[3])
  67. .addPreferredGap(RELATED,
  68. GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  69. .addComponent(arg[4])
  70. );
  71. }
  72. public static void main(String[] args) {
  73. EventQueue.invokeLater(() -> {
  74. var ex = new RadioButtonEx();
  75. ex.setVisible(true);
  76. });
  77. }
  78. }

该示例具有三个单选按钮。 所选单选按钮的值将显示在状态栏中。

  1. var group = new ButtonGroup();
  2. var rb1 = new JRadioButton("Easy", true);
  3. var rb2 = new JRadioButton("Medium");
  4. var rb3 = new JRadioButton("Hard");
  5. group.add(rb1);
  6. group.add(rb2);
  7. group.add(rb3);

创建三个JRadioButtons并将其放入ButtonGroup中。 预选第一个单选按钮。

  1. rb1.addItemListener(this);
  2. rb2.addItemListener(this);
  3. rb3.addItemListener(this);

所有三个单选按钮共享一个ItemListener

  1. if (sel == ItemEvent.SELECTED) {

当我们选择一个单选按钮时,实际上会触发两个事件:一个事件用于选择,另一个事件用于取消选择。 我们对选择感兴趣。

  1. var button = (JRadioButton) e.getSource();
  2. var text = button.getText();

我们使用getSource()方法获取事件的来源,并获取单选按钮的文本标签。

  1. var sb = new StringBuilder("Selected: ");
  2. sb.append(text);
  3. sbar.setText(sb.toString());

我们构建字符串并将其设置为标签。

基本的 Swing 组件 II - 图2

图:JRadioButtons

JSlider

JSlider是一个组件,使用户可以通过在有限的间隔内滑动旋钮来以图形方式选择一个值。 移动滑块的旋钮,将调用滑块的ChangeListenerstateChanged()方法。

HScale线

JSlider可以选择显示其值范围的刻度线。 刻度线由setMinorTickSpacing()setMajorTickSpacing()setPaintTicks()方法控制。

SliderEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JComponent;
  4. import javax.swing.JFrame;
  5. import javax.swing.JLabel;
  6. import javax.swing.JSlider;
  7. import javax.swing.event.ChangeEvent;
  8. import java.awt.EventQueue;
  9. public class SliderEx extends JFrame {
  10. private JSlider slider;
  11. private JLabel lbl;
  12. public SliderEx() {
  13. initUI();
  14. }
  15. private void initUI() {
  16. slider = new JSlider(0, 100, 0);
  17. slider.setMinorTickSpacing(5);
  18. slider.setMajorTickSpacing(10);
  19. slider.setPaintTicks(true);
  20. slider.addChangeListener((ChangeEvent event) -> {
  21. int value = slider.getValue();
  22. lbl.setText(Integer.toString(value));
  23. });
  24. lbl = new JLabel("...");
  25. createLayout(slider, lbl);
  26. setTitle("JSlider");
  27. setDefaultCloseOperation(EXIT_ON_CLOSE);
  28. setLocationRelativeTo(null);
  29. }
  30. private void createLayout(JComponent... arg) {
  31. var pane = getContentPane();
  32. var gl = new GroupLayout(pane);
  33. pane.setLayout(gl);
  34. gl.setAutoCreateContainerGaps(true);
  35. gl.setAutoCreateGaps(true);
  36. gl.setHorizontalGroup(gl.createParallelGroup()
  37. .addComponent(arg[0])
  38. .addComponent(arg[1])
  39. );
  40. gl.setVerticalGroup(gl.createSequentialGroup()
  41. .addComponent(arg[0])
  42. .addComponent(arg[1])
  43. );
  44. pack();
  45. }
  46. public static void main(String[] args) {
  47. EventQueue.invokeLater(() -> {
  48. var ex = new SliderEx();
  49. ex.setVisible(true);
  50. });
  51. }
  52. }

在代码示例中,从滑块选择的值显示在标签组件中。

  1. slider = new JSlider(0, 100, 0);

将使用最小值,最大值和当前值作为参数来创建JSlider

  1. slider.setMinorTickSpacing(5);
  2. slider.setMajorTickSpacing(10);

我们将次要刻度线和主要刻度线之间的距离设置为。

  1. slider.setPaintTicks(true);

setPaintTicks()方法确定是否在滑块上绘制刻度线。

  1. slider.addChangeListener((ChangeEvent event) -> {
  2. int value = slider.getValue();
  3. lbl.setText(Integer.toString(value));
  4. });

当滑块进行某种更改时,将触发ChangeEvent。 我们使用getValue()方法获得滑块的当前值,使用Integer.toString()将整数转换为字符串,然后使用标签的setText()方法将其设置为标签。

基本的 Swing 组件 II - 图3

图:JSlider

音量控件

第二个示例使用JSlider创建音量控件。

SliderEx2.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.ImageIcon;
  4. import javax.swing.JComponent;
  5. import javax.swing.JFrame;
  6. import javax.swing.JLabel;
  7. import javax.swing.JSlider;
  8. import javax.swing.event.ChangeEvent;
  9. import java.awt.EventQueue;
  10. public class SliderEx2 extends JFrame {
  11. private JSlider slider;
  12. private JLabel lbl;
  13. private ImageIcon mute;
  14. private ImageIcon min;
  15. private ImageIcon med;
  16. private ImageIcon max;
  17. public SliderEx2() {
  18. initUI();
  19. }
  20. private void initUI() {
  21. loadImages();
  22. slider = new JSlider(0, 150, 0);
  23. slider.addChangeListener((ChangeEvent event) -> {
  24. int value = slider.getValue();
  25. if (value == 0) {
  26. lbl.setIcon(mute);
  27. } else if (value > 0 && value <= 30) {
  28. lbl.setIcon(min);
  29. } else if (value > 30 && value < 80) {
  30. lbl.setIcon(med);
  31. } else {
  32. lbl.setIcon(max);
  33. }
  34. });
  35. lbl = new JLabel(mute, JLabel.CENTER);
  36. createLayout(slider, lbl);
  37. setTitle("JSlider");
  38. setDefaultCloseOperation(EXIT_ON_CLOSE);
  39. setLocationRelativeTo(null);
  40. }
  41. private void loadImages() {
  42. mute = new ImageIcon("src/resources/mute.png");
  43. min = new ImageIcon("src/resources/min.png");
  44. med = new ImageIcon("src/resources/med.png");
  45. max = new ImageIcon("src/resources/max.png");
  46. }
  47. private void createLayout(JComponent... arg) {
  48. var pane = getContentPane();
  49. var gl = new GroupLayout(pane);
  50. pane.setLayout(gl);
  51. gl.setAutoCreateContainerGaps(true);
  52. gl.setAutoCreateGaps(true);
  53. gl.setHorizontalGroup(gl.createSequentialGroup()
  54. .addComponent(arg[0])
  55. .addComponent(arg[1])
  56. );
  57. gl.setVerticalGroup(gl.createParallelGroup()
  58. .addComponent(arg[0])
  59. .addComponent(arg[1])
  60. );
  61. pack();
  62. }
  63. public static void main(String[] args) {
  64. EventQueue.invokeLater(() -> {
  65. var ex = new SliderEx2();
  66. ex.setVisible(true);
  67. });
  68. }
  69. }

在代码示例中,我们显示了JSliderJLabel组件。 通过拖动滑块,我们可以更改标签组件上的图标。

  1. slider = new JSlider(0, 150, 0);

这是一个JSlider构造器。 参数为最小值,最大值和当前值。

  1. private void loadImages() {
  2. mute = new ImageIcon("src/resources/mute.png");
  3. min = new ImageIcon("src/resources/min.png");
  4. med = new ImageIcon("src/resources/med.png");
  5. max = new ImageIcon("src/resources/max.png");
  6. }

loadImages()方法中,我们从磁盘加载图像文件。

  1. slider.addChangeListener((ChangeEvent event) -> {
  2. ...
  3. });

我们将ChangeListener添加到滑块。 在监听器内部,我们确定当前的滑块值并相应地更新标签。

基本的 Swing 组件 II - 图4

图:JSlider作为音量控件

JComboBox

JComboBox是一个组合了按钮或可编辑字段和下拉列表的组件。 用户可以从下拉列表中选择一个值,该列表应用户的要求出现。 如果使组合框可编辑,则组合框将包含一个可编辑字段,用户可以在其中输入值。

ComboBoxEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JComboBox;
  4. import javax.swing.JComponent;
  5. import javax.swing.JFrame;
  6. import javax.swing.JLabel;
  7. import java.awt.EventQueue;
  8. import java.awt.event.ItemEvent;
  9. import java.awt.event.ItemListener;
  10. import static javax.swing.GroupLayout.Alignment.BASELINE;
  11. public class ComboBoxEx extends JFrame
  12. implements ItemListener {
  13. private JLabel display;
  14. private JComboBox<String> box;
  15. private String[] distros;
  16. public ComboBoxEx() {
  17. initUI();
  18. }
  19. private void initUI() {
  20. distros = new String[]{"Ubuntu", "Redhat", "Arch",
  21. "Debian", "Mint"};
  22. box = new JComboBox<>(distros);
  23. box.addItemListener(this);
  24. display = new JLabel("Ubuntu");
  25. createLayout(box, display);
  26. setTitle("JComboBox");
  27. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  28. setLocationRelativeTo(null);
  29. }
  30. private void createLayout(JComponent... arg) {
  31. var pane = getContentPane();
  32. var gl = new GroupLayout(pane);
  33. pane.setLayout(gl);
  34. gl.setAutoCreateContainerGaps(true);
  35. gl.setAutoCreateGaps(true);
  36. gl.setHorizontalGroup(gl.createSequentialGroup()
  37. .addComponent(arg[0])
  38. .addComponent(arg[1])
  39. );
  40. gl.setVerticalGroup(gl.createParallelGroup(BASELINE)
  41. .addComponent(arg[0])
  42. .addComponent(arg[1])
  43. );
  44. pack();
  45. }
  46. @Override
  47. public void itemStateChanged(ItemEvent e) {
  48. if (e.getStateChange() == ItemEvent.SELECTED) {
  49. display.setText(e.getItem().toString());
  50. }
  51. }
  52. public static void main(String[] args) {
  53. EventQueue.invokeLater(() -> {
  54. var ex = new ComboBoxEx();
  55. ex.setVisible(true);
  56. });
  57. }
  58. }

在我们的示例中,我们有一个组合框和一个标签。 组合框包含一个字符串列表,这些字符串表示 Linux 发行版的名称。 从组合框中选择的项目显示在标签中。 组合框使用其ItemListener来检测更改。

  1. distros = new String[] {"Ubuntu", "Redhat", "Arch",
  2. "Debian", "Mint"};

JComboBox将保存这些字符串值。

  1. display = new JLabel("Ubuntu");

显示区域是简单的JLabel。 它显示该项目最初显示在组合框中。

  1. box = new JComboBox<>(distros);
  2. box.addItemListener(this);

JComboBox的构造器采用 Linux 发行版的字符串数组。 我们将监听器插入创建的对象。

  1. gl.setVerticalGroup(gl.createParallelGroup(BASELINE)
  2. .addComponent(arg[0])
  3. .addComponent(arg[1])
  4. );

在垂直方向上,两个组件将与其文本的基线对齐。

  1. @Override
  2. public void itemStateChanged(ItemEvent e) {
  3. if (e.getStateChange() == ItemEvent.SELECTED) {
  4. display.setText(e.getItem().toString());
  5. }
  6. }

当用户选择或取消选择一个项目时,将调用itemStateChanged()。 我们检查ItemEvent.SELECTED状态,并将组合框的所选项目设置为标签。

基本的 Swing 组件 II - 图5

图:JComboBox

JProgressBar

进度条是我们处理冗长的任务时使用的组件。 它具有动画效果,以便用户知道我们的任务正在进行中。 JProgressBar组件提供水平或垂直进度条。 初始和最小值为 0,最大值为 100。

ProgressBarEx.java

  1. package com.zetcode;
  2. import javax.swing.AbstractAction;
  3. import javax.swing.GroupLayout;
  4. import javax.swing.JButton;
  5. import javax.swing.JComponent;
  6. import javax.swing.JFrame;
  7. import javax.swing.JProgressBar;
  8. import javax.swing.Timer;
  9. import java.awt.EventQueue;
  10. import java.awt.event.ActionEvent;
  11. import java.awt.event.ActionListener;
  12. import static javax.swing.GroupLayout.Alignment.CENTER;
  13. public class ProgressBarEx extends JFrame {
  14. private Timer timer;
  15. private JProgressBar progBar;
  16. private JButton startBtn;
  17. private final int MAX_VAL = 100;
  18. public ProgressBarEx() {
  19. initUI();
  20. }
  21. private void initUI() {
  22. progBar = new JProgressBar();
  23. progBar.setStringPainted(true);
  24. startBtn = new JButton("Start");
  25. startBtn.addActionListener(new ClickAction());
  26. timer = new Timer(50, new UpdateBarListener());
  27. createLayout(progBar, startBtn);
  28. setTitle("JProgressBar");
  29. setDefaultCloseOperation(EXIT_ON_CLOSE);
  30. setLocationRelativeTo(null);
  31. }
  32. private void createLayout(JComponent... arg) {
  33. var pane = getContentPane();
  34. var gl = new GroupLayout(pane);
  35. pane.setLayout(gl);
  36. gl.setAutoCreateContainerGaps(true);
  37. gl.setAutoCreateGaps(true);
  38. gl.setHorizontalGroup(gl.createSequentialGroup()
  39. .addComponent(arg[0])
  40. .addComponent(arg[1])
  41. );
  42. gl.setVerticalGroup(gl.createParallelGroup(CENTER)
  43. .addComponent(arg[0])
  44. .addComponent(arg[1])
  45. );
  46. pack();
  47. }
  48. private class UpdateBarListener implements ActionListener {
  49. @Override
  50. public void actionPerformed(ActionEvent e) {
  51. int val = progBar.getValue();
  52. if (val >= MAX_VAL) {
  53. timer.stop();
  54. startBtn.setText("End");
  55. return;
  56. }
  57. progBar.setValue(++val);
  58. }
  59. }
  60. private class ClickAction extends AbstractAction {
  61. @Override
  62. public void actionPerformed(ActionEvent e) {
  63. if (timer.isRunning()) {
  64. timer.stop();
  65. startBtn.setText("Start");
  66. } else if (!"End".equals(startBtn.getText())) {
  67. timer.start();
  68. startBtn.setText("Stop");
  69. }
  70. }
  71. }
  72. public static void main(String[] args) {
  73. EventQueue.invokeLater(() -> {
  74. var ex = new ProgressBarEx();
  75. ex.setVisible(true);
  76. });
  77. }
  78. }

该示例显示一个进度条和一个按钮。 该按钮将启动和停止进度。

  1. progBar = new JProgressBar();
  2. progBar.setStringPainted(true);

在这里,我们创建JProgressBar组件。 最小值为 0,最大值为 100,初始值为 0。这是默认值。 setStringPainted()方法确定进度条是否显示已完成任务的百分比。

  1. timer = new Timer(50, new UpdateBarListener());

计时器对象每 50 毫秒启动一次UpdateBarListener。 在监听器内部,我们检查进度条是否达到最大值。

  1. private class UpdateBarListener implements ActionListener {
  2. @Override
  3. public void actionPerformed(ActionEvent e) {
  4. int val = progBar.getValue();
  5. if (val >= MAX_VAL) {
  6. timer.stop();
  7. startBtn.setText("End");
  8. return;
  9. }
  10. progBar.setValue(++val);
  11. }
  12. }

监听器的actionPerformed()方法增加进度条的当前值。 如果达到最大值,则计时器停止计时,并且按钮的标签设置为"End"

  1. private class ClickAction extends AbstractAction {
  2. @Override
  3. public void actionPerformed(ActionEvent e) {
  4. if (timer.isRunning()) {
  5. timer.stop();
  6. startBtn.setText("Start");
  7. } else if (!"End".equals(startBtn.getText())) {
  8. timer.start();
  9. startBtn.setText("Stop");
  10. }
  11. }
  12. }

该按钮启动或停止计时器。 该按钮的文本会动态更新。 它可以具有"Start"Stop"End"字符串值。

基本的 Swing 组件 II - 图6

图:JProgressBar

JToggleButton

JToggleButton是具有两种状态的按钮:已按下和未按下。 我们通过单击在这两种状态之间切换。 在某些情况下此功能非常合适。

ToggleButtonEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JComponent;
  4. import javax.swing.JFrame;
  5. import javax.swing.JPanel;
  6. import javax.swing.JToggleButton;
  7. import javax.swing.border.LineBorder;
  8. import java.awt.Color;
  9. import java.awt.Dimension;
  10. import java.awt.EventQueue;
  11. import java.awt.event.ActionEvent;
  12. import java.awt.event.ActionListener;
  13. import static javax.swing.GroupLayout.Alignment.CENTER;
  14. import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;
  15. public class ToggleButtonEx extends JFrame
  16. implements ActionListener {
  17. private JToggleButton redBtn;
  18. private JToggleButton greenBtn;
  19. private JToggleButton blueBtn;
  20. private JPanel display;
  21. public ToggleButtonEx() {
  22. initUI();
  23. }
  24. private void initUI() {
  25. redBtn = new JToggleButton("red");
  26. redBtn.addActionListener(this);
  27. greenBtn = new JToggleButton("green");
  28. greenBtn.addActionListener(this);
  29. blueBtn = new JToggleButton("blue");
  30. blueBtn.addActionListener(this);
  31. display = new JPanel();
  32. display.setPreferredSize(new Dimension(120, 120));
  33. display.setBorder(LineBorder.createGrayLineBorder());
  34. display.setBackground(Color.black);
  35. createLayout(redBtn, greenBtn, blueBtn, display);
  36. setTitle("JToggleButton");
  37. setLocationRelativeTo(null);
  38. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  39. }
  40. private void createLayout(JComponent... arg) {
  41. var pane = getContentPane();
  42. var gl = new GroupLayout(pane);
  43. pane.setLayout(gl);
  44. gl.setAutoCreateContainerGaps(true);
  45. gl.setAutoCreateGaps(true);
  46. gl.setHorizontalGroup(gl.createSequentialGroup()
  47. .addGroup(gl.createParallelGroup()
  48. .addComponent(arg[0])
  49. .addComponent(arg[1])
  50. .addComponent(arg[2]))
  51. .addPreferredGap(UNRELATED)
  52. .addComponent(arg[3])
  53. );
  54. gl.setVerticalGroup(gl.createParallelGroup(CENTER)
  55. .addGroup(gl.createSequentialGroup()
  56. .addComponent(arg[0])
  57. .addComponent(arg[1])
  58. .addComponent(arg[2]))
  59. .addComponent(arg[3])
  60. );
  61. gl.linkSize(redBtn, greenBtn, blueBtn);
  62. pack();
  63. }
  64. @Override
  65. public void actionPerformed(ActionEvent e) {
  66. var color = display.getBackground();
  67. int red = color.getRed();
  68. int green = color.getGreen();
  69. int blue = color.getBlue();
  70. if (e.getActionCommand().equals("red")) {
  71. if (red == 0) {
  72. red = 255;
  73. } else {
  74. red = 0;
  75. }
  76. }
  77. if (e.getActionCommand().equals("green")) {
  78. if (green == 0) {
  79. green = 255;
  80. } else {
  81. green = 0;
  82. }
  83. }
  84. if (e.getActionCommand().equals("blue")) {
  85. if (blue == 0) {
  86. blue = 255;
  87. } else {
  88. blue = 0;
  89. }
  90. }
  91. var setCol = new Color(red, green, blue);
  92. display.setBackground(setCol);
  93. }
  94. public static void main(String[] args) {
  95. EventQueue.invokeLater(() -> {
  96. var ex = new ToggleButtonEx();
  97. ex.setVisible(true);
  98. });
  99. }
  100. }

该示例具有三个切换按钮和一个面板。 我们将显示面板的背景色设置为黑色。 切换按钮将切换颜色值的红色,绿色和蓝色部分。 背景颜色取决于我们按下的切换按钮。

  1. redBtn = new JToggleButton("red");
  2. redBtn.addActionListener(this);

在这里,我们创建一个切换按钮并为其设置一个动作监听器。

  1. display = new JPanel();
  2. display.setPreferredSize(new Dimension(120, 120));
  3. display.setBorder(LineBorder.createGrayLineBorder());
  4. display.setBackground(Color.black);

这是显示通过切换按钮混合的颜色值的面板。 我们设置其首选大小(默认值非常小),将边界线更改为灰色,并设置初始背景色。

  1. var color = display.getBackground();
  2. int red = color.getRed();
  3. int green = color.getGreen();
  4. int blue = color.getBlue();

actionPerformed()方法中,我们确定显示背景色的当前红色,绿色和蓝色部分。

  1. if (e.getActionCommand().equals("red")) {
  2. if (red == 0) {
  3. red = 255;
  4. } else {
  5. red = 0;
  6. }
  7. }

我们确定切换了哪个按钮,并相应地更新 RGB 值的颜色部分。

  1. var setCol = new Color(red, green, blue);
  2. display.setBackground(setCol);

创建新的颜色,并将显示面板更新为新的颜色。

基本的 Swing 组件 II - 图7

图:JToggleButton

JList组件

JList是显示对象列表的组件。 它允许用户选择一项或多项。

ListEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JComponent;
  4. import javax.swing.JFrame;
  5. import javax.swing.JLabel;
  6. import javax.swing.JList;
  7. import javax.swing.JScrollPane;
  8. import java.awt.EventQueue;
  9. import java.awt.Font;
  10. import java.awt.GraphicsEnvironment;
  11. public class ListEx extends JFrame {
  12. private JLabel label;
  13. private JScrollPane spane;
  14. public ListEx() {
  15. initUI();
  16. }
  17. private void initUI() {
  18. var ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  19. var fonts = ge.getAvailableFontFamilyNames();
  20. var list = new JList(fonts);
  21. list.addListSelectionListener(e -> {
  22. if (!e.getValueIsAdjusting()) {
  23. var name = (String) list.getSelectedValue();
  24. var font = new Font(name, Font.PLAIN, 12);
  25. label.setFont(font);
  26. }
  27. });
  28. spane = new JScrollPane();
  29. spane.getViewport().add(list);
  30. label = new JLabel("Aguirre, der Zorn Gottes");
  31. label.setFont(new Font("Serif", Font.PLAIN, 12));
  32. createLayout(spane, label);
  33. setTitle("JList");
  34. setDefaultCloseOperation(EXIT_ON_CLOSE);
  35. setLocationRelativeTo(null);
  36. }
  37. private void createLayout(JComponent... arg) {
  38. var pane = getContentPane();
  39. var gl = new GroupLayout(pane);
  40. pane.setLayout(gl);
  41. gl.setAutoCreateContainerGaps(true);
  42. gl.setAutoCreateGaps(true);
  43. gl.setHorizontalGroup(gl.createParallelGroup()
  44. .addComponent(arg[0])
  45. .addComponent(arg[1])
  46. );
  47. gl.setVerticalGroup(gl.createSequentialGroup()
  48. .addComponent(arg[0])
  49. .addComponent(arg[1])
  50. );
  51. pack();
  52. }
  53. public static void main(String[] args) {
  54. EventQueue.invokeLater(() -> {
  55. var ex = new ListEx();
  56. ex.setVisible(true);
  57. });
  58. }
  59. }

在我们的示例中,我们将显示JListJLabel组件。 列表组件包含我们系统上所有可用字体系列名称的列表。 如果我们从列表中选择一项,则标签将以所选字体显示。

  1. var ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  2. var fonts = ge.getAvailableFontFamilyNames();

在这里,我们获得系统上所有可能的字体系列名称。

  1. var list = new JList(fonts);

我们创建一个JList组件。

  1. list.addListSelectionListener(e -> {
  2. if (!e.getValueIsAdjusting()) {
  3. ...
  4. }
  5. });

列表选择中的事件已分组。 我们收到选择和取消选择项目的事件。 为了仅过滤选择事件,我们使用getValueIsAdjusting()方法。

  1. var name = (String) list.getSelectedValue();
  2. var font = new Font(name, Font.PLAIN, 12);
  3. label.setFont(font);

我们得到所选项目并为标签设置新字体。

  1. spane = new JScrollPane();
  2. spane.getViewport().add(list);

JList可以包含的项目比实际显示在窗口上的项目多。 默认情况下它不可滚动。 我们将列表放入JScrollPane以使其可滚动。

基本的 Swing 组件 II - 图8

图:JList

JTabbedPane组件

JTabbedPane是允许用户通过单击选项卡在一组组件之间切换的组件。

TabbedPaneEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JComponent;
  4. import javax.swing.JFrame;
  5. import javax.swing.JLabel;
  6. import javax.swing.JPanel;
  7. import javax.swing.JTabbedPane;
  8. import java.awt.EventQueue;
  9. public class TabbedPaneEx extends JFrame {
  10. public TabbedPaneEx() {
  11. initUI();
  12. }
  13. private void initUI() {
  14. var tabbedPane = new JTabbedPane();
  15. tabbedPane.addTab("First", createPanel("First panel"));
  16. tabbedPane.addTab("Second", createPanel("Second panel"));
  17. tabbedPane.addTab("Third", createPanel("Third panel"));
  18. createLayout(tabbedPane);
  19. setTitle("JTabbedPane");
  20. setLocationRelativeTo(null);
  21. setDefaultCloseOperation(EXIT_ON_CLOSE);
  22. }
  23. private JPanel createPanel(String text) {
  24. var panel = new JPanel();
  25. var lbl = new JLabel(text);
  26. panel.add(lbl);
  27. return panel;
  28. }
  29. private void createLayout(JComponent... arg) {
  30. var pane = getContentPane();
  31. var gl = new GroupLayout(pane);
  32. pane.setLayout(gl);
  33. gl.setAutoCreateContainerGaps(true);
  34. gl.setAutoCreateGaps(true);
  35. gl.setHorizontalGroup(gl.createSequentialGroup()
  36. .addComponent(arg[0])
  37. );
  38. gl.setVerticalGroup(gl.createParallelGroup()
  39. .addComponent(arg[0])
  40. );
  41. pack();
  42. }
  43. public static void main(String[] args) {
  44. EventQueue.invokeLater(() -> {
  45. var ex = new TabbedPaneEx();
  46. ex.setVisible(true);
  47. });
  48. }
  49. }

在示例中,我们有一个带有三个选项卡的选项卡式窗格。 每个选项卡都显示一个带有标签的面板。

  1. var tabbedPane = new JTabbedPane();

创建一个新的JTabbedPane

  1. tabbedPane.addTab("First", createPanel("First panel"));

使用addTab()方法,我们创建了一个新标签。 第一个参数是选项卡显示的标题。 第二个参数是单击选项卡时要显示的组件。

基本的 Swing 组件 II - 图9

图:JTabbedPane

JTextArea组件

JTextArea是显示纯文本的多行文本区域。 它是用于处理文本的轻量级组件。 该组件不处理滚动。 对于此任务,我们使用JScrollPane组件。

TextAreaEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JComponent;
  4. import javax.swing.JFrame;
  5. import javax.swing.JScrollPane;
  6. import javax.swing.JTextArea;
  7. import java.awt.Dimension;
  8. import java.awt.EventQueue;
  9. public class TextAreaEx extends JFrame {
  10. public TextAreaEx() {
  11. initUI();
  12. }
  13. private void initUI() {
  14. var area = new JTextArea();
  15. var spane = new JScrollPane(area);
  16. area.setLineWrap(true);
  17. area.setWrapStyleWord(true);
  18. createLayout(spane);
  19. setTitle("JTextArea");
  20. setSize(new Dimension(350, 300));
  21. setDefaultCloseOperation(EXIT_ON_CLOSE);
  22. setLocationRelativeTo(null);
  23. }
  24. private void createLayout(JComponent... arg) {
  25. var pane = getContentPane();
  26. var gl = new GroupLayout(pane);
  27. pane.setLayout(gl);
  28. gl.setAutoCreateContainerGaps(true);
  29. gl.setAutoCreateGaps(true);
  30. gl.setHorizontalGroup(gl.createParallelGroup()
  31. .addComponent(arg[0])
  32. );
  33. gl.setVerticalGroup(gl.createSequentialGroup()
  34. .addComponent(arg[0])
  35. );
  36. pack();
  37. }
  38. public static void main(String[] args) {
  39. EventQueue.invokeLater(() -> {
  40. var ex = new TextAreaEx();
  41. ex.setVisible(true);
  42. });
  43. }
  44. }

该示例显示了一个简单的JTextArea组件。

  1. var area = new JTextArea();

这是JTextArea组件的构造器。

  1. var spane = new JScrollPane(area);

为了使文本可滚动,我们将JTextArea组件放入JScrollPane组件。

  1. area.setLineWrap(true);

如果线条太长而无法容纳文本区域的宽度,则setLineWrap()会对其进行换行。

  1. area.setWrapStyleWord(true);

在这里,我们指定线将如何包装。 在我们的例子中,行将被包裹在单词边界(空白)处。

基本的 Swing 组件 II - 图10

图:JTextArea

JTextPane组件

JTextPane组件是用于处理文本的更高级的组件。 该组件可以对文本执行一些复杂的格式化操作。 它也可以显示 HTML 文档。

test.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Simple HTML document</title>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. </head>
  8. <body>
  9. <h2>A simple HTML document</h2>
  10. <p>
  11. <em>JTextPane</em> can display HTML documents.
  12. </p>
  13. <br>
  14. <pre>
  15. JScrollPane pane = new JScrollPane();
  16. JTextPane textpane = new JTextPane();
  17. textpane.setContentType("text/html");
  18. textpane.setEditable(false);
  19. </pre>
  20. <br>
  21. <p>The Java Swing tutorial, 2018</p>
  22. </body>
  23. </html>

这是我们正在加载到JTextPane组件中的 HTML 代码。 该组件不处理滚动。

TextPaneEx.java

  1. package com.zetcode;
  2. import javax.swing.GroupLayout;
  3. import javax.swing.JComponent;
  4. import javax.swing.JFrame;
  5. import javax.swing.JScrollPane;
  6. import javax.swing.JTextPane;
  7. import java.awt.EventQueue;
  8. import java.io.IOException;
  9. import java.util.logging.Level;
  10. import java.util.logging.Logger;
  11. public class TextPaneEx extends JFrame {
  12. private JTextPane textPane;
  13. public TextPaneEx() {
  14. initUI();
  15. }
  16. private void initUI() {
  17. textPane = new JTextPane();
  18. var spane = new JScrollPane(textPane);
  19. textPane.setContentType("text/html");
  20. textPane.setEditable(false);
  21. loadFile();
  22. createLayout(spane);
  23. setTitle("JTextPane");
  24. setDefaultCloseOperation(EXIT_ON_CLOSE);
  25. setLocationRelativeTo(null);
  26. }
  27. private void createLayout(JComponent... arg) {
  28. var pane = getContentPane();
  29. var gl = new GroupLayout(pane);
  30. pane.setLayout(gl);
  31. gl.setAutoCreateContainerGaps(true);
  32. gl.setAutoCreateGaps(true);
  33. gl.setHorizontalGroup(gl.createSequentialGroup()
  34. .addComponent(arg[0])
  35. );
  36. gl.setVerticalGroup(gl.createParallelGroup()
  37. .addComponent(arg[0])
  38. );
  39. pack();
  40. }
  41. private void loadFile() {
  42. try {
  43. var curDir = System.getProperty("user.dir") + "/";
  44. textPane.setPage("File:///" + curDir + "test.html");
  45. } catch (IOException ex) {
  46. Logger.getLogger(this.getName()).log(Level.SEVERE,
  47. "Failed to load file", ex);
  48. }
  49. }
  50. public static void main(String[] args) {
  51. EventQueue.invokeLater(() -> {
  52. var ex = new TextPaneEx();
  53. ex.setVisible(true);
  54. });
  55. }
  56. }

在我们的示例中,我们显示JTextPane组件并加载 HTML 文档。 HTML 文档是从当前工作目录加载的。 当我们使用 IDE 时,它是一个项目目录。 该示例显示了组件的格式化函数。

  1. var textpane = new JTextPane();
  2. textpane.setContentType("text/html");
  3. textpane.setEditable(false);

我们创建一个JTextPane组件,将该组件的内容设置为 HTML 文档并禁用编辑。

  1. private void loadFile() {
  2. try {
  3. var curDir = System.getProperty("user.dir") + "/";
  4. textPane.setPage("File:///" + curDir + "test.html");
  5. } catch (IOException ex) {
  6. Logger.getLogger(this.getName()).log(Level.SEVERE,
  7. "Failed to load file", ex);
  8. }
  9. }

在这里,我们确定用户的当前工作目录。 我们将 HTML 文档加载到窗格中。

基本的 Swing 组件 II - 图11

图:JTextPane

在本章中,我们继续介绍基本的 Swing 组件,包括JCheckBoxJRadioButtonJSliderJComboBoxJProgressBarJToggleButtonJListJTabbedPaneJTextAreaJTextPane