首页 Java程序设计精讲八 第八章 图形界面设计
文章
取消

Java程序设计精讲八 第八章 图形界面设计

Java程序设计精讲八 第八章 图形界面设计1

1 AWT与Swing

1.1. GUI

图形用户界面( Graphical User Interface,GUI)是大多数程序不可缺少的部分。 设计图形用户界面的步骤:选取组件、设计布局及响应事件。 在java. awt(抽象窗口工具集)包和javax. swing包中定义了多种用于创建图形用户界面的组件类。

1.2. AWT组件和Swing组件

AWT组件定义在java.awt包中,Swing组件定义在javax.swing包中。

例如,标签和按钮,在java.awt包中分别用Label和Button表示,而在javax.swing包中,则分别用Jabel和JButton表示,多数Swing组件以字母“J”开头

最大的不同:Swing组件在实现时不包含任何本地代码(),因此 Swing组件可以不受硬件平台的限制,而具有更多的功能。

1.3. 轻量级和重量级

  • 轻量级”组件:不包含本地代码的Swing组件

  • “重量级”组件:包含本地代码的AWT组件。

当“重量级”组件与“轻量级”组件一同使用时,如果组件区域有重叠,则“重量级”组件总是显示在上面。在Java 2平台上推荐使用Swing组件。

1.4. 组件和容器

Java的图形用户界面由各种组件构成,组件是构成图形用户界面的基本元素。

  • 组件:按钮(JButton)、文本输入框(JTextField)、标签(JLabel)等。
  • 容器(Container):框架(Frame)、面板( Panel)等组件,它们是特殊的组件。
  • 各种组件(包括容器)可以通过add()方法添加到容器中。

2 容器

2.1. 组件

  1. 容器组件∶指可以包含其他组件的组件,又分为顶层容器和一般用途容器。
  2. 非容器组件︰必须要包含在容器中。

注意:有些容器可以嵌套,在这个嵌套层次的最外层,必须是一个顶层容器。有些容器是不能当作顶层容器的,如JpanelJscrollPane。所有容器类的父类Container

2.2. 顶层容器

2.2.1. Swing提供的4种顶层容器:

  1. JFrame

    :是一个带有标题行和控制按钮(最小化、恢复/最大化、关闭)的独立窗口,有时称为框架,创建应用程序时需要使用。

  2. JApplet

    :创建小应用程序时使用,它被包含在浏览器窗口中。

  3. JDialog

    :创建对话框时使用

  4. JWindow

    :是一个不带有标题行和控制按钮的窗口,通常很少使用。

Tips:tipping_hand_man::

image-20230326223910198

image-20230325122428974

image-20230326224902847

image-20230326223539355

2.2.2. JFrame类常用的构造方法

  • JFrame():构造一个初始时不可见、无标题的新框架窗体。
  • JFrame(String title):创建一个初始时不可见、具有指定标题的新框架窗体。

2.2.3. 常用的方法

  • void setBounds(int x , int y , int width , int height):移动并调整框架大小。左上角位置的横纵坐标分别由x和y指定,框架的宽高分别由width和height指定。
  • void setSize(int width, int height):设置框架的大小,宽度是width,高度是height。
  • void setBackground( Color bg):使用颜色bg设置框架的背景色。
  • void setVisible( boolean aFlag):设置框架可见或不可见。
  • void pack( )∶调整框架的大小,以适合其子组件的首选大小和布局。
  • void setTitle( String title):设置框架的标题为字符串title。
  • Container getContentPane():返回此框架窗体的内容窗格对象。
  • void setLayout( LayoutManager manager):设置布局管理器。

2.2.4. 使用JFrame创建应用程序的例子

1
2
3
4
5
6
7
8
static void demo1() {
    JFrame frame = new JFrame("JFrameDemo");// 创建JFrame实例
    JButton button = new JButton("Press me");//创建JButton实例
    frame.getContentPane().add(button, BorderLayout.CENTER);//将JButton放到JFrame的中央
    frame.pack();//将JFrame设置为适当的大小
    frame.setVisible(true);//显示Jframe
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭时退出
}

创建窗口用到的JFrame和JButton类定义在javax. swing 包中,而 BorderLayout定义在ja-va. awt包中,程序的最开始要引入这两个包。主程序中首先创建了一个JFrame和一个JButton。JFrame是一个顶层级窗口,构造方法的参数指明了窗口的标题。JButton构造方法的参数指明了按钮上要显示的文字。JFrame可以改变窗口大小。在刚刚创建时,它的大小为0,并且不可见,需要使用frame. pack();语句调整窗口的大小,且使用frame. setVisible( true) ;语句来显示JFrame。pack()之前的语句,是将JButton放到JFrame的中央。

