本来swing是不想看了的,但是既然书上有,还是得追求个有始有终

图形界面设置

一. AWT 与 Swing

  • AWT组件定义在 Java.awt包中
  • Swing组件定义在 Javax.swing 包中
  • Swing 组件与 AWT 组件最大的不同
    • Swing组件在实现时不包含任何本地代码
    • Swing 组件可以不受硬件平台的限制
    • Swing组件不包含本地代码,被称为 轻量级组件
    • Swing组件比AWT(重量级组件)拥有更多的功能

二. 容器

1. 顶层容器

  • 组件可以分为容器组件 和 非容器组件

    • 容器组件是指可以包含其他组件的组件
      • 又分为顶层容器 和 一般用途容器
    • 非容器组件 必须要包含在容器中
  • 所有容器类有一个父类 Container

  • 容器所有的共有操作都定义在 Container 中

  • Swing提供了 4 种顶层容器

    • JFrame
      • 带有标题行 和控制按钮(最小化,最大化,关闭)的独立窗口
      • 创建应用程序时需要使用
    • JApplet
      • 被包含在浏览器窗口中
      • 创建小应用程序时使用
    • JDialog
      • 创建对话框时使用
    • JWindow
      • 不带有 标题行 和 控制按钮 的窗口,很少使用
  • JFrame类实例

    • public static void main(String[] args) throws FileNotFoundException {
      
          // 创建一个JFrame实例,带有标题
          JFrame frame = new JFrame("JFrameDemo");
      
          // 创建一个JButton实例,按钮带文件
          JButton butt = new JButton("点我");
      
          // 将按钮放到JFrame的中央
          frame.getContentPane().add(butt, BorderLayout.CENTER);
      
          // 将JFrame设置为适当的大小
          frame.pack();
      
          // 显示JFrame
          frame.setVisible(true);
      
          // 退出时关闭窗口
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
      }
      

2. 内容窗格

  • 顶层容器的组件都放在内容窗格中

  • 4个顶层容器都有一个内容窗格,有两种方法可将组件放入该窗格中

    • 通过 顶层容器的 getContentPane( )方法

      • frame.getContentPane().add(butt, BorderLayout.CENTER);
        
    • 创建一个新的内容窗格

      • JPanel contentPane = new JPanel();  // 创建Jpanel实例
        
        contentPane.setLayout(new BorderLayout());  // 创建布局管理器
        
        contentPane.add(butt,BorderLayout.CENTER);  // 添加组件
        
        frame.setContentPane(contentPane);  // 添加内容窗格
        
    • 顶层容器的内容窗格默认是BorderLayout

    • Japanel默认的是 FlowLayout,因此需要给Jpanel实例设置一个BorderLayout布局管理器

  • 修改JFrame实例

    • public static void main(String[] args) throws FileNotFoundException {
      
          // 创建一个JFrame实例,带有标题
          JFrame frame = new JFrame("JFrameDemo");
      
          // 创建一个JButton实例,按钮带文件
          JButton butt = new JButton("点我");
      
          // 创建一个Jpanel实例
          JPanel contentPane = new JPanel();
      
          // 为Jpanel设置BorderLayout布局
          contentPane.setLayout(new BorderLayout());
      
          // 将JButton放到Jpanel中央
          contentPane.add(butt,BorderLayout.CENTER);
      
          // 为JFrame设置新的内容窗格
          frame.setContentPane(contentPane);
      
          // 将JFrame设置为实当的大小
          frame.pack();
      
          // 显示JFrame
          frame.setVisible(true);
      
          // 退出时关闭窗口
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
      }
      

