软件构造学习记录——Swing

Swing学习记录

前言

Java 1.0刚刚出现时,包含了一个用于基本 GUI 程序设计的类库,被称为抽象窗口工具箱(Abstract Window Toolkit,AWT),然而不同平台上运行的AWT用户界面库存在不同的bug,后来Sun公司和Netscape合作,创建了一个名为Swing的用户界面库。值得注意的是,Swing没有完全取代AWT,而是基于AWT构架之上,Swing仅仅提供了更强大的用户界面组件,处理事件还需要AWT

下面通过一个例子来创建基于Swing的GUI界面

创建框架

在Java中,顶层窗口(就是没有包含在其他窗口中的窗口)被称为框架。在Swing中用JFrame来描述顶层窗口,下面的例子可以创建一个宽高均为屏幕一半的界面

package GUI;

import javax.swing.*; //Swing位于javax.swing包
import java.awt.*;

public class Frame {
    public static void main (String[] args) {
        EventQueue.invokeLater(() ->
        {
            Toolkit kit = Toolkit.getDefaultToolkit();
            Dimension screenSize = kit.getScreenSize();
            int screenWith = screenSize.width;
            int screenHeight = screenSize.height;
            MyFrame frame = new MyFrame(screenWith / 2, screenHeight / 2); // 宽高均为一半
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 定义关闭框架的动作
            frame.setVisible(true); // 设置可见性
        });
    }
}

class MyFrame extends JFrame {
    private static final int DEFAULT_WIDTH = 300;
    private static final int DEFAULT_HEIGHT = 200;
    public MyFrame() {
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
    }

    public MyFrame(Dimension dimension) {
        setSize(dimension);
    }

    public MyFrame(int width, int height) {
        setSize(width, height);
        setTitle("Board"); // 框架的标题
    }
}