2.3. 内容窗格

  1. 4个顶层容器中的每一个都有一个内容窗格。除菜单之外,顶层容器中的组件都放在这个内容窗格中。

  2. 将组件放入内容窗格的方法∶

    • 通过顶层容器的getContentPane( )方法获得其默认的内容窗格。getContentPane( )方法的返回类型为java.awt.Container,它仍然是一个容器。然后将组件添加到内容窗格中。

      1
      2
      3
      4
      
      Container contentPane = frame. getContentPane( );
      contentPane.add (button, BorderLayout.CENTER);
      //也可以合并为一条:
      frame. getContentPane(). add (button, BorderLayout.CENTER);
      
    • 创建一个新的内容窗格,以取代顶层容器默认的内容窗格。通常的做法是创建一个JPanel的实例,它是java.awt.Container的子类。然后将组件添加到JPanel实例中,再通过顶层容器的setContentPane()方法将JPanel实例设置为新的内容窗格。 例如∶

      1
      2
      3
      4
      
      JPanel contentPane=new JPanel( );//创建JPane实例
      contentPane.setLayout(new BorderLayout( ) ;//创建布局管理器
      contentPane.add (button, BorderLayout.CENTER);//添加组件
      frame. setContentPane(contentPane);//添加内容窗格
      

      顶层容器默认内容窗格的布局管理器是BorderLayout,而JPanel默认的布局管理器是FlowLayout,因此需要为JPanel实例设置一个BorderLayout布局管理器。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      static void demo2() {
          JFrame frame = new JFrame("JFrameDemo2");// 创建JFrame实例
          JButton button = new JButton("Press me");//创建JButton实例
          JPanel panel = new JPanel();// 创建JPanel 并设置
          panel.setLayout(new BorderLayout());
          panel.add(button, BorderLayout.CENTER);
          frame.setContentPane(panel);//设置JPanel为内容窗格
          frame.pack();
          frame.setVisible(true);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      }
      
  3. 向顶层容器的内容窗格中添加组件时,可以直接调用顶层容器的add( )方法,这与调用内容窗格的add()方法是等价的。

2.4. 面板

2.4.1. JPanel类

  1. 常用的构造方法:

    • JPanel()︰创建具有FlowLayout布局的新面板。

    • JPanel( LayoutManager layout):创建具有指定布局管理器的新面板。

    使用public Component add (Component comp)方法可以将指定组件追加到面板中。

2.4.2. JScrollPane类

JScrollPane是带有滚动条的面板,它是Container类的子类。但是只能添加一个组件。所以当有多个组件需要添加时,一般是先将多个组件添加到JPanel中,然后再将这个JPanel添加到JScrollPane中。

  1. 构造方法
    • JScrollPane():创建一个空的JScrollPane,需要时水平和垂直滚动条都可显示。
    • JScrollPane( Component view):创建一个显示指定组件内容的JScrollPane ,只要组件的内容超过视图大小,就会显示水平和垂直滚动条。
  2. 方法
    • ovoid setHorizontalScrollBarPolicy(int policy):确定水平滚动条何时显示在滚动窗格上。参数policy的可选值为下列三者之一。
      • ScrollPaneConstants. HORIZONTAL_SCROLLBAR_AS_NEEDED:需要时可见。
      • ScrollPaneConstants. HORIZONTAL_SCROLLBAR_NEVER∶总是不可见。
      • ScrollPaneConstants. HORIZONTAL_SCROLLBAR_ALWAYS:总是可见。
    • ovoid setVerticalScrollBarPolicy (int policy):确定垂直滚动条何时显示在滚动窗格上。参数policy的可选值为下列三者之一︰
      • ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED:需要时可见。
      • ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER:总是不可见。
      • ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS:总是可见。

2.4.3. Scrollbar滚动条的构造方法:

  • Scrollbar():构造一个新的垂直滚动条。
  • Scrollbar(int orientation):构造一个具有指定方向的新滚动条。orientatic on指示滚动条的方向,其值是Scrollbar.HORIZONTAL或是Scrollbar.VERTICAL分别指示滚动条是水平滚动条,还是垂直滚动条。
  • Scrollbar( int orientation, int value, int visible, int minimum, int maximum):构造一个新的滚动条,它具有指定的方向、初始值、可视量、最小值和最大值。orientation的值如前所述,value是滚动条的初始值,visible是滚动条的可视量,通常由滑动块的大小表示,minimum是滚动条的最小值,maximum是滚动条的最大值。

3 标签及按钮

3.1. 标签

标签(JLabel)对象是最简单的Swing组件,通常用于显示提示性的文本信息或图标,不可被编辑。

3.1.1. 构造方法

  • JLabel():创建一个既不显示文本信息又不显示图标的空标签。
  • JLabel( lcon image):创建一个显示图标的标签。
  • JLabel(String text):创建一个显示文本信息的标签。
  • JLabel(Icon image, int horizontalAlignment):创建一个显示图标的标签,水平对齐方式由int型参数horizontalAlignment 指定。
  • JLabel(String text, int horizontalAlignment):创建一个显示文本信息的标签,水平对齐方式由int型参数horizontalAlignment指定。
  • JLabel(String text, Icon icon, int horizontalAlignment):创建一个同时显示文本信息和图标的标签,水平对齐方式由int型参数horizontalAlignment指定。

注意:

  1. 参数horizontalAlignment的取值∶
    • JLabel.LEFT:表示左对齐;
    • JLabel.RIGHT:表示右对齐;
    • JLabel.CENTER:表示居中对齐。
  2. 默认情况下: 标签内容在垂直方向上居中显示,只有文本信息的标签在水平方向上左对齐,只有图标的标签在水平方向上居中显示。
  3. 设置对齐方式
    • setHorizontalAlignment (int alignment)方法可以设置标签内容的水平对齐方式;
    • setVerticalAlignment (int alignment)方法可以设置标签内容的垂直对齐方式。
  4. 修改
    • setText (String text)方法修改显示在标签上的文本信息;
    • setlcon (lcon icon)方法修改标签上的图标。

3.2. 按钮

按钮 ( Button)是Java图形用户界面的基本组件之一

3.2.1. 常用的按钮︰

JButton、JToggleButton、JCheckBox和JRadioButton,它们均是 AbstractButton的子类或间接子类。各种按钮上都可以设置文本、设置图标、注册事件侦听程序。

按钮共有的方法,例如:addActionListener()、setEnabled).setText()和setlcon()等。