3. 面板

  • 普通面板 JPanel 和 滚动面板 JScrollPane 都是用途广泛的容器

    • 面板不能独立存在,可以嵌套
  • 实例:创建一个黄色普通面板,通过add( )方法在面板中添加一个按钮,然后将该面板添加到JFrame的一个实例中,JFrame实例的背景色被设置成蓝绿色

    • public static void main(String[] args) {
          // 创建带标题的JFrame实例
          JFrame frame = new JFrame("Hello");
      
          // 获取内容窗格
          Container contentPane = frame.getContentPane();
      
          // 将JFrame实例的背景色设置成蓝绿色
          contentPane.setBackground(Color.CYAN);
      
          // 创建一个JPanel实例
          JPanel panel = new JPanel();
      
          // 将JPanel实例的背景色设置为黄色
          panel.setBackground(Color.YELLOW);
      
          JButton button = new JButton("点我");
      
          // 将按钮实例添加到JPanel面板中
          panel.add(button);
      
          // 将面板JPanel实例添加到JFrame的南侧
          contentPane.add(panel,BorderLayout.SOUTH);
      
          // 设置容器大小
          frame.setSize(300,200);
      
          // 设置容器可见性
          frame.setVisible(true);
      
          // 退出时关闭窗口
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      }
      
  • JScrollPane 是滚动条的面板

    • Container的子类,只能添加一个组件
    • 一般先将多个组件添加到JPanel,然后将这个 JPanel 添加到 JScrollPane中

三. 标签及按钮

1. 标签 JLabel

  • 显示提示性的文本信息或图标

  • 创建一个以右对齐方式显示的标签

    • JLabel label = new JLabel("Hello",JLabel.RIGHT);
      

四. 布局管理器

1. FlowLayout 布局管理器

  • 将组件挨个放置在容器的一行上,一行满了,就另起一行

  • 使用FlowLayout管理JFrame中的若干按钮

    • public class Test {
      
          private JFrame frame;
          private JButton btn1,btn2,btn3;
      
          public static void main(String[] args) {
              Test test = new Test();
              test.go();
      
          }
      
          public void go() {
              frame = new JFrame("Hello");
              Container contentPane = frame.getContentPane();     // 内容窗格
              contentPane.setLayout(new FlowLayout());    // 将内容窗格设置FlowLayout布局管理器
              btn1 = new JButton("OK");   // 分别创建3个按钮
              btn2 = new JButton("Open");
              btn3 = new JButton("Close");
              contentPane.add(btn1);      // 向内容窗格中添加3个按钮
              contentPane.add(btn2);
              contentPane.add(btn3);
              frame.setSize(300,100);     // 设置窗口大小
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   // 退出时关闭窗口
          }
          
      }
      

2. BorderLayout布局管理器

  • BorderLayout是顶层容器中内容窗格默认的布局管理器

  • 被划分为5个区域

    • BorderLayout.NORTH 上
    • BorderLayout.SOUTH 下
    • BorderLayout.WEST 左
    • BorderLayout.EAST 右
    • BorderLayout.CENTER 中
  • 实例

    • public class Test {
      
          private JFrame frame;
          private JButton btnNorth,btnSouth,btnWest,btnEast,btnCenter;
      
          public static void main(String[] args) {
              Test test = new Test();
              test.go();
      
          }
      
          public void go() {
              frame = new JFrame("Hello");
              btnNorth = new JButton("上部");
              btnSouth = new JButton("下部");
              btnWest = new JButton("左部");
              btnEast = new JButton("右部");
              btnCenter = new JButton("中部");
      
              frame.getContentPane().add(btnNorth,"North");
              frame.getContentPane().add(btnSouth,"South");
              frame.getContentPane().add(btnWest,"West");
              frame.getContentPane().add(btnEast,"East");
              frame.getContentPane().add(btnCenter,"Center");
      
              frame.setSize(350,200);
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   // 退出时关闭窗口
      
      
          }
      
      }
      

3. GridLayout布局管理器

  • 将容器空间划分为若干行乘若干列的网格,组件依次放入,每个组件占一格

    • public class Test {
      
          private JFrame frame;
          private JButton b1,b2,b3,b4,b5,b6;
      
          public static void main(String[] args) {
              Test test = new Test();
              test.go();
      
          }
      
          public void go() {
              frame = new JFrame("HELLO");
              Container contentPane = frame.getContentPane();
              contentPane.setLayout(new GridLayout(3,2));
              b1 = new JButton("Grid1");
              b2 = new JButton("Grid2");
              b3 = new JButton("Grid3");
              b4 = new JButton("Grid4");
              b5 = new JButton("Grid5");
              b6 = new JButton("Grid6");
              
              contentPane.add(b1);
              contentPane.add(b2);
              contentPane.add(b3);
              contentPane.add(b4);
              contentPane.add(b5);
              contentPane.add(b6);
              
              frame.setSize(400,500);
              frame.pack();
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
      
          }
      
      }
      

