使用Swing的GUI编程
阅读原文时间:2023年07月10日阅读:2

AWT概述

  • AWT:抽象窗口工具包,提供了一套与本地图形界面进行交互的接口,是Java提供的用来建立和设置Java的图形用户界面的基本工具
  • Swing以AWT为基础的,尽管Swing消除了AWT固有的大量限制,但Swing不是用来代替AWT的。Swing使用了与AWT相同的事件处理机制;所以使用Swing需要对AWT以及事件处理有一个基本了解

两个关键的Swing特性

  • 轻量级组件
  • 可插入外观

Swing包含的内容

  • 容器
  • 组件
  • 可改变的外观
  • Java2D图形绘制

容器类型

  • 顶层容器(重量级)

    • JFrame
    • JApplet
    • JDialog
    • JWindow
    • 继承自Component和Container

    注意:每个应用程序至少有一个顶层容器,也就是我们说的窗口

  • 中间容器

    • JPanel
    • JScrollPane
    • JSplitPane
    • 继承自JComponent

顶层容器JFrame窗体的层次结构

  • JFrame窗体的底层是RootPane(javax.swing.JRootPane)

    • RootPane包含GlassPane和LayeredPane

GlassPane

  • 是一个透明面板,主要功能是捕获JFrame上的任何事件
  • JGlassPane的默认值是不可看见的,不过可以设为看见的(visible)

LayeredPane

  • 是一个可以重叠组件的面板,本身就是一个容器
  • ContentPane是LayeredPane中的一层,一般视为最底层,也是最常用,最重要的容器。通常我们会将组件放在ContentPane上,而不会加在LayeredPane上

示例:

import javax.swing.JFrame;

public class FirstSwingDemo {

    public static void main(String[] args) {
        JFrame jf = new JFrame("第一个Swing窗口");//创建一个Java预定义的窗体
        /*方法1:setSize(int newWidth, newHeight)*/
        jf.setSize(400,480);//设置窗体的大小

        /*方法2:setSize(Dimension newSize)*/
        Dimension d = new Dimension(100,100);
        jf.setSize(d);

        jf.setVisible(true);//设置窗体是否可见
    }
}

JFrame窗口参数

方法

描述

setSize(int newWidth, int newHeight) / setSize(Dimension newSize)

设置窗体大小

setVisible(boolean visibleFlag)

设置窗体是否可见

setTitle(String newTitle)

设置窗体标题

面板(JPanel)

  • JPanel类是Java GUI工具包Swing中的面板容器类,是一种轻量级的容器
  • 可以加入到JFrame窗体中,自身可以嵌套使用,主要功能是对窗体中的组件进行组织
  • 其他Swing组件可以通过调用add()方法添加到面板容器对象中
  • 一旦添加,就可以使用Component类定义的setLoacation()、setSize()、setBounds()方法手动布局和调整
  • JPanel默认布局是FlowLayout(流布局),如果需要手动布局,需要使用setLayout()方法修改布局方式

示例(给窗体添加一个面板)

import java.awt.Color;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class FirstSwingDemo {

    public static void main(String[] args) {
        JFrame jf = new JFrame("第一个Swing窗口");//创建一个Java预定义的窗体
        jf.setSize(400,480);//设置窗体的大小
        jf.setVisible(true);//设置窗体是否可见

        JPanel jp = new JPanel();//创建一个面板容器对象
        Container container = jf.getContentPane();//将JPanel对象添加到父容器中
        container.setLayout(null);//设置布局
        container.add(jp);//添加组件

        /**
         * 设置布局和大小
         */
        jp.setSize(100,100);
        jp.setLocation(50,50);
        /**
         * 设置背景色
         */
        jp.setBackground(Color.black);
    }
}

标签(JLabel)

  • JLabel是最容易使用的Swing组件,用来创建标签

  • 最常用的构造方法是:

    • JLabel(String str):str用于标签的文本

    • JLabel(Icon icon):icon用于标签的图标;获取图标最容易的方式是使用ImageIcon类,它实现了Icon,所以可以将ImageIcon类型的对象作为参数传递给JLabel构造方法的Icon参数

      JLabel jl = new JLabel("第一个标签");
      jf.getContentPane().add(jl,BorderLayout.CENTER);
      
      //显示图片
      JLabel jl = new JLabel(new ImageIcon("icon.jpg"));
      jf.getContentPane().add(jl);

