第八章图形界面设置Swing(提升笔记)

    技术2022-07-11  79

    本来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);
    Processed: 0.014, SQL: 9