4. CardLayout布局管理器

  • 卡片式布局管理器,将容器指的组件处理为一系列卡片,每一时刻只显示出一张

  • 实例:

    • 指定一个CardLayout类型的布局,然后其中加入了3张卡片,每张卡片都是JPanel的实例,并且具有不同的背景色,每按动鼠标,就会显示下一张

    • public class Test extends MouseAdapter {
      
          JPanel p1,p2,p3;
          JLabel l1,l2,l3;
          CardLayout myCard;  // 声明一个CardLayout对象
          JFrame frame;
          Container containerPane;
      
          public static void main(String[] args) {
              Test test = new Test();
              test.go();
      
          }
      
          /**
           * 处理鼠标事件,每当按下鼠标键,显示下一张卡片
           * 如果显示到最后一张,则重新显示第一张
           * @param e
           */
          @Override
          public void mouseClicked(MouseEvent e) {
              myCard.next(containerPane);
          }
      
          public void go() {
              frame = new JFrame("HELLO");
              containerPane = frame.getContentPane();
              myCard = new CardLayout();
              containerPane.setLayout(myCard);       // 设置CardLayout布局管理器
              p1 = new JPanel();
              p2 = new JPanel();
              p3 = new JPanel();
      
              l1 = new JLabel("这是第一个标签"); // 为每个JPanel创建一个标签
              p1.add(l1);
              p1.setBackground(Color.YELLOW);     // 设定不同的背景颜色
      
              l2 = new JLabel("这是第二个标签");     // 创建标签
              p2.add(l2);
              p2.setBackground(Color.GREEN);
      
              l3 = new JLabel("这是第三个标签");
              p3.add(l3);
              p3.setBackground(Color.BLUE);
      
              p1.addMouseListener(this);      // 设置鼠标事件侦听程序
              p2.addMouseListener(this);      // 设置鼠标事件侦听程序
              p3.addMouseListener(this);      // 设置鼠标事件侦听程序
      
              // 将每个Jpanel作为卡片加入Frame的内容窗格
              containerPane.add(p1,"First");  // First是p1的名字
              containerPane.add(p2,"Second");
              containerPane.add(p3,"Third");
      
              frame.setSize(300,200);
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              
          }
      
      }
      

5. BoxLayout布局管理器

  • 将容器中的组件按水平方向排成一行或按垂直方向排成一列

  • 排成一行时,每个组件可以有不同的宽度

  • 一列时,可以有不同的高度

  • 实例

    • public class Test {
      
          private JFrame frame;
          private JPanel pv,ph;
      
          public static void main(String[] args) {
              Test test = new Test();
              test.go();
          }
      
          public void go() {
              frame = new JFrame("World");
              Container contentPane = frame.getContentPane();
      
              pv = new JPanel();
              // 为pv设置为垂直方向的BoxLayout
              pv.add(new JLabel("First"));    // 为pv添加标签label
              pv.add(new Label("Second"));
              pv.add(new Label("Third"));
              // 将pv添加到内容窗格的中部
              contentPane.add(pv,BorderLayout.CENTER);
      
              ph = new JPanel();
              // 为ph设置水平方向的BoxLayout
              ph.setLayout(new BoxLayout(ph,BoxLayout.X_AXIS));
              ph.add(new JButton("Yes"));     // 为ph添加按钮
              ph.add(new JButton("No"));
              ph.add(new JButton("Cancel"));
              // 将ph添加到内容窗格的下部
              contentPane.add(ph,BorderLayout.SOUTH);
              frame.pack();
              frame.setVisible(true);
              
          }
      
      }
      

6. 空布局

  • 通过数值指定组件的位置和大小,需要将容器的布局管理器设置为空

    • 调用组件的 setBounds( )方法设置组件的位置和大小
  • 实例

    • public class Test {
      
          private JFrame frame;
          private JButton b1,b2,b3;
      
          public static void main(String[] args) {
              Test test = new Test();
              test.go();
      
          }
      
          void go() {
              frame = new JFrame("空布局");
              Container contentPane = frame.getContentPane();
              contentPane.setLayout(null);        // 将布局管理器设置为空
      
              b1 = new JButton("Yes");
              contentPane.add(b1);        // 添加按钮
      
              b2 = new JButton("No");
              contentPane.add(b2);
      
              b3 = new JButton("Cancel");
              contentPane.add(b3);
      
              // 设置按钮的位置和大小
              b1.setBounds(30,15,75,50);
              b2.setBounds(60,60,75,50);
              b3.setBounds(160,20,75,30);
      
              frame.setSize(300,200);
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          }
      
      }
      