3.2.2. JButton——最简单的按钮

  1. 构造方法

    • JButton():创建一个既没有显示文本又没有图标的按钮。
    • JButton(lcon icon):创建一个没有显示文本但有图标的按钮。
    • JButton(String text):创建一个有显示文本但没有图标的按钮。
    • JButton(String text, Icon icon):创建一个既有显示文本又有图标的按钮。3

3.2.3. 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static void demo1() {
    final int[] count = {0};
    JFrame frame = new JFrame("ButtonDemo Demo1");
    JButton button = new JButton("Sample");
    JTextField textField = new JTextField("This is TextField");
    button.addActionListener(new AbstractAction() {
        private static final long serialVersionUID = -6546290280080337668L;
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("demo1 button actionPerformed count:" + Arrays.toString(count));
            count[0]++;
            textField.setText("count:" + (count[0]));

        }
    });
    frame.getContentPane().add(button, BorderLayout.SOUTH);
    frame.getContentPane().add(textField, BorderLayout.CENTER);
    frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowOpened(WindowEvent e) {
            super.windowOpened(e);
            System.out.println("windowOpened");
        }

        @Override
        public void windowClosed(WindowEvent e) {
            System.out.println("windowClosed");
            super.windowClosed(e);
        }
    });
    frame.setSize(300, 150);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}

注意:

  • setText()方法动态地改变按钮上显示的文本;
  • setEnbled()方法改变按钮的状态。

3.3. 切换按钮、复选按钮及单选按钮

除了普通按钮JButton外,还有切换按钮(JToggieBatton )、复选按钮 ( JCheckBox)和单选按钮(JRadioButton )。JCheckBox和JRadioButton都是JToggleButton的子类。都具有选中和未选中两种状态,默认处于未选中状态。

image-20230323214905138

3.3.1. JToggleButton的构造方法

  • JToggleButton():创建一个既没有显示文本又没有图标的切换按钮。
  • JToggleButtor(Icon icon):创建一个没有显示文本但有图标的切换按钮。
  • JToggleButton(Icon icon, boolean selected):创建一个没有显示文本但有图标和指定初始状态的切换按钮。
  • JToggleButton( String text):创建一个有显示文本但没有图标的切换按钮。
  • JToggleButton(String text, boolean selected):创建一个有显示文本和指定初始状态但没有图标的切换按钮。
  • JToggleButton( String text, Icon icon):创建一个既有显示文本又有图标的切换按钮。
  • JToggleButton(String text,Icon icon , boolean selected):创建一个既有显示文本又有图。

注意:

  1. JToggleButton、JCheckBox和JRadioButton等具有两种状态的按钮不仅可以注册ActionEvent事件侦听程序,还可以注册ItemEvent事件侦听程序,在ltemListener接口中声明方法:

    1
    
    public voiditemStateChanged( ltemEvent e);//当按钮的状态发生改变时,将会调用该方法。
    
  2. 多个组件可以使用共同的事件处理程序。如getSource()方法和getltem()方法,可以获取事件源,该方法的返回类型为Object。
    1
    2
    3
    
    public Object getSource();
    //需要进行类型转换,例如,下面命令将Object类型转换为JRadioButtori类型。
    JRadioButton rb = (JRadioButton)e. getSource();
    
  3. 在事件处理程序中,通过isSelected ()方法获取按钮的当前状态, 例如︰

    1
    
    ta.append("\nJCheckBox Button 1" +cbl. isSelected());
    
  4. 按钮可以添加到按钮组中,这时首先要创建一个按钮组对象,然后调用按钮组的add()方法将按钮添加到按钮组。只能有一个按钮处于被选中状态。

  5. JCheckBox Group和JRadioButton Group分别注册了不同的事件监听程序,使用ItemListener与使用ActionListener是有差别的。

  6. 通常用JCheckBox表示那些可多选的选择项(不加入按钮组),而用JRadioButton表示只能单选的选择项(需要加入按钮组)。JCheckBox称为复选按钮,而JRadioButton称为单选按钮。

4 布局管理器

4.1. FlowLayout布局管理器

FlowLayout(流布局)定义在java.awt包中,这个布局管理器对容器中组件进行布局的方式是将组件逐个地放置在容器中的一行上,一行放满后就另起一个新行。

4.1.1. 构造方法

  • FlowLayout( ): 创建一个默认的FlowLayout布局管理器,居中对齐,默认的水平和垂直间距是5个像素。
  • FlowLayout(int align): 创建一个新的FlowLayout布局管理器,对齐方式是指定的,默认的水平和垂直间距是5个像素。
  • FlowLayout(int align, int hgap, int vgap): 创建一个新的FlowLayout布局管理器,具有指定的对齐方式以及指定的水平和垂直间距。

