JAVA Swing 图形化界面编程

目录

  • 1.组件
    • 1.1 基本组件
    • 1.2. 组件边框
    • 1.3. JToolBar 工具条
    • 1.4 JColorChooser 颜色选择器
    • 1.5 JFileChooser 文件选择器
    • 1.6 JOptionPane 对话框
      • 1. MessageDialog 消息对话框
      • 2. ConfirmDialog 确认对话框
      • 3. InputDialog 输入对话框
      • 4. OptionDialog 选择对话框
  • 2. 特殊布局
    • 2.1 JSplitPane 分隔容器
    • 2.2 JTabbedPane 标签页容器
  • 3. 进度条
    • 3.1 JProcessBar
      • 3.1.1 Model模型
    • 3.2 进度条提示框
  • 4. JList、JComboBox实现列表框
    • 4.1 简单列表框
    • 4.2 不强制存储列表项的ListModel和ComboBoxModel
    • 4.3 强制存储列表项的DefaultListModel和DefaultComboBoxModel
    • 4.4 使用ListCellRenderer绘制列表项的外观
  • 5. JTree、TreeModel实现树
    • 5.1 创建简单的树
      • 5.1.1 **JTree常用构造方法**
      • 5.1.2 **TreeNode继承体系及使用**
      • 5.1.3 外观
      • 5.1.4 JTree的基本方法
    • 5.2 编辑树的结点
      • 5.2.1 编辑树的结点
      • 5.2.1拖动树的结点
      • 5.2.2 监听结点事件
    • 5.3 扩展DefaultTreeCellRenderer改变结点外观
  • 6. JTable、JTableModel实现表格
    • 6.1 JTable实现简单表格
    • 6.2 TableModel和监视器

Swing组件继承体系图:


Swing组件按照功能来分类:

​ 1. 顶层容器: JFrame、JApplet、JDialog 和 JWindow 。
​ 2. 中间容器: JPanel 、 JScrollPane 、 JSplitPane 、 JToolBar 等 。
​ 3. 特殊容器:在用户界面上具有特殊作用的中间容器,如 JIntemalFrame 、 JRootPane 、 JLayeredPane和 JDestopPane 等 。
​ 4. 基本组件 : 实现人机交互的组件,如 JButton、 JComboBox 、 JList、 JMenu、 JSlider 等 。
​ 5. 不可编辑信息的显示组件:向用户显示不可编辑信息的组件,如JLabel 、 JProgressBar 和 JToolTip等。
​ 6. 可编辑信息的显示组件:向用户显示能被编辑的格式化信息的组件,如 JTable 、 JTextArea 和JTextField 等 。
​ 7. 特殊对话框组件:可以直接产生特殊对话框的组件 , 如 JColorChooser 和 JFileChooser 等。

1.组件

1.1 基本组件

  • 和AWT相比改动:
  1. 下拉选择框
 String [] choice = {"红色","绿色","蓝色"}JComboBox<String> jComboBox = new JComboBox<String>(choice);
  1. 单选组件
     ButtonGroup buttonGroup = new ButtonGroup();JRadioButtonMenuItem manButtonMenuItem  = new JRadioButtonMenuItem("男");JRadioButtonMenuItem womanButtonMenuItem  = new JRadioButtonMenuItem("女");
  1. 右键菜单(单选)
    ButtonGroup popupButtonGroup = new ButtonGroup()JRadioButtonMenuItem metalItem = new JRadioButtonMenuItem("Metal 风格",false);JRadioButtonMenuItem nimbusItem = new JRadioButtonMenuItem("Nimbus 风格",false);
  1. 右键菜单显示,不用监听
 jTextArea.setComponentPopupMenu(popupMenu);
  1. MenuItem之间的隔断editMenu.addSeparator();
import javax.swing.*
import java.awt.*;
import java.awt.event.ActionListener;public class SwingComponentDemo {JFrame jFrame = new JFrame("Swing组件");JPanel jPanelBottom = new JPanel();JTextField jTextField = new JTextField(20);JButton jButton = new JButton("确定");JMenuItem commentMenuItem = new JMenuItem("注释");JMenuItem cancelCommentMenuItem = new JMenuItem("取消注释");JMenuItem autoMenuItem = new JMenuItem("自动换行");JMenuItem copyMenuItem = new JMenuItem("复制",new ImageIcon("./img/component/copy.png"));JMenuItem pasteMenuItem = new JMenuItem("粘贴",new ImageIcon("./img/component/paste.png"));JMenu formatMenu = new JMenu("格式");JMenu textMenu = new JMenu("文本");JMenu editMenu = new JMenu("编辑");JMenuBar jMenuBar = new JMenuBar();Box boxH = Box.createHorizontalBox();JTextArea jTextArea = new JTextArea(8,20);// 下拉选择框String [] choice = {"红色","绿色","蓝色"};JComboBox<String> jComboBox = new JComboBox<String>(choice);//单选组件ButtonGroup buttonGroup = new ButtonGroup();JRadioButtonMenuItem manButtonMenuItem  = new JRadioButtonMenuItem("男");JRadioButtonMenuItem womanButtonMenuItem  = new JRadioButtonMenuItem("女");//复选框JCheckBox marryCheckBox = new JCheckBox("是否已婚",true);//JList<String> colorList = new JList<String>(choice);//容器Box boxTopLeft = Box.createVerticalBox();Box boxTop = Box.createHorizontalBox();//右键菜单JPopupMenu popupMenu = new JPopupMenu();ButtonGroup popupButtonGroup = new ButtonGroup();//定义五个单选按钮菜单项,用于设置程序风格JRadioButtonMenuItem metalItem = new JRadioButtonMenuItem("Metal 风格",false);JRadioButtonMenuItem nimbusItem = new JRadioButtonMenuItem("Nimbus 风格",false);JRadioButtonMenuItem windowsItem = new JRadioButtonMenuItem("Windows 风格",true);JRadioButtonMenuItem classicItem = new JRadioButtonMenuItem("Windows 经典风格",false);JRadioButtonMenuItem motifItem = new JRadioButtonMenuItem("Motif 风格",false);//菜单增加点击事件ActionListener popupActionListener = e -> {String command = e.getActionCommand();try {changeFlavor(command);} catch (Exception e1) {e1.printStackTrace();}};private void init(){//页面底部jButton.setIcon(new ImageIcon("./img/component/ok.png"));jPanelBottom.add(jTextField);jPanelBottom.add(jButton);jFrame.add(jPanelBottom, BorderLayout.SOUTH);//组装menubarcommentMenuItem.setToolTipText("将程序注释");formatMenu.add(commentMenuItem);formatMenu.add(cancelCommentMenuItem);editMenu.add(autoMenuItem);editMenu.addSeparator();editMenu.add(copyMenuItem);editMenu.add(pasteMenuItem);editMenu.addSeparator();editMenu.add(formatMenu);jMenuBar.add(textMenu);jMenuBar.add(editMenu);jFrame.setJMenuBar(jMenuBar);//组装单选组件buttonGroup.add(manButtonMenuItem);buttonGroup.add(womanButtonMenuItem);//boxH.add(jComboBox);boxH.add(manButtonMenuItem);boxH.add(womanButtonMenuItem);boxH.add(marryCheckBox);boxTopLeft.add(jTextArea);boxTopLeft.add(boxH);//文本域的右键菜单//加入一个组,单选popupButtonGroup.add(metalItem);popupButtonGroup.add(nimbusItem);popupButtonGroup.add(windowsItem);popupButtonGroup.add(metalItem);popupButtonGroup.add(classicItem);popupButtonGroup.add(motifItem);popupMenu.add(metalItem);popupMenu.add(nimbusItem);popupMenu.add(windowsItem);popupMenu.add(metalItem);popupMenu.add(classicItem);popupMenu.add(motifItem);metalItem.addActionListener(popupActionListener);nimbusItem.addActionListener(popupActionListener);windowsItem.addActionListener(popupActionListener);classicItem.addActionListener(popupActionListener);motifItem.addActionListener(popupActionListener);//设置右键菜单,简单多了jTextArea.setComponentPopupMenu(popupMenu);boxTop.add(boxTopLeft);boxTop.add(colorList);jFrame.add(boxTop);jFrame.pack();jFrame.setVisible(true);}//定义一个方法,用于改变界面风格private void changeFlavor(String command) throws Exception {switch (command) {case "Metal 风格":UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");break;case "Nimbus 风格":UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");break;case "Windows 风格":UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");break;case "Windows 经典风格":UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");break;case "Motif 风格":UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");break;}//更新f窗口内顶级容器以及所有组件的UISwingUtilities.updateComponentTreeUI(jFrame.getContentPane());//更新mb菜单条及每部所有组件UISwingUtilities.updateComponentTreeUI(jMenuBar);//更新右键菜单及内部所有菜单项的UISwingUtilities.updateComponentTreeUI(popupMenu);}public static void main(String[] args) {new SwingComponentDemo().init();}
}

1.2. 组件边框

1.3. JToolBar 工具条

创建工具条:

  1. 创建JToolBar的对象
  2. 创建Action,参数:(可显示的文本,图标地址)
  3. JToolBar.add(Action对象)
  4. 如果想要显示文本,则需要将Action放入JButton
  • TextArea增加滚动条:
    使用JScrollPan:要在创建对象时就将需要滚动的组件放入到参数中,不能使用add来增加
 JScrollPane jScrollPane = new JScrollPane(jTextArea);