五. 事件处理

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

1. 事件处理模型

  • 每当用户在组件上进行某种操作时,事件处理系统会生成一个事件类对象

  • 操作不同,事件类对象也会不同

  • 系统为了给每个事件类型提供一个侦听程序接口,规定了接收并处理该类事件的方法规范

  • 事件侦听程序

    • 为了接收某类用户事件,组件必须注册相应的事件处理程序
    • 作为侦听程序对象的类必须实现相应的接口,并实现接口中的方法
  • 委托事件处理模型

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

    • 1.程序中引入 Java.awt.event 包
    • 2.给所需的事件源对象注册事件侦听程序,事件源对象.addXXXListent(XXXListent);
    • 3.实现相应的方法
  • ActionEvent事件处理示例

    • public class Test {
      
          public static void main(String[] args) {
              JFrame frame = new JFrame("ActionEvent Demo");
              JButton btn = new JButton("点我");
              // 注册事件侦听程序
              btn.addActionListener(new ButtonHandler());
              // 添加按钮
              frame.getContentPane().add(btn,BorderLayout.CENTER);
              frame.pack();
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
          }
      
      }
      
      class ButtonHandler implements ActionListener {
      
          @Override
          public void actionPerformed(ActionEvent e) {
              System.out.println("触发了事件");
          }
      }
      
    • 事件的侦听程序可以定义在一个单独的类中,也可以定义在组件类中

  • 侦听程序定义在组件类中的示例

    • public class Test {
      
          public static void main(String[] args) {
              JFrame frame = new JFrame("ActionEvent Demo");
              JButton btn = new JButton("点我");
              // 注册事件侦听程序
              btn.addActionListener(new ButtonHandler());
              // 添加按钮
              frame.getContentPane().add(btn,BorderLayout.CENTER);
              frame.pack();
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
          }
      
      }
      
      class ButtonHandler implements ActionListener {
      
          @Override
          public void actionPerformed(ActionEvent e) {
              System.out.println("触发了事件");
          }
      }
      
    • 自定义的MyButton组件继承自JButton,同时实现了ActionListener接口

    • 在MyButton的构造方法中,通过addActionListenter(this)将自身注册为自己的侦听程序

    • 当用户单击按钮时,调用System.exit(0)结束运行

2. 事件的种类

  • 检查鼠标拖动示框

    • // 同时实现MouseListener接口和MouseListener
      public class Test implements MouseMotionListener,MouseListener {
      
          private JFrame frame;
          private JTextField tf;
      
          public static void main(String[] args) {
              Test test = new Test();
              test.go();
          }
      
          public void go() {
              frame = new JFrame("鼠标拖动实例");
              Container contentPane = frame.getContentPane();
              contentPane.add(new Label("点击鼠标"),BorderLayout.NORTH);
              tf = new JTextField(30);
              contentPane.add(tf,BorderLayout.SOUTH);
              // 注册侦听程序
              frame.addMouseMotionListener(this);
              frame.addMouseListener(this);
              frame.setSize(300,300);
              frame.setVisible(true);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
          }
      
          @Override
          public void mouseClicked(MouseEvent e) {
              String s = "点击";
              tf.setText(s);
          }
      
          @Override
          public void mousePressed(MouseEvent e) {
              String s = "按下";
              tf.setText(s);
          }
      
          @Override
          public void mouseReleased(MouseEvent e) {
              String s = "释放";
              tf.setText(s);
          }
      
          // 实现MouseListener接口中方法
          @Override
          public void mouseEntered(MouseEvent e) {
              String s = "The Mouse entered";
              tf.setText(s);
          }
      
          @Override
          public void mouseExited(MouseEvent e) {
              String s = "The mouse has left the building";
              tf.setText(s);
          }
      
          // 实现MouseMotionListener接口中的方法
          @Override
          public void mouseDragged(MouseEvent e) {
              String s = "Mouse Dragging: X = "+e.getX()+"Y="+e.getY();tf.setText(s);
          }
      
      
          @Override
          public void mouseMoved(MouseEvent e) {
              String s = "移动";
              tf.setText(s);
          }
      }
      