注意:

  1. align的可取值有
    • FlowLayout.LEFT:左对齐
    • FlowLayout. RlGHT:右对齐
    • FlowLayout. CENTER:居中对齐方式
  2. 可选项hgap和vgap,可用来设定组件的水平间距和垂直间距。
  3. 每个组件都有一个getPreferredSize()方法,容器的布局管理器会调用这一方法取得每个组件希望的大小。
1
2
3
setLayout( new FlowLayout( FlowLayout. RIGHT, 2040)) ;
setLayout( new FlowLayout( FlowLayout.LEFT));
setLayout( new FlowLayout( ));

4.2. BorderLayout布局管理器

BorderLayout(边界布局)是顶层容器中内容窗格的默认布局管理器。

4.2.1. 5个区域

上部(North)、下部 ( South)、左部 ( West)、右部(East)和中部 (Center),分别使用常量BorderLayout. NORTH、BorderLayout. SOUTH、BorderLayout. WEST、BorderLayout.EAST和 BorderLayout. CENTER来表示。

4.2.2. 构造方法

  • BorderLayou():构造一个组件之间没有间距的新的BorderLayout布局管理器。
  • BorderLayout(int hgap, int vgap):用指定的组件之间的水平和垂直间距构造一个BorderLayout布局管理器。

注意:

  1. 在BorderLayout布局管理器的管理下,组件必须通过add( )方法加入到容器中的指定区域。
  2. 在容器的每个区域,只能加入一个组件。如果试图向某个区域中加入多个组件,那么只有最后一个组件是有效的。
  3. 如果真的希望在某个区域显示多个组件,可以先在该区域放置一个内部容器,比如JPanel组件,然后将所需的多个组件放到JPanel中,再将其放到指定的区域。
  4. 对于East、South、West和North这4个边界区域,如果某个区域没有使用 那么它的大小将变为零,此时Center区域将会扩展并占据这个未用区域的位置。

4.3. GridLayout布局管理器

GridLayout是一种网格式的布局管理器,它将容器空间划分成若干行乘若干列的网格,组件依次放入其中,每个组件占据一格。GridLayout定义在java.awt包中。

4.3.1. 构造方法

  • GridLayout():创建一个只有一行的网格,网格的列数根据实际需要而定。
  • GridLayout(int rows, int cols):创建具有指定行数和列数的网格布局。
  • GridLayout(int rows , int cols,int hgap,int vgap):创建具有指定行数和列数,且有指定水平间距和垂直间距的网格布局。

注意:

  1. 网格每列的宽度都是相同的,网格每行的高度也是相同的。
  2. 组件被放入容器的次序决定了它所占据的位置。每行网格从左至右依次填充,一行用完之后转入下一行。
  3. 如果想在组件之间留有空白,则可以添加一个空白标签。

4.4. CardLayout布局管理器

CardLayout也是定义在java.awt包中的布局管理器,这是一种卡片式的布局管理器,它将容器中的组件处理为一系列卡片,每一时刻只显示出其中的一张,而容器充当卡片的容器。

4.4.1. 构造方法

  • CardLayout():创建一个默认的无间距的新的CardLayout布局管理器。
  • CardLayout(int hgap, int vgap):创建一个具有指定的水平和垂直间距的新的CardLayout布局管理器。

4.4.2. 常用方法

  • add():将组件加入容器。
  • public void first(Container parent):翻转到容器的第一张卡片。
  • public void next (Container parent):翻转到指定容器的下一张卡片。如果当前的可见卡片是最后一张,则此方法翻转到布局的第一张卡片。
  • public void previous(Container parent):翻转到指定容器的前一张卡片。如果当前的可见卡片是第一张,则此方法翻转到布局的最后一张卡片。
  • public void last( Container parent):翻转到容器的最后一张卡片。
  • public void show (Container parent ,String name):翻转到已添加到此布局的具有指定name的卡片。如果不存在这样的卡片,则不发生任何操作。

4.5. BoxLayout布局管理器

BoxLayout是定义在javax. swing包中。它将容器中的组件按水平方向排成一行 或按垂直方向排成一列。当组件排成一行时,每个组件可以有不同的宽度;当组件排成一列时,每个组件可以有不同的高度。

4.5.1. 构造方法

  • BoxLayout( Container target ,int axis):创建一个将沿给定轴放置组件的布局管理器。
    • target指明是为哪个容器设置此BoxLayout布局管理器,
    • axis指明组件的排列方向
      • BoxLayout. X_AXIS:水平方向排列
      • BoxLayout. Y_AXIS:垂直方向排列

4.5.2. 专门使用BoxLayout的特殊容器——Box类

  1. 创建Box实例的静态方法
    • public static BoxcreateHorizontalBox():使用水平方向的BoxLayout。
    • public static BoxcreateVerticalBox():使用垂直方向的BoxLayout。
  2. 创建不可见组件的方法
    • public static Component createHorizontalGlue()。
    • public static Component createVerticalGlue()。
    • public static Component createHorizontalStrut(int width)。
    • public static Component createVerticalStrut(int height)。
    • public static Component createRigid Area(Dimension d)。

4.6. 空布局