//  不能使用
//  jScrollPane.add(jTextArea)
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;public class JToolBarDemo {JFrame jFrame = new JFrame("JToolBar播放器");JTextArea jTextArea = new JTextArea(10,20);//JScrollPane 作用:增加滚动条,但是只能以下面这种方式增加JScrollPane jScrollPane = new JScrollPane(jTextArea);
//    创建工具条:
//    1. 创建JToolBar的对象
//    2.创建Action,参数:(可显示的文本,图标地址)
//    3. JToolBar.add(Action对象)
//    4.如果想要显示文本,则不要将Action放入JButtonJToolBar jToolBar = new JToolBar("播放器");Action start = new AbstractAction("播放",new ImageIcon("./img/start32.png")) {@Overridepublic void actionPerformed(ActionEvent e) {jTextArea.append("开始播放\n");}};Action pause = new AbstractAction("暂停",new ImageIcon("./img/pause32.png")) {@Overridepublic void actionPerformed(ActionEvent e) {jTextArea.append("暂停\n");}};Action next = new AbstractAction("下一曲",new ImageIcon("./img/next32.png")) {@Overridepublic void actionPerformed(ActionEvent e) {jTextArea.append("下一曲\n");}};JButton startButton = new JButton(start);JButton pauseButton = new JButton(pause);JButton nextButton = new JButton(next);private void init(){jToolBar.add(startButton);jToolBar.add(pauseButton);jToolBar.add(nextButton);jFrame.add(jScrollPane);jFrame.add(jToolBar, BorderLayout.NORTH);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new JToolBarDemo().init();}
}