3. 事件适配器

  • 事件侦听模式允许为一个组件注册多个侦听程序

  • 通过在该事件的处理程序中编写需要的所有响应

  • 事件侦听模型允许多个调用addListener方法

  • 为了进行事件处理,需要创建实现Listener接口的类,需要一 一实现这些抽象方法

  • 在适配器类中实现了相应接口中的全部方法只是方法为空

  • 在创建新类时,可以不实现接口,只继承某个适当的适配器,并且重写所需要的方法

  • 适配器实例

    • // 同时实现MouseListener接口和MouseListener
      public class Test extends MouseAdapter  {
      
          // 只关心单击鼠标事件的处理,在这里继承MouseAdapter,并只覆盖有关的方法
          @Override
          public void mouseClicked(MouseEvent e) {
              System.out.println("鼠标点击了");
          }
      }
      

六. 绘图基础

1. 颜色

  • 使用Java.awt包中的Color类来定义和管理颜色
  • 有两种方法可以生成颜色
    • Color类中预定义的颜色,Color类中包含了26个常量
    • 通过红绿蓝三原色的值来进行组合,RGB值

2. 字体

  • 列出当前机器上所有的可用字体

    • public static void main(String[] args) {
          GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
          String[] fontName = env.getAvailableFontFamilyNames();
          System.out.println("可用字体:");
          for (int i = 0; i < fontName.length; i++) {
              System.out.println(" "+fontName[i]);
          }
      }
      

3. Graphics类的基本功能

  • Graphics是所有图形处理的基础,所有图形上下文的抽象父类
  • 绘图模式分为两种
    • setPaintMode( );将绘图模式设置为正常模式(默认模式)
    • setXORMode(Color c); 将绘图模式设置为异或模式,参数c指定了绘制对象时与窗口进行异或操作的颜色
  • 选择异或模式,如果使用同一颜色绘制两遍,则相当于擦除第一次绘制的图形,即恢复原来的状态

4. Graphics2D绘图

  • 为了解决图形对象的局限性。引入了Java2D,包括一个继承于Graphics类的Graphics2D类,增加了许多状态属性,扩展了Graphics的绘图功能

  • 图形状态属性

    • stroke属性
      • 控制属性线的宽度,笔形样式,线段连接方式,创建BasicSrtoke对象,再调用setStroke()方法即可设置其属性
    • paint属性
      • 属性控制填充效果,先调用GradientPanint()方法确定填充效果,再使用setPaint()方法进行设置
    • transform属性
      • 用来实现常用的图形平移,缩放,斜切等变化操作
    • clip属性
      • 用于实现剪裁效果,可以调用setClip()方法,确定剪裁区的Shape,从而设置剪裁属性
    • composit属性
      • 设置图形重叠区域的效果
  • Graphics2D类的绘图方法

    • 先在重画方法paintComponent()或paint()中,把参数对象g强制转换为Graphics2D对象

    • 然后用图形类提供的静态方法Double()创建该图形的对象

    • 最后,以图形对象为参数调用Graphics2D对象的draw()方法绘制

    • @Override
      protected void printComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;      // 将对象g类型Graphics转换为Graphics2D
          Line2D.Double line = new Line2D.Double(30.0, 30.0, 240.0, 30.0);    // 创建图形对象
          g2d.draw(line);         // 绘制线段
          RoundRectangle2D.Double rRect = new RoundRectangle2D.Double(13.0, 30.0, 100.0, 70.0, 40.0, 20.0);   
          g2d.draw(rRect);        // 绘制圆角矩形
      }
      
  • Graphics2D的几何图形类

    • 声明并创建线段对象,起点时(2,3) 终点是(200,300)

      • Line2D line = new Line2D.Double(2, 3, 200, 300);
        
    • 声明并创建矩形对象,矩形的左上角是(20,30) 宽是80 高是40

      • Rectangle2D drect = new Rectangle2D.Double(20, 30, 80, 40);
        
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