在特殊场合,也可以不使用布局管理器,通过数值指定组件的位置和大小。

  1. 首先需要调用容器的setLayout(null)将布局管理器设置为空

  2. 然后调用组件的setBounds()方法设置组件的位置和大小, 格式︰

    1
    
    setBounds( int x, int y, int width, int height);//前两个int型参数设置组件的位置,后两个int型参数设置组件的宽度和高度。
    

4.7. Tips

image-20230324160803393

5 事件处理

用户在程序界面所进行的操作称为用户事件。对事件的响应称为事件处理。

5.1. 事件处理模型

5.1.1. 委托事件处理模型

概括来说,事件被直接送往产生这个事件的组件,组件需要注册一个或多个侦听程序。侦听程序的类中包含了事件处理程序,用来接收和处理这个事件。事件是一个对象,它只向注册的侦听程序报告。

1
2
3
public interface ActionListener extends EventListener {
	public void actionPerformed( ActionEvent e) ;
}

该接口中只定义了一个方法,即actionPerformed(),当出现ActionEvent事件时,就会调用该方法。 每个组件都有若干个形如 addXXXListener (XXXListener)的方法,通过这类方法,可以为组件注册事件侦听程序。

例如:

1
2
3
4
//在JButton类中有如下的方法:
public void addActionListener( ActionListener l);//该方法可为JButton组件注册ActionEvent事件侦听程序,方法的参数是实现了ActionListener接口的类的一个实例。
//也可以删除添加的事件侦听程序,例如:
public void removeActionListener( ActionListener l);//将移除指定的操作侦听器,以便它不再接收来自此按钮的操作事件。

5.1.2. 事件处理的步骤

  1. 程序中引人java.awt. event包。import java.awt.event;
  2. 给所需的事件源对象注册事件侦听程序。 事件源对象.addXXXListener( XXXListener);
  3. 实现相应的方法。若某个侦听程序接口包含多个方法,则需要实现所有的方法。
  4. java.awt.event包中用来检测并对事件做出反应的模型包括以下三个组成元素:源对象、监视器对象、事件对象

5.2. 事件的种类

事件类型组件接口名称方法及说明
ActionEventJButton、JCheckBox、JComboBox、 JMenultem、JRadioButtonActionListeneractionPerformed( ActionEvent)单击按钮、选择菜单项或在文本框中按<Enter>键时
AdjustmentEventJScrollBarAdjustmentListeneradjustmentValueChanged (AdjustmentEvent)当改变滚动条滑块位置时
ComponentEventJComponent类及其子类ComponentlJstenercomponenMoved (ComponentEvent)组件移动时
componentHidden(ComponenIEvent)组件隐藏时
componentResized (ComponentEvent)组件缩放时
componentShown( ComponentEvent)组件显示时
ContainerEventJContainer类及其子类ContainerListenercomponentAdded( ContainerEvent)添加组件时
componentRemoved(ContainerEvenl)移除组件时
Focus Event同ComponentEventFocusListenerfocusGained( FocusEvent)组件获得焦点时
focusLost( FocusEvent)组件失去焦点时
ItemEventJCheckBox、JComboBox、JCheckboxMenultemItemListeneritemStaleChanged (ltemEvent)选择复选框、选项框、单击列表框、选中带复选框菜单时
Key Event同ComponenlEventKeyListenerkeyPressed( KeyEvenl)键按下时
keyReleased( KeyEvent)键释放时
keyTyped( KeyEvenl)击键时
MouseButtonEvent同ComponentEvenlMouseListenermousePressed( MouseEvent)鼠标键按下时
mouseReleased( MouseJEvent)鼠标键释放时
mouseEntered(MouseEvent)鼠标进入时
mouseExiled(MouseEvent)鼠标离开时
mouseClicked (MouseEvent)单击鼠标时
MouseMotionEvent同ComponenlEventMouseMotionListenermouseDragged(MouseEvent)鼠标拖放时
mouseMoved( MouseEvent)鼠标移动时
TextEventJTextField、 TextAreaTextListenertextValueChanged( TextEvent)文本框、文本区内容修改时
WindowEventJFrame、JWindow、JDialogWindow ListenerwindowClosing( WindowEvent)窗口关闭时
windowOpened(WindowEvenl)窗口打开后
windowlconified( WindowEvent)窗口最小化时
windowDeiconified(WindowEvent)最小化窗口还原时
windowClosed(WindowEvent)窗口关闭后
windowAclivated( WindowEvent)窗口激活时
windowDeactivated( WindowEvent)窗口失去焦点时

5.3. 事件适配器

  1. 事件侦听模式允许为一个组件注册多个侦听程序,通常的做法是在该事件的处理程序中编写需要的所有响应。有时需要在同一程序的不同部分对同一事件进行响应。事件侦听模型允许根据需要多次调用addListener方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    public class MouseClickHandler implements MouseListener{
    //只关心对单击鼠标事件的处理,因此改写mouseClicked()方法
        public void mouseClicked(MouseEvent e){/*进行有关的处理*/}
        //但是对其他方法,仍然需要给出实现
    	public void mousePressed( MouseEvent e){}
        public void mouseReleased( MouseEvent e){}
        public void mouscEntered( MouseEvent e){}
        public void mouscExited( MouseEvent e){}
    }
    
  2. Java为一些声明了多个方法的Listener接口提供了相对应的适配器类

    接口名称适配器名称接口名称适配器名称
    ComponentListenerComponentAdapterMouseListenerMouseAdapter
    ContainerListenerContainerAdapterMouseMotionListenerMouseMotionAdapter
    FocusListenerFocusAdapterMouselnputListenerMouselnputAdapter
    KeyListenerKeyAdapterWindowListenerWindowAdapter