文本输入框(JTextField)

  • Swing的文本组件,通过它可以编辑一行文本,也可以响应用户交互事件

示例:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

public class FirstSwingDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("第一个Swing窗口");//创建一个Java预定义的窗体
        Dimension d = new Dimension(400,200);
        frame.setSize(d);

        /**
         * 添加一个用于显示的标签
         */
        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(d.width,60));
        frame.getContentPane().add(label,BorderLayout.NORTH);

        /**
         * 添加文本输入框
         */
        JTextField text = new JTextField();
        text.setPreferredSize(new Dimension(d.width,60));

        /**
         * 添加文本输入框Enter事件
         */
        text.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                label.setText(text.getText());
            }
        });
        frame.getContentPane().add(text,BorderLayout.CENTER);
        frame.setVisible(true);
    }

}

按钮(JButton)

  • JButton
  • JToggleButton
  • JCheckBox
  • JRadioButton

以上这些都是AbstractButton的子类,包含了许多用于控制按钮行为的方法。如下:

  • void setDisableIcon(Icon di)
  • void setPressedIcon(Icon pi)
  • void setSelectedIcon(Icon si)
  • void setRolloverIcon(Icon ri)

通过以下方法可以获取和修改关联的文本内容:

  • String getText()
  • void setText(String str)

示例:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class SecondSwingDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("这是按钮的练习");
        Dimension d = new Dimension(400,200);
        frame.setSize(d);

        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(d.width,60));
        frame.getContentPane().add(label,BorderLayout.NORTH);

        /**
         * 添加按钮
         */
        JButton button = new JButton("按钮");
        button.setPreferredSize(new Dimension(d.width,60));
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                label.setText("测试一下按钮");

            }
        });
        frame.getContentPane().add(button,BorderLayout.SOUTH);//在窗体中增加按钮
        frame.setVisible(true);//显示窗体
    }

}

组合框(JComboBox)

  • Swing通过JComboBox类来提供组合框(文本域与下拉列表组合)
  • 组合框通常显示一个条目,但也可以显示一个允许用户从中选择不同条目的下拉列表
  • 还可以创建允许用户在文本域中输入选项的组合框
  • 从JDK7开始,JComboBox设计成泛型类:class JComboBox
  • 可以通过addItem()方法添加到下拉列表中
  • 可以通过setSelectedItem()方法设置当前被选中的条目
  • 通过getSelectedItem()方法获取当前被选中的条目

示例:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.JComboBox;
import javax.swing.JFrame;

public class ThirdSwingDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("这是组合框的测试");
        Dimension d = new Dimension(400,200);
        frame.setSize(d);
        frame.setLayout(null);
        ArrayList<String> cars = new ArrayList<>();
        cars.add("哈弗");
        cars.add("吉利");
        cars.add("大众");
        cars.add("本田");
        cars.add("长安");

        /**
         * 创建下拉菜单
         */
        JComboBox<String> box = new JComboBox<>();
        box.setBounds(d.width/2-100,d.height/2-60,200,60);

        /**
         * 添加下拉菜单内容
         */
        for(String brands : cars) {
            box.addItem(brands);
        }

        box.setSelectedItem(cars.get(4));//设置当前选中的选项
        frame.getContentPane().add(box,BorderLayout.CENTER);
        frame.setVisible(true);
    }

}

BorderLayout类

  • 布置容器的边框布局管理器
  • 可以对容器组件进行安排,并调整其大小,使其符合五个区域:东、南、西、北、中
  • 每个区域只能包含一个组件

边框布局示例:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;

public class FourthSwingDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("BorderLayout示例");
        Dimension d = new Dimension(400,200);
        frame.setSize(d);
        BorderLayout layout = new BorderLayout();
        Container panel = frame.getContentPane();
        panel.setLayout(layout);
        Font font = new Font("黑体",Font.BOLD,24);
        JButton north = new JButton("北");
        north.setFont(font);
        panel.add(north,BorderLayout.NORTH);

        JButton south = new JButton("南");
        south.setFont(font);
        panel.add(south,BorderLayout.SOUTH);

        JButton west = new JButton("西");
        west.setFont(font);
        panel.add(west,BorderLayout.WEST);

        JButton east = new JButton("东");
        east.setFont(font);
        panel.add(east,BorderLayout.EAST);

        JButton center = new JButton("中");
        center.setFont(font);
        panel.add(center,BorderLayout.CENTER);

        frame.setVisible(true);

    }

}