运行时会创建一个框架,标题是"Board",如下图。采用EventQueue.invokeLater(() -> { statement; }要比直接在主线程中完成初始化更加安全(虽然不知道原理)
在这里插入图片描述

框架的定位及部分属性

JFrame 类本身只包含若干个改变框架外观的方法,其他许多处理框架大小和位置的方法是从其超类中继承来的,下图是JFrame类的继承层次图,图片取自《Java核心技术卷I​》⬇️(后面的图片也是)
在这里插入图片描述
比较重要的设置框架位置、大小的方法有:

  • setLocation(int x, int y),setBounds(int x, int y, int width, int height):这两个方法都是从Component类中继承得来的,setLoction方法将框架的左上角设为(x,y)位置,屏幕左上角为(0,0);setBounds同时将窗口大小设置为width×height
  • setLocationByPlatform(boolean bool):是否让窗口系统选择窗口的位置,如果bool为true,窗口系统可以控制窗口的位置,通常是距离最后一个显示窗口很少偏移量的位置
  • setSize(int width, int height),setSize(Dimension dimension):设置窗口大小
  • setIconImage(Image image):设置图标(ALT+TAB时候显示的图标)
  • setTitle(String title):设置标题
  • setResizable(boolean bool):设置用户是否可以重新设置框架大小

JFrame的结构

可以直接将消息绘制在框架中,然而并不推荐这样。在Java中,框架被设计为放置组件的容器,所以在通常情况下,应该在一个组件上绘制信息,再将这个组件添加到框架中。
JFrame包含四层面板,其中根面板、层级面板和玻璃面板使用来组织菜单栏和内容窗格以及实现观感的,编程时并不太关心它们,而关心内容窗格Content Pane,在编程时使用下列代码将组件添加到内容窗格中
在这里插入图片描述

Container contentPane = frame.getContentPane();
Component c = ...;
contentPane.add(c);

在Java SE 1.4及以前版本中,使用JFrame类中的add方法时会抛出异常"Do not use JFrame.add().Use JFrame.getContentPane.add() instead",如今JFrame.add会调用内容窗格的add,所以可以直接调用

frame.add(c);

加到框架中的组件c,必须是实现了paintComponent方法的类,该方法表示这个组件如何进行绘制

Swing组件

首先来看一下各个组件的类层次在这里插入图片描述

布局管理

布局管理顾名思义就是管理各个组件,使其按照一定的模式排列在一个框架或容器内
每个容器都有一个默认的布局管理器,但可以使用setLayout()方法重新进行设置,如

panel.setLayout(new GridLayout(2, 2)); // 将布局设置为网格布局

JPanel对象默认采用流布局管理器(flow layout manager),当一行的空间不够时,会将显示在新的一行上。通常,组件放置在容器中, 布局管理器决定容器中的组件具体放置的位置和大小,下面介绍两种布局

  1. 边框布局(BorderLayout)
    边框布局管理器(border layout manager)是每个JFrame的内容窗格的默认布局管理器,与流布局管理器不同的是,边框布局管理器不会完全控制每个组件的放位置,它允许为每个组件选择一个放置位置。可以将组件放置在,东南西北或中,5种位置,如下图

    5个位置可以不填满,当容器被缩放时,四边的组件的大小不会发生改变,而中间组件的大小会发生变化。与流布局不同,边框布局会扩展所有组件的尺寸以便填满可用空间,而流布局将维持每个组件的最佳尺寸。

  2. 网格布局(GridLayout)

    网格布局像电子数据表一样,按行列排列所有的组件。不过,它的每个单元大小都是一样的,当缩放窗口时,所有组件的大小都会变化,但是它们的大小始终保持一致

文本

具有用户输入和编辑文本功能的组件有三种:

  • JTextField:文本域,只能接受单行文本的输入
  • JTextArea:文本区,可以接受多行文本的输入
  • JPasswordField:密码域,只能接受单行文本的输入,且不会显示出原内容,而是以回显字符(echo character)表示,比如’*’

上面三种组件均继承于抽象类JTextComponent,下面一一介绍其用法:

  1. 文本域

     JPanel panel = new JPanel();
     JTextField textField = new JTextField("Default input", 15);
     panel.add(textField);
     frame.add(panel);
    

    上面采用将文本域加入到面板,再将面板加入框架的方法,也可以直接将文本域加入到框架中。第二行构造JTextField用到了两个参数,第一个参数指示初始字符串,可以省略,第二个参数指示文本域的列数。可以使用getColumns()方法获取列数,用setColumns(int cols)方法来重新设置列数,需要注意的是使用setColumns方法改变了一个文本域的大小之后,需要调用包含这个文本框的容器(上面的例子中这个容器是panel)的revalidate方法。该方法会重新计算容器内所有组件的大小,并且对它们重新进行布局。
    可以通过setText(String str)方法改变文本域中的内容,也可以用getText()方法获得用户输入的文本,如果嫌弃字体难看可以用setFont(Font f)方法设置组件的字体

  2. 文本区

     JPanel panel = new JPanel();
     JTextArea textArea = new JTextArea(8, 15); // 8 行 15 列
     panel.add(textField);
     frame.add(panel);
    

    文本区用于接收超过一行的用户输入,setRows和setColumns可以改变行数和列数,布局管理器也可能对文本区进行缩放(比如一行输入巨长时,文本区的列数会变化;行数同理)。当一行输入文本巨长时,文本区会变得很长,可以通过开启换行特性来避免过长

    textArea.setLineWrap(true);
    

    这样当一行输入文本长度比文本区的列数大时,该行文本会被自动换行。值得注意的是,换行只是视觉效果,文档中的文本没有改变,文本中并没有插入’\n’字符。

  3. 密码域

    JPanel panel = new JPanel();
     JPasswordField  password = new JPasswordField(15);
     panel.add(password);
     frame.add(panel);
    

    如果你看不顺眼默认的回显字符,可以用setEchoChar(char echo)方法设置。同时,可以用getPassword()方法返回密码域中的文本,为了安全起见,使用后应该覆盖返回数组的内容。值得注意的是,该方法返回的是char[]而不是String,因为字符串对象在被垃圾回收器回收之前会驻留在虚拟机中

下图给出了三个组件的显示效果
在这里插入图片描述
与文本有关的还有标签(JLabel)组件,它可以用于标识其他组件。
在文本区中,如果输入长度(不管是列方向还是行方向)超过文本区设定的大小都会扩张文本区(文本域和密码域不会),使用setLineWrap方法会让一行文本分行显示,然而有些用户并不喜欢这样,它们更倾向于使用滚动条。然而文本区中没有滚动条,不过可以将文本区插入到滚动窗格(scroll pane)中

textArea = new JTextArea(8, 15);
JScrollPane scrollPane = new JScrollPane(textArea);

效果如图所示:在这里插入图片描述
这是一种为任意组件添加滚动功能的通用机制, 而不是文本区特有的。也就是说,要想为组件添加滚动条,只需将它们放入一个滚动窗格中即可

(读到这实验3的GUI应该差不多可以完成,其他的组件做完实验再加,咕咕咕)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值