Tips:tipping_hand_man::

image-20230325122203330

image-20230325122330375

6 绘图基础

坐标原点(0,0)位于整个区域的左上角。一个坐标点(x,y )对应屏幕窗口中的一个像素,这里x与y必须都是非负整数。设定绘图区域的宽width和高height,绘图区域的大小也就确定下来了。

6.1. 颜色

使用java.awt包中的Color类来定义和管理颜色。

6.1.1. 生成颜色的方法

  1. 使用java的Color类中预定义的颜色。Color类中包含了26个常量,提供了13种基本的预定义的颜色。

    颜色对象RGB值颜色对象RGB值
    黑色Color. black0,0,0洋红色Color.magenta255,0,255
    蓝色Color.blue0,0,255橙色Color.orange255,200,0
    青色Color.cyan0,255,255粉红色Color.pink255,175,175
    灰色Color.gray128,128,128红色Color.red255,0,0
    深灰色Color.darkGray64,64,64白色Color.white255,255,255
    浅灰色Color.lightCray192,192,192黄色Color.yellow255,255,0
    绿色Color.green0,255,0   

6.1.2. 设置组件的前景色和背景色

  • public void setForeground(Color c):设置前景色。
  • public void setBackground( Color c):设置背景色。

在这两个方法中,都需要java.awt.Color类的一个实例作参数,包括Color类中预定义的颜色常量,比如Color.red和Color.blue,或是自己创建的颜色。

6.2. 字体

6.2.1. 显示文字的方法

  • public void drawChars(char[ ]data, int offset, int length, int x,int y):使用此图形上下文的当前字体和颜色显示字符数组data中从offset位置开始、最多length个字符。首字符的基线位于此图形上下文坐标系统的(×,y)处。
  • public void drawString(String aString,int x, int y)∶在指定位置显示字符串aString。
  • public void drawBytes( byte[] data, int offset, int length, int x,int y) :使用此图形上下文的当前字体和颜色显示由指定的byte数组data中从offset位置开始、最多length个字符。首字符的基线位于此图形上下文坐标系统的(x,y)处。

6.2.2. 文字字形3个要素

  1. 字体

    :常用的字体有Times New roman、Symbol、宋体、楷体等。

  2. 样式

    :Font. PLAIN (正常) 、Font.BOLD(粗体)及Font.ITALIC(斜体)3种。

    基本样式可以组合使用,例如 Font. BOLD + Font.ITALIC。

  3. 字号

    ∶字的大小,单位是磅。

6.2.3. Font类

  1. 构造方法

    • Font(String name,int style , int size):根据指定字体名称、样式和字号,创建一个新Font对象。
      1
      
      Font f = new Font("Dialog"Font.PLAIN,14);
      
  2. 方法

    • String getName():返回此Font的逻辑名称,即字体名称。
    • int getSize():返回此Font的字号大小,舍入为整数。
    • int getStyle():返回此Font的样式。
    • boolean isBold():测试此Font对象的样式是否为BOLD。
    • boolean isltalic():测试此Font对象的样式是否为ITALIC。
    • boolean isPlain():测试此Font对象的样式是否为PLAIN。

6.3. Graphics类的基本功能

6.3.1. Graphics类