FlowLayout类

  • 布置容器的流布局管理器

  • 具有指定的对齐方式以及指定的水平和垂直间隙

  • align参数的值必须为以下的值之一:

    FlowLayout.LEFT、FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING、FlowLayout.TRAILING

流布局示例:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class FlowLayoutDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("FlowLayout示例");
        Dimension d = new Dimension(1280,1080);
        frame.setSize(d);
        JPanel panel = new JPanel();
        panel.setBackground(new Color(200,200,200));
        FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
        panel.setLayout(layout);
        frame.getContentPane().add(panel,BorderLayout.CENTER);

        for(int i = 0; i < 2; i++) {
            ImageIcon icon = new ImageIcon("myfinder.png");
            JLabel label = new JLabel(icon);
            label.setPreferredSize(new Dimension(
                    icon.getIconWidth(),icon.getIconHeight()));
            panel.add(label);
        }
        JButton button = new JButton("窗体减半");
        button.setFont(new Font("微软雅黑",Font.PLAIN,24));
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                panel.setSize(new Dimension(
                        panel.getWidth()/2,panel.getHeight()));
                panel.doLayout();
            }
        });
        panel.add(button);
        frame.setVisible(true);
    }

}

GridLayout类

  • 布置容器的网格布局管理器
  • 将容器划分成网络,组件可以按行和列排列
  • 在网格布局管理器中,每一个组件的大小相同
  • 网格中空格个数由网格行数和列数决定
  • 组件从网格的左上角开始,从左往右,从上往下的顺序加入到网格中
  • 每一个组件都会填满整个网格,改变窗体大小,组件大小也会随之改变

GridLayout示例:

import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GridLayoutDemo {

    public static void main(String[] args) {
        JFrame frame = new JFrame("FlowLayout示例");
        Dimension d = new Dimension(680,500);
        frame.setSize(d);

        JPanel gridPanel = new JPanel();
        int rowMax = 5;
        int colMax = 4;
        gridPanel.setLayout(new GridLayout(rowMax,colMax));
        frame.getContentPane().add(gridPanel);
        String[][] signal = {
                {"(",")","%","C"},
                {"1","2","3","+"},
                {"4","5","6","-"},
                {"7","8","9","*"},
                {"0",".","=","/"}
        };

        for (int i = 0; i < rowMax; i++) {
            for(int j = 0; j < colMax; j++) {
                JButton button = new JButton();
                button.setFont(new Font("微软雅黑",Font.BOLD,54));
                button.setText(signal[i][j]);
                gridPanel.add(button);
            }
        }
        frame.setVisible(true);
    }

}

组件绘制

渐变色面板示例:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class GradientPanel extends JPanel{

    public GradientPanel(BorderLayout borderLayout) {
        super(borderLayout);
    }

    @ Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(!isOpaque()) {
            return;
        }
        int width = this.getWidth();
        int height = this.getHeight();
        Graphics2D g2 = (Graphics2D)g;
        GradientPaint grandientPaint = new GradientPaint(
                width/4,
                height/4,
                Color.red,
                width,
                height,
                Color.blue,
                false);
        g2.setPaint(grandientPaint);
        g2.fillRect(0, 0, width, height);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("渐变色面板示例");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(500,400);

        GradientPanel grandientPanel = new GradientPanel(new BorderLayout());
        frame.getContentPane().add(grandientPanel);
        frame.setVisible(true);
    }

}

基本图形绘制

  • 常见的图形绘制方法:

    • 绘制直线:drawLine()
    • 绘制矩形:drawRect()
    • 绘制椭圆:drawOval()
    • 绘制弧形:drawArc()
    • 绘制多边形:drawPolygon()

    示例:

    @ Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.red);
            g.drawLine(0, //起点横坐标
            this.getHeight, //起点纵坐标
            this.getWidth, //终点横坐标
            this.getHeight/2);//终点纵坐标
        }
  • 常见的图形填充方法:

    • 填充矩形:fillRect()
    • 填充椭圆:fillOval()
    • 填充扇形:fillArc()
    • 填充多边形:fillPolygon()

    示例:

    @ Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.red);
            g.fillArc(this.getWeight/2-100, //圆心横坐标
            this.getHeight/2-100,//圆心纵坐标
             200, 200, //圆的直径
             0,  360);//起始弧度,终止弧度
        }