超级详细的Swing学习笔记

Posted mp-ui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超级详细的Swing学习笔记相关的知识,希望对你有一定的参考价值。

Swing学习笔记

写在前面

这个笔记是我在B站学习的时候写的一些笔记(https://www.bilibili.com/video/BV1h7411v7Mq)

如果有什么不对的地方欢迎指正!

框架代码

照此框架即可

import javax.swing.*;
import java.awt.*;
public class SwingDemo

	private static void createGUI()
	
		// JFrame指一个窗口,构造方法的参数为窗口标题
		JFrame frame = new JFrame("Swing Demo");
		
		// 当关闭窗口时,退出整个程序 (不懂的话没事,照抄即可,这一行不是重点)
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// JFrame创建时自带了一个根容器,称为ContentPane,但一般我们会自己创建一个JPanel(后面有演示)
		Container contentPane = frame.getContentPane();
		contentPane.setLayout(new FlowLayout());
		
		// 向内容面板里添加控件 , 如 JLabel, JButton
		contentPane.add(new JLabel("Hello,World"));
		contentPane.add(new JButton("测试"));
        //JLabel和JButton都是可以通过构造方法设置他显示的内容,也可以用setText()方法
		
		// 设置窗口的其他参数,如窗口大小
		frame.setSize(400, 300);
		
		// 显示窗口
		frame.setVisible(true);
	
	
	public static void main(String[] args)
	
		// 此段代码间接地调用了 createGUI(),具体原理在 Swing高级篇 里讲解
		// 初学者先照抄此代码框架即可
		javax.swing.SwingUtilities.invokeLater(new Runnable() 
			public void run()
			
				createGUI();
			
		);

	

框架代码+

上面的CreateGUI()方法里面比较乱,所以自己实现一个MyFrame类,窗口里面各种布局的设置都是MyFrame类里面完成,这样才不显得乱。(以后都这样做,照搬SwingDemo类,只需改写MyFrame类)

import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MyFrame extends JFrame 
	/**
	 * 序列化UID
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * 引用父类的构造方法,并且所有的控件都在这里定义,免得SwingDemo那个类比较乱
	 * @param nameString
	 */
	public MyFrame(String nameString) 
		super(nameString);
		Container contentPane = getContentPane();
		contentPane.setLayout(new FlowLayout());
		// 向内容面板里添加控件 , 如 JLabel, JButton
		contentPane.add(new JLabel("Hello,World"));
		contentPane.add(new JButton("测试"));
	

public class SwingDemo

	private static void createGUI()
	
		MyFrame frame = new MyFrame("Swing Demo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(400, 300);
		frame.setVisible(true);
	
	public static void main(String[] args)
	
		javax.swing.SwingUtilities.invokeLater(new Runnable() 
			public void run()
			
				createGUI();
			
		);
	

Swing和AWT

1、Swing是基于AWT的,所以在Swing项目中,可以看到会引入java.awt.*下的内容。

2、两套控件,AWT的是Label、Button、…,Swing的是JLabel、JButton、…,我们用的都是Swing的控件。Swing是一套轻量化的实现。

监听器Listener

监听器是Swing里界面事件处理的一种方式。

1、新建一个类,实现ActionListener接口

class MyButtonListener implements ActionListener
	@Override
	public void actionPerformed(ActionEvent e) 
		// TODO Auto-generated method stub
		System.out.println("按钮被点击了。");
	

2、创建监听器对象

MyButtonListener myButtonListener = new MyButtonListener();

3、将监听器对象交给按钮

JButton jButton2 = new JButton("按钮");//新建一个按钮
contentPane.add(jButton2);
jButton2.addActionListener(myButtonListener);//绑定Listener

4、当按钮被点击时,Swing框架会调用监听器对象里的方法,进行处理。

◆一般都采用匿名内部类的写法,才不显得那么啰嗦。

JButton jButton = new JButton("按钮名称"); //创建一个按钮
jButton.addActionListener(new ActionListener() 	
	@Override
	public void actionPerformed(ActionEvent e) 
		System.out.println("按钮被点击了");
	
);

◆或者采用Lambda表达式。

JButton jButton = new JButton("按钮名称"); //创建一个按钮
jButton.addActionListener((e)->
	System.out.println("按钮被点击了");
);

控件

JComponent类

JComponent是除顶层容器外所有 Swing 组件的基类。

公用方法:

void setOpaque(boolean isOpaque) 
          设置是否不透明,如果为 true,则该组件绘制其边界内的所有像素。 
void setPreferredSize(Dimension preferredSize) 
          设置此组件的首选大小(注意不是setSize(),setSize()是Component类的方法(com.awt包下))。
void setToolTipText(String text) 
          注册要在工具提示中显示的文本(鼠标停靠在上面时显示的文本)。 
void setVisible(boolean aFlag) 
          使该组件可见或不可见。 
void setFont(Font font) 
          设置此组件的字体。 
void setForeground(Color fg) 
          设置此组件的前景色。 
void setBackground(Color bg) 
          设置此组件的背景色。 (注:如果是JLabel,必须先调用setOpaque(true))
void setEnabled(boolean enabled) 
          设置是否启用此组件。 

标签JLabel

构造方法:
JLabel(String text) 
          创建具有指定文本的 JLabel 实例。
普通方法:
String getText() 
          返回该标签所显示的文本字符串。 
void setText(String text) 
          定义此组件将要显示的单行文本。 
void setHorizontalAlignment(int alignment) 
          设置标签内容沿 X 轴的对齐方式。 
void setVerticalAlignment(int alignment) 
          设置标签内容沿 Y 轴的对齐方式。 
 setHorizontalAlignment中alignment的参数可以为:
 	SwingConstants.CENTER、SwingConstants.LEFT、SwingConstants.RIGHT
 setVerticalAlignment中alignment的参数可以为:
  	SwingConstants.CENTER、SwingConstants.TOP、SwingConstants.BOTTOM
JLabel jLabel = new JLabel();
jLabel.setText("这是一个标签");
jLabel.setFont(new Font("微软雅黑",Font.PLAIN,16));
/*
Font的构造方法:Font("字体名称",样式,大小);
样式可以是 PLAIN(常规)、BOLD(粗体)、ITALIC(斜体) 或 BOLD+ITALIC(粗体加斜体)。
*/
jLabel.setForeground(Color.BLUE);
/*
颜色可以是Color.XXX或者Color.xxx,
也可以用构造方法new Color(int r,int g,int b);参数范围0-255
*/
jLabel.setToolTipText("标签提示");
contentPane.add(jLabel);

文本框JTextField

继承关系:JComponent–JTextComponent–JTextField

构造方法:
new JTextField(int columns);  构造一个具有指定列数的新的空 TextField。
new JTextField(String text) 构造一个用指定文本初始化的新 TextField。 
new JTextField(String text, int columns) 构造一个用指定文本和列初始化的新 TextField。 
普通方法(继承自JTextComponent):
String getText() 
          返回此 TextComponent 中包含的文本。 
String getText(int offs, int len) 
          获取由组件表示的文本部分。 
void setEditable(boolean b) 
          设置指定的 boolean 变量,以指示此 TextComponent 是否应该为可编辑的。 
void setText(String t) 
          将此 TextComponent 文本设置为指定文本。 
普通方法(类本身的):
int getColumns() 
          返回此 TextField 中的列数。 
void setColumns(int columns) 
          设置此 TextField 中的列数,然后验证布局。 
/*
实现功能:有一个标签一个文本框一个按钮,点击按钮就弹出一个消息框,显示刚刚输入的内容
*/
JLabel jLabel = new JLabel("请输入:");      //新建一个标签,显示的文字为“请输入”
JTextField jTextField = new JTextField(16); //设置宽度为16
JButton jButton = new JButton("确定");      //新建一个按钮,显示的文字为“确定”
jButton.addActionListener(new ActionListener() 
    @Override
    public void actionPerformed(ActionEvent e) 
        String str = jTextField.getText();
        JOptionPane.showMessageDialog(MyFrame.this,"输入了:" + str);
        /*
        JOptionPane的静态方法
static void showMessageDialog(Component parentComponent, Object message) 
          调出标题为 "Message" 的信息消息对话框。 
static void showMessageDialog(Component parentComponent, Object message, String title, int messageType) 
          调出对话框,它显示使用由 messageType 参数确定的默认图标的 message。 
static void showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon) 
          调出一个显示信息的对话框,为其指定了所有参数。 

        */
    
);
contentPane.add(jLabel);
contentPane.add(jTextField);
contentPane.add(jButton);

单选框JRadioButton

继承关系:
javax.swing.JComponent
-javax.swing.AbstractButton
--javax.swing.JToggleButton
---javax.swing.JRadioButton
方法和下面复选框的类似!

▲▲注:需要另外创建一个 ButtonGroup 对象配合使用才能实现单选效果。

复选框JCheckBox

继承关系:

javax.swing.JComponent
–javax.swing.AbstractButton
---- javax.swing.JToggleButton
------- javax.swing.JCheckBox

构造方法:
new JCheckBox(String text) 
          创建一个带文本的、最初未被选定的复选框。 
new JCheckBox(String text, boolean selected) 
          创建一个带文本的复选框,并指定其最初是否处于选定状态。
普通方法:
isSelect()/setSelect() : 获取/设置选中状态
setText():选项文字

下拉列表框JComboBox

1 创建 JComoboBox
JComboBox<String> colorList = new JComboBox<>();
可见,JComboBox 是一个泛型,参数类型T 表示是的数据项的类型

2 添加数据项
colorList.addItem("红色");
colorList.addItem("蓝色");
colorList.addItem("绿色");
addItem ( T ) ,T的类型在创建时指定,这里是 String 类型,也就是每一项Item的数据类型是String

3 按索引访问
getSelectedIndex() : 获取选中项的索引
setSelectedIndex() : 设置选中项
remove (index) :按索引删除

4 按数据项访问
getSelectedItem() 
setSelectedItem()
remove ( item )

5 事件处理
单击: ActionListener
选项改变:ItemListener,但这个事件总会执行2次,解决办法,加if判断:
if(e.getStateChange() == ItemEvent.SELECTED)
/*
实现功能:左边下拉列表框,右边标签,左边选好颜色后右边变成相应的颜色。
*/
JComboBox<String> jComboBox = new JComboBox<>();
jComboBox.addItem("红色");
jComboBox.addItem("绿色");
jComboBox.addItem("蓝色");
JLabel jLabel = new JLabel("这是一个示例 This is a simple example!");
jComboBox.setSelectedIndex(0);  //默认选中第一个(红色)
jLabel.setForeground(Color.RED); //默认是红色
contentPane.add(jComboBox);
contentPane.add(jLabel);
jComboBox.addActionListener(new ActionListener() 
    @Override
    public void actionPerformed(ActionEvent e) 
        Color color = null;
        switch (jComboBox.getSelectedIndex())
            case 0:
                color = Color.RED;
                break;
            case 1:
                color = Color.GREEN;
                break;
            case 2:
                color = Color.BLUE;
                break;
            default:
                color = Color.BLACK;
        
        jLabel.setForeground(color);
    
);

列表框JList

JList是一个泛型类(和JComboBox类似)

构造方法:
JList() 构造一个具有空的、只读模型的 JList。 
JList(ListModel dataModel) 根据指定的非 null 模型构造一个显示元素的 JList。 
JList(Object[] listData) 构造一个 JList,使其显示指定数组中的元素。 
普通方法:
(查API)

■我发现JList是只读的,没有像JComboBox的addItem()方法,所以只能在构造方法中传入数组。

示例:

JList<String> jList = new JList<>(new String[]"选项1","选项2");
contentPane.add(jList);

根据我上网查后发现,如果想实现动态添加,那么应该使用ListModel(这是接口,使用的是他的实现类DefaultListModel)【JComboBox也有相对应的ComboModel】

DefaultListModel<String> defaultListModel= new DefaultListModel<>();
defaultListModel.addElement("选项1");
defaultListModel.addElement("选项2");
JList<String> jList = new JList<>(defaultListModel);//通过构造方法把ListModel传进去
contentPane.add(jList);

默认是不显示水平和垂直滚动条的,即使列表满了,如果要显示滚动条,还应该使用JScrollPane【不是JScrollBar,这个组件就单纯是创建一个滚动条而已,不起什么作用】

DefaultListModel<String> defaultListModel= new DefaultListModel<>();
defaultListModel.addElement("选项1");
defaultListModel.addElement("选项2");
JList<String> jList = new JList<>(defaultListModel);//通过构造方法把ListModel传进去
//contentPane.add(jList);
JScrollPane jScrollPane = new JScrollPane(jList);//构造方法中绑定要显示滚动条的部件(注:只有显示满了才会显示)
contentPane.add(jScrollPane);//绑定之后,往容器里加的是JScrollPane对象了而不再是JList,contentPane.add(jList)已不起作用!

注:如果部件绑定滚动条之后,想要设置组件大小,不能通过被绑定的部件来设置,如

jList.setPreferredSize(new Dimension(300,500));
/*
经过测试,这样子设,不起作用,反而还出问题
*/

正确代码

jScrollPane.setPreferredSize(new Dimension(300,500));

★另:改变列表中每一项显示的样式,可以使用ListCellRenderer

例子:

这里使用JLabel来绘制列表中的每一项,也可以使用其他的,只要最后return回去就行了。注意:使用这个的意思并不是将JLabel控件放到JList上面,而是将JLabel的显示效果复制到JList上面去而已。

private static class MyListCellRenderer implements ListCellRenderer<String>
    @Override
    public Component getListCellRendererComponent(JList<? extends String> list, //使用这个CellRenderer的列表对象
                                                  String value,//每一项的值
                                                  int index, //索引
                                                  boolean isSelected,//是否被选中状态
                                                  boolean cellHasFocus //不知道,和上面的差不多
) 
        JLabel jLabel = new JLabel();
        jLabel.setText(value); //要显示的文本
        jLabel.setHorizontalAlignment(SwingConstants.CENTER);//居中显示
        jLabel.setFont(new Font("微软雅黑",Font.BOLD,18));
        jLabel.setBackground(Color.white);
        jLabel.setForeground(Color.RED);
        jLabel.setOpaque(true);
        if(isSelected)
            //当被选中时呈现的效果
            jLabel.setBackground(Color.CYAN);
        
        return jLabel;
    

//然后把这个CellRenderer放到JList上面。
jList.setCellRenderer(new MyListCellRenderer()); //设置CellRenderer(也可以使用匿名内部类的写法)

表格控件JTable

和JList一样,也需要一个Model来负责数据的管理,即TableModel(使用其实现类DefaultTableModel)。为了显示出滚动条,也需要被绑在JScrollPane里。

通过我的实验发现,直接往容器里添加JTable是不显示表头的,必须要用JScrollPane才能显示表头。

DefaultTableModel的方法:

void addColumn(Object columnName) 
          添加列头
void addRow(Object[] rowData) 
          添加一行
void addRow(Vector rowData) 
          添加一行

表格控件里的常用方法:

Object getValueAt(int row, int column) 
          返回 row 和 column 位置的单元格值。 
void setRowHeight(int rowHeight) 
          设置单元格高度
void setColumnSelectionAllowed(boolean columnSelectionAllowed) 
          是否是整行选择,默认true
int getSelectedColumn() 
          返回第一个选定列的索引;如果没有选定的列,则返回 -1。 
int[] getSelectedColumns() 
          返回所有选定列的索引。 
int getSelectedRow() 
          返回第一个选定行的索引;如果没有选定的行,则返回 -1。 
int[] getSelectedRows() 
          返回所有选定行的索引。 

★用TableCellRenderer可以自定义单元格的显示,和ListCellRenderer一样。

但是绘制器只能一列一列地设置

TableColumn column = jTable.getColumnModel().getColumn(列数);//获取某一列的对象
column.setCellRenderer(...);    //设置TableCellRenderer
column.setHeaderRenderer(...);    //设置标题的样式

转盘控件JSpinner

这个是可以将数字微调的控件,通常提供一对带小箭头的按钮以便逐步遍历序列元素。

◆构造方法:
JSpinner() 构造一个 spinner,使其具有初始值为 0 并且无任何最小值或者最大值限制
JSpinner(SpinnerModel model) 构造具有一对 next/previous 按钮和 SpinnerModel 编辑器的完整 spinner。 
▲SpinnerModel是一个接口,如果是数字的话就使用它的实现类SpinnerNumberModel
如:new JSpinner(new SpinnerNumberModel(值,最小值,最大值,步长));

◆普通方法:
void setModel(SpinnerModel model)  更改表示此 spinner 值的模型。 
SpinnerModel getModel() 返回定义此 spinner 值序列的 SpinnerModel。 
void setValue(Object value) 更改模型的当前值,通常此值是 editor 所显示的值。 
Object getValue() 返回模型的当前值,通常此值是 editor 所显示的值。 
注:获取当前值也可以getModel().getValue()

其他控件

这里是一些其他比较常用的控件,具体使用方法自己查API文档:

  1. JTabbedPane:选项卡

  2. JTree:树

    e.g.

    DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode("根");
    JTree jTree = new JTree(treeNode);
    DefaultMutableTreeNode treeNode1 = new DefaultMutableTreeNode("子1");
    DefaultMutableTreeNode treeNode11 = new DefaultMutableTreeNode("子子1");
    DefaultMutableTreeNode treeNode2 = new DefaultMutableTreeNode("子2");
    DefaultMutableTreeNode treeNode3 = new DefaultMutableTreeNode("子3");
    treeNode.add(treeNode1);
    treeNode.add(treeNode2);
    treeNode.add(treeNode3);
    treeNode1.add(treeNode11);
    contentPane.add(jTree);
    

彩色标签案例

JLabel jLabel1 = new JLabel("标签1");
jLabel1.setOpaque(true);    //设置为不透明,这样才能显示出背景色
jLabel1.setBackground(Color.BLUE);   //设置背景色为蓝色
jLabel1.setHorizontalAlignment(SwingConstants.CENTER);  //水平居中
jLabel1.setPreferredSize(new Dimension(40,30));  //设置组件的首选大小
contentPane.add(jLabel1);

布局(实现LayoutManager接口)

流布局FlowLayout

特点:从左到右逐个排列,当一行占满时挪到下一行

//上面的代码在创建窗口的时候就设置了布局模式
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());

方法:

void setAlignment(int align)  设置此布局的对齐方式。 
--可以取的值有:
FlowLayout.LEFT 左对齐
FlowLayout.RIGHT  右对齐
FlowLayout.CENTER  居中
FlowLayout.LEADING  与容器方向的开始边对齐
FlowLayout.TRAILING  与容器方向的结束边对齐

void setHgap(int hgap) 设置组件之间以及组件与 Container 的边之间的水平间隙。 
void setVgap(int vgap) 设置组件之间以及组件与 Container 的边之间的垂直间隙。
void setAlignment(int align) 设置此布局的对齐方式。 

构造方法:
new FlowLayout(int align) 
          构造一个新的 FlowLayout,它具有指定的对齐方式,默认的水平和垂直间隙是 5 个单位。 
new FlowLayout(int align, int hgap, int vgap) 
          创建一个新的流布局管理器,它具有指定的对齐方式以及指定的水平和垂直间隙。 

边界布局BorderLayout

特点:把布局分为上、下、左、右、中 五个区域

方法:

构造方法:
BorderLayout() 构造一个组件之间没有间距的新边框布局。 
BorderLayout(int hgap, int vgap) 构造一个具有指定组件间距的边框布局。 
普通方法:
 void setHgap(int hgap) 设置组件之间的水平间距。 
 void setVgap(int vgap) 设置组件之间的垂直间距。 
常量:
static String CENTER 中间区域的布局约束(容器中央)。 
static String EAST 东区域的布局约束(容器右边)。 
static String NORTH 北区域的布局约束(容器顶部)。 
static String SOUTH 南区域的布局约束(容器底部)。 
static String WEST 西区域的布局约束(容器左边)。 
用于add方法的第二个参数,表示将组件添加到布局的哪个位置上
contentPane.add(组件1,BorderLayout.EAST); //添加到左边
contentPane.add(组件2,BorderLayout.WEST);  //添加到右边
contentPane.add(组件3,BorderLayout.NORTH);  //添加到上边
contentPaneJava学习笔记7.1.1 初探Swing世界 - Swing顶级容器

Java学习笔记7.1.1 初探Swing世界 - Swing顶级容器

Java学习笔记7.3.1 用户界面 - Swing常用组件

Java学习笔记7.3.1 用户界面 - Swing常用组件

如何将间距约束指定为超级视图大小的比例?

详细解读CSS链接属性——Web前端系列学习笔记