java.awt包中的Graphics类是所有图形处理的基础。Graphics类是所有图形上下文的抽象父类,允许应用程序在组件以及屏幕图像上进行绘制

  1. 功能:建立字体、设定显示颜色、显示图像和文本、绘制和填充各种几何图形等。

  2. 绘图模式:

    • 正常模式

      :后绘制的图形覆盖先绘制的图形,使得先绘制的图形被重叠的部分不再可见

    • 异或模式

      :当前绘制的颜色、先前绘制的颜色及所选定的某种颜色之间进行某种处理,使用得到的新颜色值进行绘制

  3. 设置绘图模式的方法

    • setPaimMode( ):将此图形上下文的绘图模式设置为正常模式,这是默认模式。
    • setXORMode(Color c):将此图形上下文的绘图模式设置为异或模式,参数c指定了绘制对象时与窗口进行异或操作的颜色。
  4. 所有绘制都必须通过一个图形对象完成

    1. 直接在框架(Frame)中显示文本信息,也可以直接在框架中绘图。

    2. 在某个组件中绘图,一般应该为这个组件所属的子类重写pait()方法,在该重写的方法中进行绘图。

    3. 在JCornponem子类的组件中绘图,应重写paintComponent()方法,在该方法中进行绘图。

      要创建自定义图形,需要由JPanel类派生一个新类,并重写父类的paintComponent()方法。

      1
      2
      3
      
      public void paintComponent( Graphics g){
      	//将在这里通过参数g编写绘制代码
      }
      

      通常情况下,如果需要在组件上绘制图形,只需要重写JComponent的paintComponent(Graphics g)方法,该方法的参数是一个Graphics对象。

  5. Graphics中定义的多种绘图方法

    • drawArc( int x, int y, int width, int height, int startAngle, int arcAngle)∶沿着由左上角为(x y)、宽为width、高为height的外接矩形所限定的椭圆绘制一条弧.弧起始于startAngle,延伸的距离由arcAngle定义。
    • drawLine(int x1 , int y1 , intx2 , inty2):绘制一条从点(x1, y1)到点( x2,y2)的直线。
    • drawOval( int x , int y, int width, int height):绘制一个由左上角为(x,y)、宽为width、高为height的外接矩形所限定的椭圆。
    • drawPolygon( int[ ]xPoints , int[ ]yPoints , int nPoints):绘制由x和y坐标数组定义的一系列连接线。每对(x, y)坐标定义了一个点。如果第一个点和最后一个点不同,则图形不是闭合的。
    • drawRect(int X , int y , int width, int height):绘制一个矩形,其左上角为(X,y),宽为width,高为height。
    • drawRoundRect( int x, int y, int width, int height, int arcWidth,intarcHeight):用此图形上下文的当前颜色绘制圆角矩形的边框。矩形的左边和右边分别位于x和x + width。矩形的顶边和底边位于y和y + height。
    • drawString(String str , int x , int y):在点(x,y)处输出字符串str,向右扩展。
    • draw3DRect( (int x , int y , int width, int height, boolean raised)):绘制指定矩形的3-D突出显示边框。矩形的左上角为(x,y),宽为width,高为height。raised指示矩形是凸出平面显示还是凹入平面显示。
  6. 填充图形(用当前的前景色填充图形)

    • fillArc(intx, int y, int width, int height, int startAngle, int arcAngle)。

    • fillOval(intx , int y, int width, int height)。

    • fillPolygon( int [ ] xPoints, int [ ]yPoints, int nPoints)。

    • fillRect(intx, int y, int width, int height)。

    • fillRoundRect( int x, int y, int width,int height, int arcWidth,intarcHeight)。

    用Graphics类中的setColor方法可以设置前景色,使用所画组件(如面板)的setBackground方法可以设置背景色。

  7. 绘制多边形 画多边形的方法分别是drawPolygon()和fillPolygon ()。这两种方法都是重载的。当使用数组作参数时,drawPolygon()和fillPolygon()方法各带3个参数。

    • 第一个参数:表示多边形各点x坐标的整数数组,
    • 第二个参数:表示多边形各点y坐标的整数数组,
    • 第三个参数:一个整数,表示两个数组中有多少个点可用。放在一起来看,前两个参数表示多边形各点的( x,y)坐标。
  8. 绘制折线

    与多边形不同的是,绘制折线时第一个坐标和最后一个坐标并不自动连接起来。因为折线不封闭,所以也不能填充。它只有一个方法drawPolyline(),方法中的参数与drawPolygon()方法中的参数类似。

  9. Polygon类中的常用方法∶

    • Polygon():构造方法,创建空的多边形。
    • Polygon(int[] xpoints , int[] ypoints, int npoints):构造方法,使用xpoints和ypopints中的相对应的坐标对(×,y)来创建多边形。
    • addPoint(intx , int y):将由参数指定的点加入到多边形中。
    • contains(int x , int y):如果指定的点含在多边形中,则返回真。
    • contains(Point p):如果指定的点含在多边形中,则返回真。
    • getBcnmdS():得到多边形的外接矩形。
    • translate (int deltaX, int deltaY):将多边形的各顶点沿x轴偏移deltaX,沿y轴偏移deltaY。

6.4. Graphics2D绘图

Java 2D包括一个继承于Graphics类的Graphics2D类,GmphiCS2D拥有更强大的二维图形处理能力,提供对几何形状、坐标转换、颜色管理以及文字布局等更复杂的控制。

6.4.1. 图形状态属性

image-20230326224803866

  1. stroke 属性

控制线的宽度、笔形样式、线段连接方式或短划线图案。创建BasicStroke对象后,再调用setStroke()方法即司设置stroke属性。