1.4 JColorChooser 颜色选择器

  • 参数(父窗口,标题,默认选中的颜色)
  • Color color = JColorChooser.showDialog(jFrame, "选择颜色", Color.white);
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;public class ColorDialogDemo {JFrame jFrame = new JFrame();JButton jButton = new JButton(new AbstractAction("选择背景颜色",new ImageIcon("./img/start32.png")) {@Overridepublic void actionPerformed(ActionEvent e) {//参数(父窗口,标题,默认选中的颜色)Color color = JColorChooser.showDialog(jFrame, "选择颜色", Color.white);jTextArea.setBackground(color);}});JTextArea jTextArea = new JTextArea(8,20);private void init(){jFrame.add(jTextArea);jFrame.add(jButton, BorderLayout.SOUTH);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new ColorDialogDemo().init();}
}

1.5 JFileChooser 文件选择器

JFileChooser使用步骤:

  1. 创建JFileChooser对象:
JFileChooser chooser = new JFileChooser("D:\\a");//指定默认打开的本地磁盘路径
  1. 调用JFileChooser的一系列可选方法,进行初始化
setSelectedFile(File file)/setSelectedFiles(File[] selectedFiles):设定默认选中的文件
setMultiSelectionEnabled(boolean b):设置是否允许多选,默认是单选
setFileSelectionMode(int mode):设置可以选择内容,例如文件、文件夹等,默认只能选择文件
  1. 打开文件对话框
showOpenDialog(Component parent):打开文件加载对话框,并指定父组件
showSaveDialog(Component parent):打开文件保存对话框,并指定父组件
  1. 获取用户选择的结果
File getSelectedFile():获取用户选择的一个文件
File[] getSelectedFiles():获取用户选择的多个文件

案例:

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;public class JFileChooserDemo {JFrame jFrame = new JFrame();JMenuBar jMenuBar = new JMenuBar();JMenu jMenu = new JMenu("文件");JFileChooser jFileChooser = new JFileChooser();BufferedImage image;//Swing的JPanel取代了AWT中Canvesprivate class MyJpanel extends JPanel {@Overridepublic void paint(Graphics g) {g.drawImage(image, 0, 0, null);}}MyJpanel myJpanel = new MyJpanel();JTextArea jTextArea = new JTextArea(8, 20);//打开图片,并显示在myJpanelJMenuItem multipleChoiceItem = new JMenuItem(new AbstractAction("打开图片") {@Overridepublic void actionPerformed(ActionEvent e) {//设置要打开的默认路径jFileChooser.setCurrentDirectory(new File("."));//是否允许多选,默认是false单选jFileChooser.setMultiSelectionEnabled(false);//模式:0-文件,1-文件夹,2-文件或文件夹jFileChooser.setFileSelectionMode(0);jFileChooser.showOpenDialog(jFrame);File selectedFile = jFileChooser.getSelectedFile();try {image = ImageIO.read(selectedFile);autoWindow();} catch (IOException ex) {throw new RuntimeException(ex);}myJpanel.repaint();}});//选择多个文件,并将文件的绝对路径显示在TextArea中JMenuItem multiSelectItem = new JMenuItem(new AbstractAction("选择多个文件") {@Overridepublic void actionPerformed(ActionEvent e) {//设置要打开的默认路径jFileChooser.setCurrentDirectory(new File("."));//是否允许多选,默认是false单选jFileChooser.setMultiSelectionEnabled(true);//模式:0-文件,1-文件夹,2-文件或文件夹jFileChooser.setFileSelectionMode(0);jFileChooser.showOpenDialog(jFrame);File[] selectedFiles = jFileChooser.getSelectedFiles();jFrame.remove(myJpanel);for (File file : selectedFiles) {jTextArea.append(file.getPath() + "\n");}jFrame.add(jTextArea);jFrame.pack();}});//选择文件夹JMenuItem folderItem = new JMenuItem(new AbstractAction("选择文件夹") {@Overridepublic void actionPerformed(ActionEvent e) {//设置要打开的默认路径jFileChooser.setCurrentDirectory(new File("."));//是否允许多选,默认是false单选jFileChooser.setMultiSelectionEnabled(false);//模式:0-文件,1-文件夹,2-文件或文件夹jFileChooser.setFileSelectionMode(1);jFileChooser.showOpenDialog(jFrame);File selectedFile = jFileChooser.getSelectedFile();jFrame.remove(myJpanel);jTextArea.append(selectedFile.getPath() + "\n");jFrame.add(jTextArea);jFrame.pack();}});//将图片另存为,通过绑定的方式增加ActionJMenuItem saveItem = new JMenuItem();Action saveItemAction = new AbstractAction("另存为") {@Overridepublic void actionPerformed(ActionEvent e) {jFileChooser.showSaveDialog(jFrame);File file = jFileChooser.getSelectedFile();if (image != null){System.out.println(file);try {ImageIO.write(image,"jpeg",file);} catch (IOException ex) {ex.printStackTrace();}}}};private void autoWindow() {if (image != null) {myJpanel.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));jFrame.pack();}}private void init() {saveItem.setAction(saveItemAction);jMenu.add(multipleChoiceItem);jMenu.add(multiSelectItem);jMenu.add(folderItem);jMenu.add(saveItem);jMenuBar.add(jMenu);jFrame.setJMenuBar(jMenuBar);jFrame.add(myJpanel);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new JFileChooserDemo().init();}
}

1.6 JOptionPane 对话框

通过 JOptionPane 可以非常方便地创建一些简单的对话框, Swing 已经为这些对话框添加了相应的组件,无须程序员手动添加组件 。 JOptionPane 提供了如下 4 个方法来创建对话框 。

方法名称 方法功能
showMessageDialog/showInternalMessageDialog 消息对话框 ,告知用户某事己发生 , 用户只能单击"确定"按钮 , 类似于 JavaScript 的 alert 函数 。
showConfirmDialog/showInternalConfirmDialog 确认对话框,向用户确认某个问题,用户可以选择 yes 、 no ~ cancel 等选项 。 类似于 JavaScript 的 comfirm 函数 。该方法返回用户单击了 哪个按钮
showInputDialog/showInternalInputDialog 输入对话框,提示要求输入某些信息,类似于 JavaScript的 prompt 函数。该方法返回用户输入的字符串 。
showOptionDialog/showInternalOptionDialog 自定义选项对话框 ,允许使用自 定义选项 ,可以取代showConfirmDialog 所产生的对话框,只是用起来更复杂 。

上述方法都有都有很多重载形式,选择其中一种最全的形式,参数解释如下:

showXxxDialog(Component parentComponent,Object message, String title, int optionType, int messageType,ImageIcon icon,Object[] options, Object initialValue)
--参数解释:
parentComponent:当前对话框的父组件
message:对话框上显示的信息,信息可以是字符串、组件、图片等
title:当前对话框的标题
optionType:当前对话框上显示的按钮类型:DEFAULT_OPTION、YES_NO_OPTION、YES_NO_CANCEL_OPTION、OK_CANCEL_OPTION
messageType:当前对话框的类型:ERROR_MESSAGE、INFORMATION_MESSAGE、WARNING_MESSAGE、QUESTION_MESSAGE、PLAIN_MESSAGE
icon:当前对话框左上角的图标
options:自定义下拉列表的选项
initialValue:自定义选项中的默认选中项

当用户与对话框交互结束后,不同类型对话框的返回值如下:

  • showMessageDialog: 无返回值 。
  • showlnputDialog: 返回用户输入或选择的字符串 。
  • showConfirmDialog: 返回 一个整数代表用户选择的选项 。
  • showOptionDialog : 返回 一个整数代表用户选择的选项,如果用户选择第一项,则返回 0; 如果选择第二项,则返回1……依此类推 。

对 showConfirmDialog 所产生的对话框,有如下几个返回值:

  • YES OPTION: 用户 单击了 "是"按钮后返回 。
  • NO OPTION: 用 户单击了"否"按钮后返回 。
  • CANCEL OPTION: 用户单击了"取消"按钮后返回 。
  • OK OPTION : 用户单击了"确定"按钮后返回 。
  • CLOSED OPTION: 用户 单击了对话框右上角的 " x" 按钮后返回。

1. MessageDialog 消息对话框

JOptionPane.showMessageDialog(jFrame, jTextArea.getText(),title,counter,new ImageIcon("./img/component/female.png"));
  • 参数中默认的4个图标很难看,还是自己弄一个吧
  • 参数:父窗口,提示消息内容,标题,系统提供的图标,自定义图标
package Component.JOptionPane;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;public class MessageDialog {JFrame jFrame = new JFrame("对话框演示");int counter = 0;String title = "第"+counter+"个消息";JTextArea jTextArea = new JTextArea(8,20);JButton jButton = new JButton();Action action = new AbstractAction("消息提示框") {@Overridepublic void actionPerformed(ActionEvent e) {title = "第"+counter+"个消息";jTextArea.setText(title);//参数:父窗口,提示消息内容,标题,默认的图标,自定义图标JOptionPane.showMessageDialog(jFrame, jTextArea.getText(),title,counter,new ImageIcon("./img/component/female.png"));counter ++;}};private void init(){jTextArea.append("Hello World");jButton.setAction(action);jFrame.add(jButton, BorderLayout.SOUTH);jFrame.add(jTextArea);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new MessageDialog().init();}
}

2. ConfirmDialog 确认对话框

JOptionPane.showConfirmDialog(jFrame, jTextArea.getText(), "确认对话框", JOptionPane.YES_NO_CANCEL_OPTION, 2, new ImageIcon("./img/component/female.png"));

参数:父窗口,显示的提示信息,标题,显示的按钮类型共4种,系统提供的图标4种,自定义图标

按钮类型:

  1. 默认:DEFAULT_OPTION = -1 只有确定按钮
  2. YES_NO_OPTION = 0; 是、否两个按钮
  3. YES_NO_CANCEL_OPTION = 1;是、否、取消三个按钮
  4. OK_CANCEL_OPTION = 2; 确定、取消两个按钮

返回值:

  1. JOptionPane.YES_OPTION:确认和是都返回0
  2. JOptionPane.NO_OPTION:否返回1
  3. JOptionPane.CANCEL_OPTION:取消返回2
  4. JOptionPane.OK_OPTION:确定返回0
  5. JOptionPane. CLOSED_OPTION:直接关闭对话框返回-1
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;public class ConfirmDialog {JFrame jFrame = new JFrame("对话框演示");JTextArea jTextArea = new JTextArea(8, 20);JButton jButton = new JButton();Action action = new AbstractAction("消息提示框") {@Overridepublic void actionPerformed(ActionEvent e) {//int reslt = JOptionPane.showConfirmDialog(jFrame, jTextArea.getText(), "确认对话框", JOptionPane.YES_NO_CANCEL_OPTION, 2, new ImageIcon("./img/component/female.png"));switch (reslt) {case JOptionPane.YES_OPTION:jTextArea.append("点击 确定 按钮\n");break;case JOptionPane.NO_OPTION:jTextArea.append("点击 否 按钮\n");break;case JOptionPane.CANCEL_OPTION:jTextArea.append("点击 取消 按钮\n");break;                   case JOptionPane.CLOSED_OPTION:jTextArea.append("点击 关闭对话框 按钮\n");break;}}};private void init() {jTextArea.append("Hello World");jButton.setAction(action);jFrame.add(jButton, BorderLayout.SOUTH);jFrame.add(jTextArea);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new ConfirmDialog().init();}
}

3. InputDialog 输入对话框

手动输入内容:参数:(父窗口, 提示信息, 标题, 系统图标),返回String
下拉选择输入:参数:(父窗口, 提示信息, 标题, 系统图标,自定义图标,数组,默认选择),返回Object对象
直接关闭对话框返回:null

package Component.JOptionPane;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;public class InputDialog {JFrame jFrame = new JFrame("对话框演示");JTextArea jTextArea = new JTextArea(8, 20);JButton jButton = new JButton();String[] selectValus = {"1","2"};Action action = new AbstractAction("对话框") {@Overridepublic void actionPerformed(ActionEvent e) {//            String result = JOptionPane.showInputDialog(jFrame, "请输入卡号", "输入对话框", 1);String result = (String) JOptionPane.showInputDialog(jFrame, "请输入卡号", "输入对话框", 1,new ImageIcon("./img/component/female.png"),selectValus,selectValus[0]);jTextArea.append(result+"\n");}};private void init() {jButton.setAction(action);jFrame.add(jButton, BorderLayout.SOUTH);jFrame.add(jTextArea);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new InputDialog().init();}
}

4. OptionDialog 选择对话框

参数:(父窗口, 提示信息, 标题, 系统图标,自定义图标,数组,默认选择),返回Int类型数组下标
如果直接关闭对话框返回:-1

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;public class OptionDialog {JFrame jFrame = new JFrame("对话框演示");JTextArea jTextArea = new JTextArea(8, 20);JButton jButton = new JButton();String[] selectValus = {"1", "2", "3"};Action action = new AbstractAction("对话框") {@Overridepublic void actionPerformed(ActionEvent e) {int result = JOptionPane.showOptionDialog(jFrame, "请选择", "选择对话框", 1, 1, new ImageIcon("./img/component/female.png"), selectValus, selectValus[0]);if (result != -1)jTextArea.append(selectValus[result] + "\n");}};private void init() {jButton.setAction(action);jFrame.add(jButton, BorderLayout.SOUTH);jFrame.add(jTextArea);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new OptionDialog().init();}
}

2. 特殊布局

2.1 JSplitPane 分隔容器

JSplitPane使用步骤:

  1. 创建JSplitPane对象
通过如下构造方法可以创建JSplitPane对象
JSplitPane(int newOrientation, Component newLeftComponent,Component newRightComponent)newOrientation:指定JSplitPane容器的分割方向:如果值为JSplitPane.VERTICAL_SPLIT,为纵向分割;如果值为JSplitPane.HORIZONTAL_SPLIT,为横向分割;newLeftComponent:左侧或者上侧的组件;newRightComponent:右侧或者下侧的组件;
  1. 设置是否开启连续布局的支持(可选)
setContinuousLayout(boolean newContinuousLayout):默认是关闭的,如果设置为true,则打开连续布局的支持,但由于连续布局支持需要不断的重绘组件,所以效率会低一些
  1. 设置是否支持"一触即展"的支持(可选)
setOneTouchExpandable(boolean newValue):默认是关闭的,如果设置为true,则打开"一触即展"的支持
  1. 其他设置
setDividerLocation(double proportionalLocation):设置分隔条的位置为JSplitPane的某个百分比
setDividerLocation(int location):通过像素值设置分隔条的位置
setDividerSize(int newSize):通过像素值设置分隔条的大小
setLeftComponent(Component comp)/setTopComponent(Component comp)/setRightComponent(Component comp)/setBottomComponent(Component comp):设置指定位置的组件

案例:

JSplitPane参数:(方向,第一个组件/容器,第二个组件/容器)
JSplitPane.VERTICAL_SPLIT:垂直
JSplitPane.HORIZONTAL_SPLIT:水平

JList中如果是对象时,通过调用对象类中的toString()方法直接在组件中显示选项
JList选项选中时,调用JList.getSelectedValue(),返回值就是选中的对

文本域增加滚动条:JScrollPane scrollPanenew = new JScrollPane(TextArea);

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;public class SplitPane {JFrame jFrame = new JFrame("特殊容器SplitPane");Book[] books = {new Book("java自学宝典", new ImageIcon("./img/container/java.png"), "java自学宝典"),new Book("java自学宝典1", new ImageIcon("./img/container/android.png"), "java自学宝典"),new Book("java自学宝典2", new ImageIcon("./img/container/jQuery.png"), "java自学宝典")};//直接在参数种装入books,在显示时会调用对象的toString()方法JList<Book> bookList = new JList<Book>(books);JLabel labelCover = new JLabel();JTextArea bookDesc = new JTextArea();private void init(){//给组件设置大小bookList.setPreferredSize(new Dimension(150,400));labelCover.setPreferredSize(new Dimension(220,300));bookDesc.setPreferredSize(new Dimension(220,100));//list添加点击事件bookList.addListSelectionListener(new ListSelectionListener() {@Overridepublic void valueChanged(ListSelectionEvent e) {//获得选择的选项不能使用e,使用getSelectedValue()方法Book book = bookList.getSelectedValue();labelCover.setIcon(book.getImage());bookDesc.setText(book.getDesc());}});//文本域增加滚动条JSplitPane left = new JSplitPane(JSplitPane.VERTICAL_SPLIT,labelCover,new JScrollPane(bookDesc));//开启连续布局left.setContinuousLayout(true);//开启一触即展left.setOneTouchExpandable(true);JSplitPane all = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,left,bookList);jFrame.add(all);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new SplitPane().init();}
}

2.2 JTabbedPane 标签页容器

如果需要使用JTabbedPane在窗口上创建标签页 ,则可以按如下步骤进行:

  1. 创建JTabbedPane对象
 JTabbedPane(int tabPlacement, int tabLayoutPolicy):tabPlacement:指定标签标题的放置位置,可以选择 SwingConstants中的四个常量:TOP、LEFT、BOTTOM、RIGHTtabLaoutPolicy:指定当窗口不能容纳标签页标题时的布局策略,可以选择JTabbedPane.WRAP_TAB_LAYOUT和JTabbedPane.SCROLL_TAB_LAYOUT
  1. 通过JTabbedPane对象堆标签进行增删改查
addTab(String title, Icon icon, Component component, String tip):添加标签title:标签的名称icon:标签的图标component:标签对应的组件tip:光标放到标签上的提示insertTab(String title, Icon icon, Component component, String tip, int index):插入标签页title:标签的名称icon:标签的图标component:标签对应的组件tip:光标放到标签上的提示index:在哪个索引处插入标签页
setComponentAt(int index, Component component):修改标签页对应的组件index:修改哪个索引处的标签component:标签对应的组件
removeTabAt(int index):index:删除哪个索引处的标签
  1. 设置当前显示的标签页
setSelectedIndex(int index):设置哪个索引处的标签被选中
  1. 设置JTabbedPane的其他属性
setDisabledIconAt(int index, Icon disabledIcon): 将指定位置的禁用图标设置为 icon,该图标也可以是null表示不使用禁用图标。
setEnabledAt(int index, boolean enabled): 设置指定位置的标签页是否启用。
setTitleAt(int index, String title): 设置指定位置标签页的标题为 title,该title可以是null,这表明设置该标签页的标题为空。
setToolTipTextAt(int index, String toolTipText): 设置指定位置标签页的提示文本 。
  1. 为JTabbedPane设置监听器
addChangeListener(ChangeListener l)

案例:

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;public class TabbedPanel {JFrame frame = new JFrame("JTabbedPane 标签页容器");//参数:(标签页位置,标签页滚动)JTabbedPane jTabbedPane = new JTabbedPane(JTabbedPane.LEFT,JTabbedPane.SCROLL_TAB_LAYOUT);private void init(){//jTabbedPane容器添加标签//参数:(标签显示的文字,图标,该标签对应的组件,提示信息)jTabbedPane.addTab("用户管理",null,null,"您没有权限");jTabbedPane.addTab("商品管理",new ImageIcon("./img/container/open.gif"),new JList<String>(new String[]{"用户一","用户二","用户三"}),"商品管理");jTabbedPane.addTab("商品管理",null,new JList<String>(new String[]{"订单一","订单二","订单三"}),"订单管理");//默认选中指定索引的标签jTabbedPane.setSelectedIndex(1);//设置指定索引的标签禁用jTabbedPane.setEnabledAt(0,false);//如果标签禁用,则添加指定的图标jTabbedPane.setDisabledIconAt(0,new ImageIcon(".\\img\\component\\exit.png"));//设置指定索引的标签的标题(初始化标签时可以设置)jTabbedPane.setTitleAt(1,"商品管理标题");//设置指定索引的标签的提示信息(初始化时可以设置)jTabbedPane.setToolTipTextAt(2,"订单管理的提示文本");//标签选择改变时jTabbedPane.addChangeListener(new ChangeListener() {@Overridepublic void stateChanged(ChangeEvent e) {int selectedIndex = jTabbedPane.getSelectedIndex();JOptionPane.showMessageDialog(jTabbedPane,"点击了第 "+(selectedIndex + 1)+ "标签");}});frame.setBounds(200,200,400,400);frame.add(jTabbedPane);frame.setVisible(true);}public static void main(String[] args) {new TabbedPanel().init();}
}

3. 进度条

3.1 JProcessBar

使用JProgressBar创建进度条的步骤:

  1. 创建JProgressBar对象
public JProgressBar(int orient, int min, int max):orint:方向min:最小值max:最大值
  1. 设置属性
setBorderPainted(boolean b):设置进度条是否有边框
setIndeterminate(boolean newValue):设置当前进度条是不是进度不确定的进度条,如果是,则将看到一个滑块在进度条中左右移动
setStringPainted(boolean b):设置进度条是否显示当前完成的百分比
  1. 获取和设置当前进度条的进度状态
setValue(int n):设置当前进度值
double getPercentComplete():获取进度条的完成百分比
String  getStrin():返回进度字符串的当前值

3.1.1 Model模型


Swing 组件大都将外观显示和 内部数据分离 , JProgressBar 也不例外, JProgressBar 组件有一个内置的用于保存其状态数据的Model对象 , 这个对象由BoundedRangeModel对象表示,程序调用JProgressBar对象的方法完成进度百分比的设置,监听进度条的数据变化,其实都是通过它内置的BoundedRangeModel对象完成的。下面的代码是对之前代码的改进,通过BoundedRangeModel完成数据的设置,获取与监听。

//获取进度条数据模型对象:ModelBoundedRangeModel model = jProgressBar.getModel();//通过Model对象来操作
model.setValue(progressThread.getCurrent());
model.getMaximum()

案例:

  1. 创建子线程
  2. JCheckBox的使用和监听
  3. Timer定时器
  4. 子线程中的变量如何被访问

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class ProgressBar {JFrame jFrame = new JFrame();JCheckBox progressBox = new JCheckBox("不确定进度");JCheckBox borderBox = new JCheckBox("不绘制边框");Box verticalBox = Box.createVerticalBox();//创建进度条,参数:(进度条的方向,最大值,最小值)JProgressBar jProgressBar = new JProgressBar(JProgressBar.HORIZONTAL, 0, 100);//获取数据模型对象:ModelBoundedRangeModel model = jProgressBar.getModel();private void init() {//选择框组件progressBox.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {boolean selected = progressBox.isSelected();//进度条是不是不确定进度的进度条jProgressBar.setIndeterminate(selected)}});borderBox.addActionListener(e -> {boolean selected = borderBox.isSelected();//进度条时候有边框jProgressBar.setBorderPainted(!selected);});//进度条显示百分比jProgressBar.setStringPainted(true);//创建线程对象progressThread progressThread = new progressThread(jProgressBar.getMaximum());//创建线程,并运行new Thread(progressThread).start();//设置定时器,间隔读取线程中current,设置进度条的当前进度Timer timer = new Timer(300, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//                jProgressBar.setValue(progressThread.getCurrent());//model对象model.setValue(progressThread.getCurrent());System.out.println(progressThread.getCurrent());}});timer.start();//监听进度条的变化,当前进度>最大进度时,停止计时器jProgressBar.addChangeListener(new ChangeListener() {@Overridepublic void stateChanged(ChangeEvent e) {//                if (jProgressBar.getMaximum() <= progressThread.getCurrent()) {//model对象if (model.getMaximum() <= progressThread.getCurrent()) {timer.stop();System.out.println("计时器停止");}}});verticalBox.add(progressBox);verticalBox.add(borderBox);jFrame.setLayout(new FlowLayout());jFrame.add(verticalBox);jFrame.add(jProgressBar);jFrame.pack();jFrame.setVisible(true)}//线程任务public class progressThread extends Thread {//进度条最大值private int amount;//当前进度值//volatile关键字,内存可见,能保证该变量可以被别的线程访问private volatile int current = 0public progressThread(int amount) {this.amount = amount;}public int getCurrent() {return current;}@Overridepublic void run() {while (amount > current) {try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}current++;}}}public static void main(String[] args) {new ProgressBar().init();}
}

3.2 进度条提示框

不依赖于窗口,可单独显示
点击提示框的取消按钮: ProgressMonitor.isCanceled()

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class ProgressMonitorTest {//参数(父窗口,提示信息,提示信息,最小值,最大值)ProgressMonitor progressMonitor = new ProgressMonitor(null, "请等待任务完成","现在进度:",0,100);//模拟下载的子线程ProgressThread progressThread = new ProgressThread(100);//定时器Timer timer = new Timer(200, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//设置当前进度条的进度progressMonitor.setProgress(progressThread.getCurrent());//点击对话框的取消按钮if (progressMonitor.isCanceled()){timer.stop();//中断进程progressThread.interrupt();}}});public static void main(String[] args) {ProgressMonitorTest progressMonitorTest = new ProgressMonitorTest();progressMonitorTest.progressThread.start();progressMonitorTest.timer.start();}
}

4. JList、JComboBox实现列表框

4.1 简单列表框

使用JList或JComboBox实现简单列表框的步骤:

  1. 创建JList或JComboBox对象
JList(final E[] listData):创建JList对象,把listData数组中的每项内容转换成一个列表项展示
JList(final Vector<? extends E> listData):创建JList对象,把listData数组中的每项内容转换成一个列表项展示
JComboBox(E[] items):
JComboBox(Vector<E> items):
  1. 设置JList或JComboBox的外观行为
---------------------------JList----------------------------------------------
addSelectionInterval(int anchor, int lead):在已经选中列表项的基础上,增加选中从anchor到lead索引范围内的所有列表项
setFixedCellHeight(int height)/setFixedCellWidth(int width):设置列表项的高度和宽度
setLayoutOrientation(int layoutOrientation):设置列表框的布局方向
setSelectedIndex(int index):设置默认选中项
setSelectedIndices(int[] indices):设置默认选中的多个列表项
setSelectedValue(Object anObject,boolean shouldScroll):设置默认选中项,并滚动到该项显示
setSelectionBackground(Color selectionBackground):设置选中项的背景颜色
setSelectionForeground(Color selectionForeground):设置选中项的前景色
setSelectionInterval(int anchor, int lead):设置从anchor到lead范围内的所有列表项被选中
setSelectionMode(int selectionMode):设置选中模式,默认没有限制,也可以设置为单选或者区域选中
setVisibleRowCount(int visibleRowCount):设置列表框的可是高度足以显示多少行列表项
---------------------------JComboBox----------------------------------------------
setEditable(boolean aFlag):设置是否可以直接修改列表文本框的值,默认为不可以
setMaximumRowCount(int count):设置列表框的可是高度足以显示多少行列表项
setSelectedIndex(int anIndex):设置默认选中项
setSelectedItem(Object anObject):根据列表项的值,设置默认选中项
  1. 设置监听器,监听列表项的变化,JList通过addListSelectionListener完成,JComboBox通过addItemListener完成

案例:

用方法来创建按钮
Box创建的容器,内部组件会填充整个容器。
JPanel创建的容器,内部组件不会填充整个容器。

import javax.swing.*;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import java.awt.*;public class ListText1 {JFrame jFrame = new JFrame("列表框测试");String[] books = {"java自学宝典", "轻量级javaEE企业应用实战", "Android基础教程", "jQuery实战教程", "SpringBoot企业级开发"};Box vBox = Box.createVerticalBox();Box hBox = Box.createHorizontalBox();JPanel jPanelLeft1 = new JPanel();JPanel jPanelLeft2 = new JPanel();JPanel jPanelRight = new JPanel();ButtonGroup buttonGroup1 = new ButtonGroup();ButtonGroup buttonGroup2 = new ButtonGroup();JList<String> list = new JList<>(books);JComboBox comboBox = new JComboBox<>(books);JTextArea textArea = new JTextArea();//用方法创建单选按钮和选择事件private void addBtnPanelLeft1(String name, int orientation) {JRadioButton jRadioButton = new JRadioButton(name);buttonGroup1.add(jRadioButton);jPanelLeft1.add(jRadioButton);// 当组中只有一个组件时,设置为默认选中if (buttonGroup1.getButtonCount() == 1) {jRadioButton.setSelected(true);}jRadioButton.addActionListener(e -> {list.setLayoutOrientation(orientation);});}//用方法创建单选按钮private void addBtnPanelLeft2(String name, int select) {JRadioButton jRadioButton = new JRadioButton(name);buttonGroup2.add(jRadioButton);jPanelLeft2.add(jRadioButton);if (buttonGroup2.getButtonCount() == 1) {jRadioButton.setSelected(true);}jRadioButton.addActionListener(e -> {list.setSelectionMode(select);});}private void init() {// 列表选择框显示3项list.setVisibleRowCount(3);// 列表选择框,默认2-4选中list.setSelectionInterval(2, 4);// 选中项的背景色list.setSelectionBackground(Color.cyan);// 选中项的字体颜色list.setSelectionForeground(Color.red);//设置边框,参数:(创建标题边框匿名对象(作用:线条比较深,标题))jPanelLeft1.setBorder(new TitledBorder(new EtchedBorder(), "确定选项布局"));addBtnPanelLeft1("纵向滚动", JList.VERTICAL);addBtnPanelLeft1("纵向换行", JList.VERTICAL_WRAP);addBtnPanelLeft1("横向换行", JList.HORIZONTAL_WRAP);//jPanelLeft2.setBorder(new TitledBorder(new EtchedBorder(), "确定选择模式"));addBtnPanelLeft2("单选", ListSelectionModel.SINGLE_SELECTION);addBtnPanelLeft2("单范围", ListSelectionModel.SINGLE_INTERVAL_SELECTION);addBtnPanelLeft2("无限制", ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);// JList选择框的事件list.addListSelectionListener(e -> {textArea.setText("");for (String s : list.getSelectedValuesList()) {textArea.append(s+"\n");}});// 下拉选择框// 下拉框中显示多少行comboBox.setMaximumRowCount(3);// 是否可以直接修改文本框里的值comboBox.setEditable(true);// 下拉选择框选择事件comboBox.addItemListener(e -> {int selectedIndex = comboBox.getSelectedIndex();textArea.setText(books[selectedIndex]);});//文本框textArea.setBorder(new TitledBorder(new EtchedBorder(),"最喜欢的图书"));textArea.setRows(4);jPanelRight.setBorder(new TitledBorder(new EtchedBorder(),"下拉"));vBox.add(new JScrollPane(list));vBox.add(jPanelLeft1);vBox.add(jPanelLeft2);jPanelRight.add(comboBox);hBox.add(vBox);hBox.add(jPanelRight);jFrame.add(hBox);jFrame.add(textArea,BorderLayout.SOUTH);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new ListText1().init();}
}

4.2 不强制存储列表项的ListModel和ComboBoxModel

与JProgressBar一样,JList和JComboBox也采用了MVC的设计模式,JList和JComboBox只负责外观的显示,而组件底层的状态数据则由对应的Model来维护。JList对应的Model是ListModel接口,JComboBox对应的Model是ComboBox接口,其代码如下:

public interface ListModel<E>{int getSize();E getElementAt(int index);void addListDataListener(ListDataListener l);void removeListDataListener(ListDataListener l);
}public interface ComboBoxModel<E> extends ListModel<E> {void setSelectedItem(Object anItem);Object getSelectedItem();
}

从上面接口来看,这个 ListMode l 不管 JList 里的所有列表项的存储形式,它甚至不强制存储所有的列表项,只要 ListModel的实现类提供了getSize()和 getElementAt()两个方法 , JList 就可以根据该ListModel 对象来生成列表框 。ComboBoxModel 继承了 ListModel ,它添加了"选择项"的概念,选择项代表 JComboBox 显示区域内可见的列表项 。

在使用JList和JComboBox时,除了可以使用jdk提供的Model实现类,程序员自己也可以根据需求,自己定义Model的实现类,实现对应的方法使用。

4.3 强制存储列表项的DefaultListModel和DefaultComboBoxModel

前面只是介绍了如何创建 JList 、 JComboBox 对象, 当 调用 JList 和 JComboBox构造方法时时传入数组或 Vector 作为参数,这些数组元素或集合元素将会作为列表项。当使用JList 或 JComboBox 时 常常还需要动态地增加、删除列表项,例如JCombox提供了下列方法完成增删操作:

addItem(E item):添加一个列表项
insertItemAt(E item, int index):向指定索引处插入一个列表项
removeAllItems():删除所有列表项
removeItem(Object anObject):删除指定列表项
removeItemAt(int anIndex):删除指定索引处的列表项

JList 并没有提供这些类似的方法。如果需要创建一个可以增加、删除列表项的 JList 对象,则应该在创建 JLi st 时显式使用 DefaultListModel作为构造参数 。因为 DefaultListModel 作为 JList 的 Model,它负责维护 JList 组件的所有列表数据,所以可以通过向 DefaultListModel 中添加、删除元素来实现向 JList 对象中增加 、删除列表项 。DefaultListModel 提供了如下几个方法来添加、删除元素:

add(int index, E element): 在该 ListModel 的指定位置处插入指定元素 。
addElement(E obj): 将指定元素添加到该 ListModel 的末尾 。
insertElementAt(E obj, int index): 在该 ListModel 的指定位置处插入指定元素 。
Object remove(int index): 删除该 ListModel 中指定位置处的元素
removeAllElements(): 删 除该 ListModel 中的所有元素,并将其的大小设置为零 。
removeElement(E obj): 删除该 ListModel 中第一个与参数匹配的元素。
removeElementAt(int index): 删除该 ListModel 中指定索引处的元素 。
removeRange(int 企omIndex , int toIndex): 删除该 ListModel 中指定范围内的所有元素。
set(int index, E element) : 将该 ListModel 指定索引处的元素替换成指定元素。
setElementAt(E obj, int index): 将该 ListModel 指定索引处的元素替换成指定元素。

案例:

通过DefaultListModel操作JList中的元素

import javax.swing.*;
import java.awt.*;public class DefaultListModeTest {JFrame jFrame = new JFrame("强制存储列表项");JList<String> jList;JPanel jPanel = new JPanel();JTextField jTextField = new JTextField(30);JButton addButton = new JButton("增加图书");JButton delButton = new JButton("删除选中图书");//1. 创建DefaultListModel的对象DefaultListModel<String> bookModel = new DefaultListModel<>();public DefaultListModeTest() {// 2. 用Model构造JListjList = new JList<String>(bookModel);}public void init(){//3. Model添加数据bookModel.addElement("第一本书");bookModel.addElement("第二本书");bookModel.addElement("第三本书");bookModel.addElement("第四本书");bookModel.addElement("第五本书");bookModel.addElement("第六本书");jList.setVisibleRowCount(4);addButton.addActionListener(e -> {//Model添加元素bookModel.addElement(jTextField.getText());});delButton.addActionListener(e -> {int selectedIndex = jList.getSelectedIndex();if ( selectedIndex != -1) {// Model删除元素bookModel.removeElementAt(selectedIndex);}});jPanel.add(jTextField);jPanel.add(addButton);jPanel.add(delButton);jFrame.add(new JScrollPane(jList));jFrame.add(jPanel, BorderLayout.SOUTH);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new DefaultListModeTest().init();}
}

4.4 使用ListCellRenderer绘制列表项的外观

  1. 创建ListCellRenderer 的实现类ImageCellRenderer。
  2. 设置JList使用ImageCellRenderer作为列表项绘制器 List.setCellRenderer(new ImageCellRenderer());
  3. 在类方法public Component getListCellRendererComponent中绘制列表项的内容,然会返回,返回值是容器

JPanel容器内组件默认居中排列
Box容器内组件默认靠左排列

  • 类方法:
public interface ListCellRenderer<E>
{Component getListCellRendererComponent(JList<? extends E> list,//列表组件E value,//当前列表项的值int index,//当前列表项的索引boolean isSelected,//当前列表项是否被选中boolean cellHasFocus);//当前列表项是否获取了焦点
}

package listBox;import javax.swing.*;
import java.awt.*;public class ListCellRendererTest {private JFrame jFrame = new JFrame("好友列表");private String[] friends = {"李清照","苏格拉底","李白","弄玉","虎头"};//定义一个JList对象JList friendsList = new JList(friends);public void init() {//设置JList使用ImageCellRenderer作为列表项绘制器friendsList.setCellRenderer(new ImageCellRenderer());jFrame.add(new JScrollPane(friendsList));jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new ListCellRendererTest().init();}class ImageCellRenderer implements ListCellRenderer {private ImageIcon icon;private String name;//定义绘制单元格的背景色private Color background;//定义绘制单元格的前景色private Color foreground@Overridepublic Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {//容器各种套娃,为的就是把图片和文字垂直居中,每次返回的只是一组头像和文字,有多少组就返回多少次this.icon = new ImageIcon("./img/list/"+value+".gif");this.name = value.toString();this.background = isSelected ? list.getSelectionBackground() : list.getBackground();this.foreground = isSelected ? list.getSelectionForeground() : list.getForeground();Box vBox = Box.createVerticalBox();JPanel jPanel1 = new JPanel();JPanel jPanel2 = new JPanel();JLabel jLabel1 = new JLabel(this.icon);JLabel jLabel2 = new JLabel(this.name);jPanel1.setBackground(this.background);jPanel2.setBackground(this.background);jPanel1.add(jLabel1);jPanel2.add(jLabel2);vBox.add(jPanel1);vBox.add(jPanel2);//返回当前vBox对象,作为列表项绘制器return vBox;}}
}

5. JTree、TreeModel实现树

5.1 创建简单的树

5.1.1 JTree常用构造方法

JTree(TreeModel newModel):使用指定 的数据模型创建 JTree 对象,它默认显示根结点。
JTree(TreeNode root): 使用 root 作为根节 点创建 JTree 对象,它默认显示根结点 。
JTree(TreeNode root, boolean asksAllowsChildren):
使用root作为根结点创建JTree对象,它默认显示根结点。
asksAllowsChildren 参数控制怎样的结点才算叶子结点,如果该参数为 true ,则只有当程序使用 setAllowsChildren(false)显式设置某个结点不允许添加子结点时(以后也不会拥有子结点) ,该结点才会被 JTree当成叶子结点:如果该参数为 false ,则只要某个结点当时没有子结点(不管以后是否拥有子结点) ,该结点都会被 JTree 当成叶子结点。

5.1.2 TreeNode继承体系及使用

  1. 创建出所有节点:DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");
  2. 将子节点依次添加到父节点:root.add(guangdong);
  3. 为根节点创建JTree对象:jTree = new JTree(root);

package tree;import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;public class SimpleJTree {JFrame jFrame = new JFrame("简单树的演示");JTree jTree ;private void init(){//创建所有节点DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");//给父节点添加子节点root.add(guangdong);root.add(guangxi);guangdong.add(foshan);guangdong.add(shantou);guangxi.add(guilin);guangxi.add(nanning);//为根节点创建TreejTree = new JTree(root);//      设置外观
//        jTree.putClientProperty( "JTree.lineStyle", "None");
//        jTree .putClientProperty("JTree.lineStyle" , "Horizontal");
//        jTree .setShowsRootHandles(true);jTree .setRootVisible(false);jFrame.add(jTree);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new SimpleJTree().init();}
}

5.1.3 外观

设置结点之间没有连接线

jTree .putClientProperty( "JTree.lineStyle", "None");

设置结点之间只有水平分割线

 jTree .putClientProperty("JTree.lineStyle" , "Horizontal");

设置根结点有"展开、折叠"图标

jTree .setShowsRootHandles(true);

隐藏根结点

jTree .setRootVisible(false);

5.1.4 JTree的基本方法

Enumeration breadthFirstEnumerationO/preorderEnumeration(): 按广度优先的顺序遍历以此结点为根的子树,并返回所有结点组成的枚举对象 。
Enumeration depthFirstEnumerationO/postorderEnumeration(): 按深度优先的顺序遍历以此结点为根的子树,并返回所有结点组成的枚举对象 。
DefaultMutableTreeNode getNextSibling(): 返回此结点的下一个兄弟结点 。
TreeNode getParent(): 返回此结点的父结点 。 如果此结点没有父结点,则返回null 。
TreeNode[] getPath(): 返回从根结点到达此结点的所有结点组成的数组。
DefaultMutableTreeNode getPreviousSibling(): 返回此结点的上一个兄弟结点。
TreeNode getRoot(): 返回包含此结点的树的根结点 。
TreeNode getSharedAncestor(DefaultMutableTreeNode aNode): 返回此结点和aNode最近的共同祖先 。
int getSiblingCount(): 返回此结点的兄弟结点数 。
boolean isLeaf(): 返回该结点是否是叶子结点 。
boolean isNodeAncestor(TreeNode anotherNode): 判断anotherNode是否是当前结点的祖先结点(包括父结点) 。
boolean isNodeChild(TreeNode aNode): 如果aNode是此结点的子结点,则返回true。
boolean isNodeDescendant(DefaultMutableTreeNode anotherNode): 如果 anotherNode 是此结点的后代,包括是此结点本身、此结点的子结点或此结点的子结点的后代,都将返回true 。
boolean isNodeRelated(DefaultMutableTreeNode aNode) : 当aNode和当前结点位于同一棵树中时返回 true 。
boolean isNodeSibling(TreeNode anotherNode): 返回anotherNode是否是当前结点的兄弟结点 。
boolean isRoot(): 返回当前结点是否是根结点 。
Enumeration pathFromAncestorEnumeration(TreeNode ancestor): 返回从指定祖先结点到当前结点的所有结点组成的枚举对象 。

5.2 编辑树的结点

5.2.1 编辑树的结点

  • 树的结点默认是不可编辑的,设置编辑:JTree.setEditable(boolean b)

编辑树结点的步骤:

  1. 获取当前被选中的结点

获取当前被选中的结点,会有两种方式:

  1. 首先通过JTree对象的某些方法,例如 TreePath selectionPath = JTree.getSelectionPath();等,得到一个TreePath对象selectionPath,包含了从根结点到当前结点的路径,然后调用TreePath对象selectionPath.getLastPathComponent()方法,得到当前选中结点。
  2. 调用JTree对象的 Object getLastSelectedPathComponent() 方法获取当前被选中的结点
  1. 调用DefaultTreeModel数据模型有关增删改的一系列方法完成编辑,方法执行完后,会自动重绘JTree。
  • 下面程序中使用到的方法:

获得JTree的数据模型ModelDefaultTreeModel model = (DefaultTreeModel) JTree.getModel();

  1. 寻找当前结点的父结点: TreeNode parent = 当前结点.getParent();
  2. 获得当前结点在父结点中的索引:int index = 父结点.getIndex(当前结点);
  3. 在索引前插入结点:model .insertNodeInto(在索引前要插入的结点, 父结点, 父结点的索引);
  4. 当前结点到根结点的结点集合:TreeNode[] pathToRoot = model.getPathToRoot(当前结点);
  5. 根据结点集合找到路径:TreePath treePath = new TreePath(pathToRoot);
  6. 获得当前结点的子节点数:int index = 当前结点.getChildCount();
  7. 删除当前结点:model .removeNodeFromParent(当前结点);
  8. 当前结点可编辑:树.startEditingAtPath(要编辑结点的路径);

package tree;import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;public class EditSimpleJTree {JFrame jFrame = new JFrame("可编辑树");Box vBox = Box.createHorizontalBox();JTree jTree;DefaultTreeModel model;JButton addBrotherButton = new JButton("添加兄弟结点");JButton addChildButton = new JButton("添加子结点");JButton delButton = new JButton("删除结点");JButton editButton = new JButton("编辑结点");private void init() {//创建所有节点DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");//给父节点添加子节点root.add(guangdong);root.add(guangxi);guangdong.add(foshan);guangdong.add(shantou);guangxi.add(guilin);guangxi.add(nanning);//为根节点创建TreejTree = new JTree(root);//树可编辑jTree.setEditable(true);//获取jTree对象的数据模型对象model = (DefaultTreeModel) jTree.getModel();//添加兄弟结点,必须要找到父结点addBrotherButton.addActionListener(e -> {//1. 获取当前选中结点DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();if (selectNode == null) return;//2. 找到选中结点的父结点DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectNode.getParent();if (parent == null) return;//3. 创建一个新结点DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新结点");//4. 在当前选中结点之前添加新结点int index = parent.getIndex(selectNode);//获取当前结点的在父节点的索引model.insertNodeInto(newNode, parent, index);//在索引前插入新结点,参数:(新节点,父结点,索引)//5. 在窗口中展示新添加的结点TreeNode[] pathToRoot = model.getPathToRoot(newNode);//新结点到根结点的路径,返回路径上所有结点的组成的数组TreePath treePath = new TreePath(pathToRoot);//根据结点数组找到路径jTree.scrollPathToVisible(treePath);//滚动到这个路径,在窗口展示//6. 重绘jTree
//            jTree.updateUI();//使用model方法,不需要手动刷新UI});//添加子结点addChildButton.addActionListener(e -> {//1. 获取当前选中结点DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();if (selectNode == null) return;//2. 创建一个新结点DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("子结点");//3. 在当前选中结点的子节点的最后添加结点int index = selectNode.getChildCount();//获取当前结点子结点的数量model.insertNodeInto(newNode, selectNode, index);//在索引前插入新结点,参数:(新节点,父结点,索引)//5. 在窗口中展示新添加的结点TreeNode[] pathToRoot = model.getPathToRoot(newNode);//新结点到根结点的路径,返回路径上所有结点的组成的数组TreePath treePath = new TreePath(pathToRoot);//根据结点数组找到路径System.out.println("结点的路径:"+treePath);jTree.scrollPathToVisible(treePath);//滚动到这个路径,在窗口展示//6. 重绘jTree
//            jTree.updateUI();//使用model方法,不需要手动刷新UI});//删除选中结点delButton.addActionListener(e -> {//1. 获取当前选中结点DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();//选中的结点是根结点、有子结点则不能删除if (selectNode == null || selectNode.isRoot() || selectNode.getChildCount() > 0) return;// 2. 删除结点(要从父结点删除)model.removeNodeFromParent(selectNode);});//编辑结点editButton.addActionListener(e -> {//1. 获取当前选中结点的路径TreePath selectionPath = jTree.getSelectionPath();if (selectionPath != null){jTree.startEditingAtPath(selectionPath);}});vBox.add(addBrotherButton);vBox.add(addChildButton);vBox.add(delButton);vBox.add(editButton);jFrame.add(new JScrollPane(jTree));jFrame.add(vBox,BorderLayout.SOUTH);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new EditSimpleJTree().init();}
}

5.2.1拖动树的结点

  • 知识点:
  1. boolean isOrNo= APath.isDescendant(BPath);BPath路径的结点是不是APath路径结点的后代;
  2. 移动时,先删除原路径的结点,再向新位置添加结点。
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;public class MoveJTree {JFrame jFrame = new JFrame("简单树的演示");JTree jTree;DefaultTreeModel model;private void init() {//创建所有节点DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");//给父节点添加子节点root.add(guangdong);root.add(guangxi);guangdong.add(foshan);guangdong.add(shantou);guangxi.add(guilin);guangxi.add(nanning);//为根节点创建TreejTree = new JTree(root);//可编辑jTree.setEditable(true);//获取model模型model = (DefaultTreeModel) jTree.getModel();jTree.addMouseListener(new moveNodeListener(jTree, model));jFrame.add(new JScrollPane(jTree));jFrame.pack();jFrame.setVisible(true);}//拖动结点到另一结点中,此类可复用public static class moveNodeListener extends MouseAdapter {DefaultTreeModel model;TreePath movePath;JTree jTree;public moveNodeListener(JTree jTree, DefaultTreeModel model){this.jTree = jTree;this.model = model;}//当鼠标按下时,由坐标取得结点的路径@Overridepublic void mousePressed(MouseEvent e) {//获得鼠标按下时的结点路径TreePath pathForLocation = jTree.getPathForLocation(e.getX(), e.getY());if (pathForLocation != null) movePath = pathForLocation;}//当鼠标抬起时,将结点放入@Overridepublic void mouseReleased(MouseEvent e) {//获得鼠标抬起时的结点路径TreePath pathForLocation = jTree.getPathForLocation(e.getX(), e.getY());//不能移动到自己的后代中(pathForLocation是movePath的后代)if (pathForLocation == null || movePath == null || movePath.isDescendant(pathForLocation)) return;//鼠标按下时的结点DefaultMutableTreeNode pressedComponent = (DefaultMutableTreeNode) movePath.getLastPathComponent();//根据路径获得鼠标抬起时结点DefaultMutableTreeNode releasedComponent = (DefaultMutableTreeNode) pathForLocation.getLastPathComponent();//根据路径删除原来的结点model.removeNodeFromParent(pressedComponent);int index = releasedComponent.getChildCount();//插入到抬起时结点的子节点中model.insertNodeInto(pressedComponent, releasedComponent, index);//展示TreeNode[] pathToRoot = model.getPathToRoot(pressedComponent);TreePath treePath = new TreePath(pathToRoot);//根据结点数组找到路径jTree.scrollPathToVisible(treePath);//滚动到这个路径,在窗口展示
//                jTree.updateUI();}}public static void main(String[] args) {new MoveJTree().init();}
}

5.2.2 监听结点事件

修改JTree的选择模式:

  1. 获得用于保存JTree选中状态的Model对象:jTree.getSelectionModel();
  2. 通过Model对象的setSelectionMode(int mode);方法修改JTree的选择模式。
    Model的模式有以下3种:
    TreeSelectionModel.CONTIGUOUS_TREE_SELECTION: 可 以连续选中多个 TreePath 。
    TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION : 该选项对于选择没有任何限制 。
    TreeSelectionModel.SINGLE_TREE_SELECTION: 每次只能选择一个 TreePath 。
  3. 默认是无限制模式

为JTree添加监听器:

  1. addTreeExpansionListener(TreeExpansionListener tel) : 添加树节点展开/折叠事件的监听器。
  2. addTreeSelectionListener(TreeSelectionListener tsl) : 添加树节点选择事件的监听器。
package tree;import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;public class ListenerModel {JFrame jFrame = new JFrame("监听结点事件");JTree jTree ;Box hBox = Box.createHorizontalBox();JTextArea jTextArea = new JTextArea(10,20);private void init(){//创建所有节点DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");//给父节点添加子节点root.add(guangdong);root.add(guangxi);guangdong.add(foshan);guangdong.add(shantou);guangxi.add(guilin);guangxi.add(nanning);//为根节点创建TreejTree = new JTree(root);//创建TreeSelectionModel selectionModel = jTree.getSelectionModel();//设置单选模式selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);//监听点击的结点发生改变jTree.addTreeSelectionListener(new TreeSelectionListener() {@Overridepublic void valueChanged(TreeSelectionEvent e) {if (e.getOldLeadSelectionPath()!=null)jTextArea.append("上一次的选择:"+e.getOldLeadSelectionPath().toString()+"\n");jTextArea.append("当前的选择:"+e.getNewLeadSelectionPath().toString()+"\n");}});//监听结点展开/折叠事件jTree.addTreeExpansionListener(new TreeExpansionListener() {@Override//结点展开时调用public void treeExpanded(TreeExpansionEvent event) {jTextArea.append("结点被展开:"+event.getPath().toString()+"\n");}//结点折叠时调用@Overridepublic void treeCollapsed(TreeExpansionEvent event) {jTextArea.append("结点被折叠:"+event.getPath().toString()+"\n");}});hBox.add(new JScrollPane(jTree));hBox.add(new JScrollPane(jTextArea));jFrame.add(hBox);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new ListenerModel().init();}
}

5.3 扩展DefaultTreeCellRenderer改变结点外观

  1. 创建结点对象new DefaultMutableTreeNode(obj);时,DefaultMutableTreeNode类的构造函数会将参数obj赋值给对象的userObject属性。
  2. 结点在窗体显示时,会调用DefaultTreeCellRenderer类对象的getTreeCellRendererComponent()方法绘制
  3. getTreeCellRendererComponent()方法中的参数value就是结点对象
  4. Object类型的value,通过类型的强制转换,转换为DefaultMutableTreeNode类型:DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
  5. node.getUserObject();方法,把结点对象中第一步传入的参数取出,并强制转换为自己定义的数据类型
  6. 至此就可以通过创建结点对象时传入的参数来重绘结点的组件
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;public class ExtendsDefaultCellTreeRenderer {JFrame jf = new JFrame("根据结点类型定义图标");JTree jTree;ImageIcon rootIcon = new ImageIcon("./img/tree/root.gif");ImageIcon databaseIcon = new ImageIcon("img\\tree\\database.gif");ImageIcon tableIcon = new ImageIcon("img\\tree\\table.gif");ImageIcon columnIcon = new ImageIcon("img\\tree\\column.gif");ImageIcon indexIcon = new ImageIcon("img\\tree\\index.gif");//定义几个初始结点DefaultMutableTreeNode root = new DefaultMutableTreeNode(new NodeData(rootIcon, "数据库导航"));DefaultMutableTreeNode salaryDb = new DefaultMutableTreeNode(new NodeData(databaseIcon, "公司工资数据库"));DefaultMutableTreeNode customerDb = new DefaultMutableTreeNode(new NodeData(databaseIcon, "公司客户数据库"));DefaultMutableTreeNode employee = new DefaultMutableTreeNode(new NodeData(tableIcon, "员工表"));DefaultMutableTreeNode attend = new DefaultMutableTreeNode(new NodeData(tableIcon, "考勤表"));DefaultMutableTreeNode concat = new DefaultMutableTreeNode(new NodeData(tableIcon, "联系方式表"));DefaultMutableTreeNode id = new DefaultMutableTreeNode(new NodeData(indexIcon, "员工ID"));DefaultMutableTreeNode name = new DefaultMutableTreeNode(new NodeData(columnIcon, "姓名"));DefaultMutableTreeNode gender = new DefaultMutableTreeNode(new NodeData(columnIcon, "性别"));public void init() {//通过结点的add方法,建立结点的父子关系root.add(salaryDb);root.add(customerDb);salaryDb.add(employee);salaryDb.add(attend);customerDb.add(concat);concat.add(id);concat.add(name);concat.add(gender);jTree = new JTree(root);//重绘结点jTree.setCellRenderer(new MyRenderer());
/*        //设置使用windows外观风格try {UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");} catch (Exception e) {e.printStackTrace();}//更新JTree的UI外观SwingUtilities.updateComponentTreeUI(jTree);*/jf.add(new JScrollPane(jTree));jf.pack();jf.setVisible(true);}public static void main(String[] args) {new ExtendsDefaultCellTreeRenderer().init();}//结点的外观class NodeData {ImageIcon image;String name;public NodeData(ImageIcon image,String name){this.image = image;this.name = name;}@Overridepublic String toString() {return "NodeData{" +"image=" + image +", name='" + name + '\'' +'}';}}//重绘结点组件class MyRenderer extends DefaultTreeCellRenderer{@Overridepublic Component getTreeCellRendererComponent(JTree tree, Object value,boolean sel,boolean expanded,boolean leaf, int row,boolean hasFocus){DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;NodeData nodeData = (NodeData)node.getUserObject();System.out.println(nodeData);this.setIcon(nodeData.image);this.setText(nodeData.name);return this;}}
}

6. JTable、JTableModel实现表格

6.1 JTable实现简单表格

  1. 创建一个一维数组存放标题行。
  2. 创建一个二维数组存放表格数据。
  3. 创建JTable的对象,并将上述的两个数组作为参数传入

package table;import javax.swing.*;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;public class SimpleTable {JFrame jFrame = new JFrame("简单表格");JTable jTable;//定义二维数组作为表格数据Object[][] tableData = {new Object[]{"李清照",29,"女"},new Object[]{"苏格拉底",56,"男"},new Object[]{"李白",35,"男"},new Object[]{"弄玉",18,"女"},new Object[]{"虎头",2,"男"},};//定义一个一维数组,作为列标题Object[] columnTitle = {"姓名","年龄","性别"};private void init(){jTable = new JTable(tableData,columnTitle);//获取jTable的Model模型,修改选择模式ListSelectionModel selectionModel = jTable.getSelectionModel();selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);//单选,只能选择一行selectionModel.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);//多选,必须是连续的行selectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);//无限制//获得列,并设置宽度TableColumn tableColumn0 = jTable.getColumn(columnTitle[0]);tableColumn0.setMaxWidth(60);TableColumn tableColumn2 = jTable.getColumn(columnTitle[2]);tableColumn2.setMinWidth(40);jFrame.add(new JScrollPane(jTable));jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new SimpleTable().init();}
}

6.2 TableModel和监视器

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;public class JTableModel {JFrame jFrame = new JFrame("JTableModel表格");JPanel jPanel = new JPanel();//定义二维数组作为表格数据Object[][] tableData = {new Object[]{"李清照", 29, "女"},new Object[]{"苏格拉底", 56, "男"},new Object[]{"李白", 35, "男"},new Object[]{"弄玉", 18, "女"},new Object[]{"虎头", 2, "男"},};//定义一个一维数组,作为列标题Object[] columnTitle = {"姓名", "年龄", "性别"};JTable jTable = new JTable();//数据必须通过Model来传递DefaultTableModel defaultTableModel = new DefaultTableModel(tableData, columnTitle);JButton addRow = new JButton("增加一行");JButton delRow = new JButton("删除一行");JButton addColum = new JButton("增加一列");private void init() {//设置Model为jTable数据管理jTable.setModel(defaultTableModel);addRow.addActionListener(e -> {// 根据上面定义的数据类型,传入参数defaultTableModel.addRow(new Object[]{"柳岩", "18", "女"});});delRow.addActionListener(e -> {// 获得选中行的行号int selectedRow = jTable.getSelectedRow();if (selectedRow > 0)defaultTableModel.removeRow(selectedRow);});addColum.addActionListener(e -> {defaultTableModel.addColumn("职业");});jPanel.add(addColum);jPanel.add(addRow);jPanel.add(delRow);jFrame.add(new JScrollPane(jTable));jFrame.add(jPanel, BorderLayout.SOUTH);jFrame.pack();jFrame.setVisible(true);}public static void main(String[] args) {new JTableModel().init();}
}

JAVA Swing 图形化界面编程相关推荐

  1. 双人弹球小游戏 (基于Java图形化界面编程)

    用户界面如下 : 玩法:双方玩家可以分别控制A-D键和←-→键来进行各自球拍的位置,如果某方没有接住小球,则对方获胜,游戏结束. 代码如下: import javax.swing.*; import ...

  2. Java图形化界面编程之——AWT

    目录 1.AWT简介 2.AWT继承体系 3.Container容器 3.1.Container继承体系 3.2.常用API 3.2.1.Component的常用方法 3.2.2.Container的 ...

  3. Java图形化界面编程

    Java图形化界面编程(使用AWT) 文章目录  内容概述  容器Container   Window   Panel   ScrollPane   Box  布局管理器   FlowLayout   ...

  4. JAVA之旅(三十一)——JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件

    JAVA之旅(三十一)--JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件 有段时间没有更新JAVA了,我们今天来说一下JAVA中的图形化界面,也就是GUI ...

  5. c语言编程游戏界面,震惊!!!一个关于c语言图形化界面编程的小游戏-Go语言中文社区...

    关于C语言的图形化界面编程 第一个小程序<飞翔的小鸟> 效果图 本人也是小白,大家轻点喷!!!! 下面是源码 作者: @追风 #include #include #include #inc ...

  6. 震惊!!!一个关于c语言图形化界面编程的小游戏

    关于C语言的图形化界面编程 第一个小程序<飞翔的小鸟> 效果图 本人也是小白,大家轻点喷!!!! 下面是源码 作者: @追风#include<graphics.h> #incl ...

  7. Java 图形化界面编程(Swing)入门实例

    本文目录 入门实例 先整一个图形化界面出来 常用布局 流式布局 网格布局 边界布局 边界布局 四个入门实例(附截图) 一个小demo(单词计数) 一个较为完整的demo Java (Swing)文件版 ...

  8. java之图形化界面(GUI)

    一.概述 用户与计算机进行交换的方式有两种: GLI:Command lin User Interface(命令行用户接口),也就是常见的dos窗口,它需要记住一些常用的命令,操作不直观方便. GUI ...

  9. java 高级 图形化界面_java高级图形化界面

    java.awt.event.WindowAdapter 是一个接口 学生的答案: C 标准答案: C 该题分数:4.0 学生得分: 4.0 分 9. 在基于 Swing 的图形用户界面设计中,面板属 ...

最新文章

  1. java 拉姆表达式_Java8 lambda表达式10个示例
  2. 以 OSGi 包的形式开发和部署 Web 服务
  3. ‘ping‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
  4. leetcode 65. 有效数字(正则表达式)
  5. UnrealEngine4-Roadmap
  6. 想象力惊人!只凭一句话,AI就能脑补出动漫小片
  7. git clone指定分支到本地
  8. 如何vista中使用netmeeting
  9. 【转载】Excel中批量填充公式有5个方法
  10. bugzilla dbd-mysql_如何在CentOS 7上安装Bugzilla 5.0.x
  11. Convex Optimization: 3 Convex functions
  12. 58同城数据爬取+可视化分析
  13. Bloom filter 过滤(布隆过滤算法)原理
  14. 键盘上哪个键是ESCAPE键?
  15. c++的继承与派生之从入门到入坟-------集大成者
  16. html 404错误页面模板,50款国外非常有意思的网页404错误页面模板
  17. 大数据思维,到底是什么?
  18. 计算机的服务桌面,比较实用的电脑桌面软件值得入手,个个精选
  19. 乍得“随军”记 ——写在结婚一周年
  20. MySQL——IN的用法详解

热门文章

  1. 2.2 数据管理 之 数据加权
  2. 工业工厂三维可视化设备3D建模展示
  3. 移动终端软件测试基础知识,移动终端软件测试基础知识 - Mr.南柯 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  4. 南柯服务器压力,从纳兰性德《木兰花》中看网络暴力和舆论压力带来的抑郁现象...
  5. linux下安装mysql8.0(二进制方式)
  6. TURN协议(RFC5766详解)
  7. 软件项目管理第4版课后习题-期末复习题型分册版-带答案
  8. CAD画图教程,手把手教你画“鱼”
  9. 超声波测距 c语言程序流程图,超声波测距c语言源程序代码-20210413051213.docx-原创力文档...
  10. ADB interface驱动安装失败解决方法