创建BasicStroke对象的方法:

  • BasicStroke(float w):指定线的宽度w。
  • BasicStroke(float w , int cap, int join):指定线的宽度w,端点样式cap及两线段交汇处的连接方式join。
    • cap的值有:CAP_BUTT(无修饰)、CAP_ROUND(半圆形末端)和CAP_SQUARE (方形末端,默认值)。
    • join的值有:JOIN_BEVEL (无修饰)、JOIN_MTTER(尖形末端,默认值)和JOIN_ROUND(圆形末端)。
  1. paint属性

    控制填充效果。先调用GradientPaint()方法确定填充效果,再使用setPaint()方法进行设置

    GradientPaint()方法:

    • GradientPaint( float x1 , float y1 , Color c1 , float x2,float y2 ,Color c2);:构造一个简单的非周期性的GradientPaint对象。从点( x1,y1 )到点(x2,y2),c1是点(x1, y1)处的颜色,c2是点(x2,y2)处的颜色,从c1渐变到c2。
    • GradientPaint (float x1 , float y1 ,Color c1, float x2, float y2, Color c2,Boolean cyclic):根据boolean参数构造一个周期性或非周期性的GradientPaint对象。如果希望渐变到终点又是起点的颜色,应将cyclic设置为true.
  2. transform属性

    用来实现常用的图形平移、缩放和斜切等变换操作。首先创建AffineTransform对象,然后调用setTransform()方法设置transform属性。最后,使用具有指定属性的Graphics2D对象绘制图形。

    创建AffineTransform对象的方法∶

    • AffineTransform( ):构造一个表示仿射(ldentity)变换的新AffineTransform。

    类中的常用方法:

    • getRotatelnstance( double theta):旋转theta弧度。
    • getRotateInstance(double theta, dioble x , double y):绕旋转中心(x, y)旋转。
    • getScalelnstance(double sx , double sy) :x和y方向分别按sx , sy比例变换。
    • getTranslatelnstance(double tx , double ty):平移变换。
    • getShearInstance( double shx, double shy):斜切变换,shx和shy 指定斜拉度。

    指定图形平移、旋转及缩放变换:

    • translate(double dx , double dy):将图形在×轴方向平移dx像素
    • scale (double sx , double sy):图形在x轴方向缩放sx倍,纵向缩放sy倍。
    • rotate (double arc , double x , double y):图形以点(x,y)为轴点,旋转arc弧度。
  3. clip属性

    用于实现剪裁效果J可以调用setClip( )方法,确定剪裁区的Shape从而设置剪裁属性,可以使用连续多个setClip()得到它们交集的剪裁区。

  4. composit属性

    设置图形重叠区域的效果。先使用方法AlphaComposite. getlnstance (int rule,float alpha),得到AlphaComposite对象,再通过setComposite()方法设置混合效果。alpha值的范围为0.0f(完全透明)至0.1f(完全不透明)。

6.4.2. Graphics2D类绘图方法

  1. 在java.awt.geom包中声明的系列类,分别用于创建各种几何图形对象。

    这些类主要有:Line2D线段类、RoundRectangle2D圆角矩形类、Ellipse2D椭圆类、Arc2D圆弧类、QuadCurve2D二次曲线类和CubicCurve2D三次曲线类。

  2. 画图步骤︰

    1. 先在重画方法paintComPonent()或Paint()中,把参数对象g强制转换成GmPhicS2D对象;
    2. 用上述各图形类提供的静态方法Double()创建该图形的对象;
    3. 以图形对象为参数调用Gmphics2D对象的draw()方法绘制这个图形。

示例:

1
2
3
4
5
Graphics2D g2d = (Graphics2D)g//将对象g类型从Graphics转换成Graphics2D
Line2D line = new Line2D.Double(30.0,30.0,340.0,30. 0);//创建图形对象
g2d. draw (line);//绘制线段
RoundRectangle2D rRect = new RoundRectangle2D.Double(13.0,30.0,100.0,70.0,40.0,20.0);
g2d.draw( rRect);//绘制圆角矩形

6.4.3. Graphics2D的几何图形类

  1. 线段

    1
    
    Line2D line = new Line2D.Double(2,3,200,300) ;//声明并创建线段对象,起点是(2,3),终点是(200,300):
    
  2. 矩形

    1
    
    Rectangle2D rect = new Rectangle2D.Double (20,30,80,40);//声明并创建矩形对象,矩形的左上角是(20,30),宽是80,高是40
    
  3. 圆角矩形

    1
    2
    
       
    RoundRectangle2D rectRound = new RoundRectangle2D.Double(20,30,130,100,18,15);//声明并创建圆角矩形,左上角是(20,30),宽是130,高是100,圆角的长轴是18,短轴是15∶
    
  4. 椭圆

    1
    
    Ellipse2D ellipse = new Eltipse2D.Double(20,30,100, 50);//声明并创建椭圆,左上角(20,30),宽是100,高是50
    
  5. 圆弧

    1
    
    Arc2D arcl =new Arc2D. Double(8,30,85,605,90,Arc2D.OPEN);//声明并创建圆弧,外接矩形的左上角是(8,30),宽是85,高是60,起始角是5度,终止角是90度,Arc2D.OPEN表示是一个开弧
    
  6. 弓弧(Arc2D.CHORD)和饼弧(Arc2D.PIE)

    1
    2
    
    Arc2D arc2 = new Arc2D. Double(20,65,90,70,0,180,Arc2D. CHORD);//弓弧
    Arc2D arc3 = new Arc2D. Double(40,110, 50, 90,0,270,Arc2D.PIE);//饼弧
    
  7. 二次曲线

    在数学上,二次曲线用二阶多项式表示:y~(x)~ = ax^2^ + bx + c

    绘制一条二次曲线时需要确定3个点,分别是始点、控制点和终点。方法 Double ()中的6个参数分别是二次曲线的始点、控制点和终点。

    1
    2
    3
    4
    
    //3条二次曲线有相同的始点和相同的终点,控制点均不同
    QuadCurve2D curve1 = new QuadCurver2D. Double(20,10,90,65,55,115);
    QuadCurve2D curve2 = new QuadCurver2D. Double(20,10,15,63,55,115);
    QuadCurve2D curve3 = new QuadCurver2D. Double(20,10,54,64,55,115);
    
本文由作者按照 CC BY 4.0 进行授权

Java程序设计精讲六 第七章 输入和输出流

Java程序设计精讲十 第九章 Swing组件