java GUI编程

一、GUI编程简介

  • GUI:图形用户界面,Graphical User Interface,简称 GUI,又称图形用户接口
  • 组件
    • 窗口
    • 弹窗
    • 面板
    • 文本框
    • 列表框
    • 按钮
    • 图片
    • 监听事件
      • 鼠标事件
      • 键盘事件
    • 外挂:因为Java是基于JVM运行的,所以不会被检测出来
    • 破解工具
  • 简介
    • GUI的核心技术:Swing AWT
    • 不流行的原因:
      • 因为界面不美观
      • 需要jre环境
    • 学习原因:
      • MVC架构的基础,后期需要了解MVC架构,了解监听
      • 可以写出自己心中想要的一些小工具
      • 工作时,可能需要维护到swing界面,概率很小,因为这个技术已经很老了

二、AWT

1、AWT介绍

  • AWT(抽象窗口工具)介绍
    • 包含了很多类和接口

    • Eclipse:就是java写的

    • 元素:窗口、按钮、文本框

    • java.awt包中

    • awt包总体框架:image-20220322081019722

    • 补充知识:java用的包都在rt.jar中,可解压打开

image-20220322081549980

2、Frame窗口程序实例

package www.xiaoxiao.com;

import java.awt.*;

public class FrameDemo {
    public static void main(String[] args) {
        Frame frame = new Frame("myFist window program");
        //设置可见性
        frame.setVisible(true);
        //设置长宽
        frame.setSize(400,400);
        //设置初使位置
        frame.setLocation(100,100);
        //设置背景颜色
        frame.setBackground(new Color(6, 248, 190));
        //设置固定大小
        frame.setResizable(false);
    }
}

image-20220322170811324

通过封装实现多个窗口:

package www.xiaoxiao.com;
import java.awt.*;
public class FrameDemo02 {
    public static void main(String[] args) {
        new MyFrame(100,100,400,400).setBackground(Color.BLUE);
        new MyFrame(600,100,400,400).setBackground(Color.CYAN);
        new MyFrame(600,600,400,400).setBackground(Color.black);
        new MyFrame(100,600,400,400).setBackground(Color.GRAY);
    }
}
class MyFrame extends Frame{
    static int id=0;//计数器
    public MyFrame(int x,int y,int w,int h)  {
        super("myFrame"+(id++));
        setLocation(x,y);//子类继承了父类的方法
        this.setLocation(x,y);//不管是用this还是super,子类现在并没有重写父类的方法,因此都是调用父类的方法
        //super.setLocation(x,y);
        setResizable(false);
        setSize(w,h);
        setVisible(true);
    }
}

image-20220322204723639

3、面板Panel实例

package www.xiaoxiao.com.AWT;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

//面板
public class PanelDemo {
    public static void main(String[] args) {
        Frame frame=new Frame();
        Panel panel=new Panel();
        frame.setVisible(true);
        frame.setBounds(200,200,400,400);
        frame.setBackground(Color.CYAN);
        panel.setBounds(100,100,200,200);//设置属性是相对于add到的容器来说的
        panel.setVisible(true);
        panel.setBackground(Color.BLUE);
        frame.add(panel);
        frame.setLayout(null);//不设置布局无效果,清空布局,默认布局是继承自Window的BorderLayout,会覆盖
        //设置关闭按钮监听
        //使用适配器模式,只重写窗口closeing事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);//返回0为正常退出
            }
        });
    }
}

image-20220323094605921

  • 补充:(为什么Frame要setvisible=true,而其他组件不需要设置)经调试,发现源码中:
    • Window(顶级窗口)的visible初始值为false(Frame.visible为false)image-20220324203044927
    • 而Component的visible的初始值为true,即按钮面板等组件的visible属性默认为trueimage-20220324203215855

4、Layout布局

  1. 流式布局:布局方式像流一样,可以指定以左中右为开始位置部件依次进行顺序排列
package www.xiaoxiao.com.AWT;

import java.awt.*;

public class LayoutDemo01 {
    public static void main(String[] args) {
        //流式布局:可以定义从中间、左、右来进行排列 ,add的组件按顺序依次排列
        Frame frame = new Frame("流式布局");
        Button btn1 = new Button("btn1");
        Button btn2 = new Button("btn2");
        Button btn3 = new Button("btn3");
        frame.add(btn1);
        frame.add(btn2);
        frame.add(btn3);
        frame.setVisible(true);
        frame.setSize(500,500);
        frame.setLayout(new FlowLayout(FlowLayout.LEFT));
        frame.setLayout(new FlowLayout(FlowLayout.RIGHT));
        frame.setLayout(new FlowLayout(FlowLayout.CENTER));
        frame.setLayout(new FlowLayout(FlowLayout.CENTER,50,50));//后面两个参数为组件间的间隙
    }
}
  1. 东南西北中布局(BorderLayout,Frame的默认布局)
package www.xiaoxiao.com.AWT;

import java.awt.*;

//东南西北中布局
public class LayoutDemo02 {
    public static void main(String[] args) {
        Frame frame = new Frame();//不写参数,标题就没有
        Button east = new Button("east");
        Button west = new Button("west");
        Button south = new Button("south");
        Button north = new Button("north");
        Button center = new Button("center");
        frame.setVisible(true);
        frame.setSize(500,500);
        //Frame的默认布局就是BorderLayout
        //BorderLayout borderLayout = new BorderLayout(50,50);
        //frame.setLayout(borderLayout);
        frame.add(east,BorderLayout.EAST);
        frame.add(west,BorderLayout.WEST);
        frame.add(south,BorderLayout.SOUTH);
        frame.add(north,BorderLayout.NORTH);
        frame.add(center,BorderLayout.CENTER);
        //如果add方法不指定第二个参数(容器),默认会写到BorderLayout.Center中,要注意一个组件对象只能写到一个地方,对同一个组件对象进行多次位置变化时,以最后一次变化为准
    }
}

image-20220323140318789

*:Frame继承自Window,window的初使化方法中默认设置为borderLayout,如下图。

image-20220323134641715

  1. 网格布局GridLayout
package www.xiaoxiao.com.AWT;

import java.awt.*;

public class LayoutDemo03 {
    public static void main(String[] args) {
        Frame frame=new Frame("GridLayout");
        Button bt1=new Button("bt1");
        Button bt2=new Button("bt2");
        Button bt3=new Button("bt3");
        Button bt4=new Button("bt4");
        Button bt5=new Button("bt5");
        frame.setVisible(true);
        frame.setSize(500,500);
        frame.setLayout(new GridLayout(2,3,50,50));
        frame.add(bt1);
        //frame.add(bt2);重复加没用
        frame.add(bt2);
        frame.add(bt3);
        frame.add(bt4);
        frame.add(bt5);
    }
}

image-20220323140147678

5、布局练习:实现下图的嵌套布局

image-20220324205616242

package www.xiaoxiao.com.AWT;

import javafx.scene.layout.Pane;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class LayoutTestDemo {
    public static void main(String[] args) {
        Frame frame = new Frame("课堂练习");
        Panel panel1=new Panel();
        Panel panel2=new Panel();
        Panel panel3=new Panel();
        Panel panel4=new Panel();
        panel1.setBackground(Color.CYAN);
        panel2.setBackground(Color.blue);
        frame.setBounds(300,300,300,300);
        frame.add(panel1);
        frame.add(panel2);
        panel1.setLayout(new BorderLayout());
        panel1.add(new Button("no1West"),BorderLayout.WEST);
        panel1.add(new Button("no1Eest"),BorderLayout.EAST);
        panel1.add(panel3);//默认为添加到BorderLayout.Center
        panel3.setLayout(new GridLayout(2,1));
        panel3.add(new Button("no1CenterNorth"));
        panel3.add(new Button("no1CenterSouth"));
        panel2.setLayout(new BorderLayout());
        panel2.add(new Button("no2West"),BorderLayout.WEST);
        panel2.add(new Button("no2Eest"),BorderLayout.EAST);
        panel2.add(panel4);
        panel4.setLayout(new GridLayout(2,2));
        panel4.add(new Button("btn1"));
        panel4.add(new Button("btn2"));
        panel4.add(new Button("btn3"));
        panel4.add(new Button("btn4"));
        frame.setLayout(new GridLayout(2,1));
        frame.setVisible(true);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

6、AWT(抽象窗口工具)总结

  • Frame是一个顶级窗口
  • Panel无法单独显示,必须添加到某个容器中
  • 布局管理器:
    • 流式
    • 东西南北中
    • 网格式

7、事件监听

  • 事件监听:当某个事情发生时,要执行什么操作

    • package www.xiaoxiao.com.AWT;
      import java.awt.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.event.WindowAdapter;
      import java.awt.event.WindowEvent;
      
      public class MonitorDemo01 {
          public static void main(String[] args) {
              //事件监听
              Frame frame=new Frame();
              Button button1=new Button("button");
              button1.addActionListener(new MyListener());
              frame.add(button1);
              frame.pack();//自适应
              WindowClose(frame);
              frame.setVisible(true);
          }
          //抽取方法
          private static void WindowClose(Frame frame){
              frame.addWindowListener(new WindowAdapter() {
                  @Override
                  public void windowClosing(WindowEvent e) {
                      System.exit(0);
                  }
              });
          }
      }
      class MyListener implements ActionListener{
          @Override
          public void actionPerformed(ActionEvent e) {
              System.out.println("aaa");
          }
      }
      
  • 多个部件共用一个监听事件

    • package www.xiaoxiao.com.AWT;
      
      import java.awt.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.util.Date;
      
      //多个组件共用一个监听
      public class MonitorDemo02 {
          public static void main(String[] args) {
              Frame frame = new Frame("start-stop");
              Button button1 = new Button("start");
              Button button2 = new Button("stop");
              button1.setActionCommand("already start");
              frame.setBounds(500,500,500,500);
              frame.setLayout(new FlowLayout());
              frame.add(button1);
              frame.add(button2);
              frame.setVisible(true);
              MyMonitor myMonitor=new MyMonitor();
              //这样做的好处是节省了代码
              button1.addActionListener(myMonitor);
              button2.addActionListener(myMonitor);
          }
      }
      class  MyMonitor implements ActionListener{
          @Override
          public void actionPerformed(ActionEvent e) {
              if (e.getActionCommand().equals("stop")){
                  System.out.print(new Date(e.getWhen()).toLocaleString()+": ");
                  System.out.println(e.getActionCommand());//如果组件中设置了ActionCommand则返回设置的,否则返回标题
              }else{
                  System.out.println("我没停止");
              }
          }
      }
      

8、文本框及其监听

package www.xiaoxiao.com.AWT;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

//输入框及其监听事件
public class TextFieldDemo {
    public static void main(String[] args) {
        //一般项目的main方法中只有一个启动方法
        new MyTestFrame();
    }
}
class MyTestFrame extends Frame{
    public MyTestFrame() throws HeadlessException {
        TextField textField=new TextField();
        add(textField);//相当于this.add()
        MyTestListener testListener=new MyTestListener();
        //TextField的监听事件是当回车按下
        textField.addActionListener(testListener);
        //设置回显字符(多用于密码密码)
        textField.setEchoChar('*');
        setVisible(true);
        pack();//自适应
        setLocation(400,440);
        setSize(500,500);
    }
}
class MyTestListener implements ActionListener{
    @Override
    public void actionPerformed(ActionEvent e) {
        TextField field=(TextField) e.getSource();//获取资源
        System.out.println(field.getText());
        field.setText(null);//按下回车后将文本框内容置为null
    }
}

9、简易计算机的实现

  • 原始代码

    //入口类
    public class SimplyCalc {
        public static void main(String[] args) {
            //程序入口
            new MyCalcFrame();
        }
    }
    //窗体实现类
    import java.awt.*;
    public class MyCalcFrame extends Frame {
        public MyCalcFrame(){
            TextField num1 = new TextField(10);//长度
            TextField num2 = new TextField(10);//长度
            TextField num3 = new TextField(20);//长度
            Button equal = new Button("=");
            Label label = new Label("+");
            equal.addActionListener(new MyListener(num1,num2,num3));
            setLayout(new FlowLayout());
            add(num1);
            add(label);
            add(num2);
            add(equal);
            add(num3);
            pack();//要在加之前用,否则会出错
            setLocation(500,500);
            setVisible(true);
        }
    }
    //监听实现类
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    public class MyListener implements ActionListener {
        private TextField num1;
        private TextField num2;
        private TextField num3;
        public MyListener(TextField num1, TextField num2, TextField num3) {
            this.num1=num1;
            this.num2=num2;
            this.num3=num3;
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            int n1 = Integer.parseInt(num1.getText());
            int n2 = Integer.parseInt(num2.getText());
            num3.setText(""+(n1+n2));
            num1.setText("");
            num2.setText("");
        }
    }
    
  • 使用组合的方式优化

    //入口
    public class SimplyCalc {
        public static void main(String[] args) {
            //程序入口
            new MyCalcFrame().load();
        }
    }
    //窗体实现类,将属性和方法抽离,使其更加对象化
    import java.awt.*;
    public class MyCalcFrame extends Frame {
        //属性,要写在构造方法前,否则MyListener无法引用
        TextField num1,num2,num3;
        //方法,直接调用方法
        public void load(){
            num1 = new TextField(10);//长度
            num2 = new TextField(10);//长度
            num3 = new TextField(20);//长度
            Button equal = new Button("=");
            Label label = new Label("+");
            equal.addActionListener(new MyListener(this));
            setLayout(new FlowLayout());
            add(num1);
            add(label);
            add(num2);
            add(equal);
            add(num3);
            pack();//要在加之前用,否则会出错
            setLocation(500,500);
            setVisible(true);
        }
    }
    
    //监听实现类,使用组合的方式,直接使用MyCalcFrame当做属性,可以简化代码
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class MyListener implements ActionListener {
        //使用组合的方法直接调用对象就可心使用里面的属性了
        private MyCalcFrame myCalcFrame=null;
        public MyListener(MyCalcFrame myCalcFrame) {
           this.myCalcFrame=myCalcFrame;
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            int n1 = Integer.parseInt(myCalcFrame.num1.getText());
            int n2 = Integer.parseInt(myCalcFrame.num2.getText());
            myCalcFrame.num3.setText(""+(n1+n2));
            myCalcFrame.num1.setText("");
            myCalcFrame.num2.setText("");
        }
    }
    
  • 使用内部类的方式(更好的包装)

    //内部类最大的好处,就是可以畅通无阻的访问外部的属性和方法
    //入口
    public class SimplyCalc {
        public static void main(String[] args) {
            //程序入口
            new MyCalcFrame().load();
        }
    }
    
    //实现
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    public class MyCalcFrame extends Frame {
        //属性,要写在构造方法前,否则MyListener无法引用
        TextField num1,num2,num3;
        //方法,直接调用方法
        public void load(){
            num1 = new TextField(10);//长度
            num2 = new TextField(10);//长度
            num3 = new TextField(20);//长度
            Button equal = new Button("=");
            Label label = new Label("+");
            equal.addActionListener(new MyListener());
            setLayout(new FlowLayout());
            add(num1);
            add(label);
            add(num2);
            add(equal);
            add(num3);
            pack();//要在加之前用,否则会出错
            setLocation(500,500);
            setVisible(true);
        }
        private class MyListener implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                int n1 = Integer.parseInt(num1.getText());
                int n2 = Integer.parseInt(num2.getText());
                num3.setText(""+(n1+n2));
                num1.setText("");
                num2.setText("");
            }
        }
    }
    
    

10、画笔

package www.xiaoxiao.com.AWT;
import java.awt.*;
public class PaintDemo {
    public static void main(String[] args) {
        new MyPaint().overLoad();
    }
}
class MyPaint extends Frame{
    public void overLoad(){
        setBounds(300,300,600,500);
        setVisible(true);//调用这个方法默认会调用repaint()方法进行重绘
    }
    @Override
    public void paint(Graphics g) {
        g.setColor(Color.CYAN);
        //g.drawRect(100,200,88,99);
        g.fillRect(100,200,88,99);
        g.setColor(Color.BLUE);
        //g.drawOval(200,200,100,100);
        g.fillOval(200,200,100,100);
        //一般来说在画笔使用完成后,要将其初始化为原始颜色,方便下次调用
        //默认为黑色
        g.setColor(Color.BLACK);
    }
}

11、鼠标监听,实现单击一下鼠标画一个点

  • 实现思想 image-20220331112011818
package www.xiaoxiao.com.AWT;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;

public class MousePaintPointDemo {
    public static void main(String[] args) {
        new MyMouseFrame("鼠标监听");
    }
}
//首先要有个窗体
class MyMouseFrame extends Frame{
    ArrayList points;
    public MyMouseFrame(String title){
        super(title);
        points=new ArrayList();
        setBounds(300,300,400,500);
        addMouseListener(new MyMouseLissener());
        setVisible(true);
    }
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Iterator iterator = points.iterator();
        while (iterator.hasNext()){
            Point next = (Point) iterator.next();
            g.setColor(Color.BLUE);
            g.fillOval(next.x,next.y,10,10);
        }
    }
    public void addPoint(Point point){
        points.add(point);
    }
    //单击鼠标监听事件,适配器模式
    class MyMouseLissener extends MouseAdapter{
        @Override
        public void mousePressed(MouseEvent e) {
            //鼠标单击时获取鼠标的位置(就是点的位置),将点加到ArrayList中
            //MyMouseFrame frame = (MyMouseFrame) e.getSource();//获取资源对象,为当前窗体
            int x = e.getX();//获取x坐标
            int y = e.getY();//获取y会标
            addPoint(new Point(x,y));
            repaint();
        }
    }
}

12、窗口监听

package www.xiaoxiao.com.AWT;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class WindowLinsenerDemo {
    public static void main(String[] args) {
        new MyFrame1();
    }
}
class MyFrame1 extends Frame{
    public MyFrame1() throws HeadlessException {
        setBounds(500,400,500,500);
        setBackground(Color.BLUE);
        setVisible(true);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("窗口正在关闭");
            }
            @Override
            public void windowIconified(WindowEvent e) {
                //窗口最小化
                System.out.println("窗口最小化");
            }
            @Override
            public void windowDeiconified(WindowEvent e) {
                //窗口从最小化恢复
                System.out.println("窗口从最小化恢复");
            }
            @Override
            public void windowActivated(WindowEvent e) {
                System.out.println("窗口激活");
            }
            @Override
            public void windowDeactivated(WindowEvent e) {
                System.out.println("窗口未激活");
            }
        });
    }
}

13、键盘监听

package www.xiaoxiao.com.AWT;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class KeyDemo {
    public static void main(String[] args) {
        new MyKeyFrame();
    }
}
class MyKeyFrame extends Frame{
    public MyKeyFrame() throws HeadlessException {
        setBounds(100,100,500,500);
        setVisible(true);
        addKeyListener(new KeyAdapter() {
            //键入字符
            @Override
            public void keyTyped(KeyEvent e) {
                int keyCode = e.getKeyCode();
                System.out.println((char) keyCode+"typed");
            }
            //按下
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                System.out.println((char)keyCode+"yaxia");
            }
            //弹起
            @Override
            public void keyReleased(KeyEvent e) {
                int keyCode = e.getKeyCode();
                System.out.println((char)keyCode+"released");
            }
        });
    }
}

三、Swing

  • Swing和AWT差不多,是在AWT的基础上进行的优化,多了一些组件等

1、JFrame窗口

  • 关于设置jFrame的背景
    • 在直接调用setBackground(Color.red)这个方法后,的确设置了JFrame的背景颜色,而你看到的却不是直接的JFrame,而是JFrame.getContentPane()。而JFrame上的contentPane默认是Color.WHITE的,所以,无论对JFrame怎么设置背景颜色,看到的都只是contentPane.
package www.xiaoxiao.com.Swing;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.colorchooser.ColorSelectionModel;
import java.awt.*;

public class WindowDemo {
    //初始化
    public void init(){
        JFrame jFrame = new JFrame();
        jFrame.setBounds(100,100,500,500);
        //不能直接设置背景
        //jFrame.setBackground(Color.BLUE);无效果
        //方法一:
        //1.获取容器
        Container contentPane = jFrame.getContentPane();
        //2.设置容器的颜色
        contentPane.setBackground(Color.blue);
        //方法二:jFrame.getContentPane().setVisible(false)将其设置为不可见,但这种方式会导致加进来的组件不可见
        //jFrame.getContentPane().setVisible(false);
        //jFrame.setBackground(Color.BLUE);
        contentPane.setLayout(new GridLayout(2,2));
        //面板
        JPanel jPanel = new JPanel();
        jPanel.setSize(20,20);
        //jPanel.setBounds(10,10,200,200);
        jPanel.setBackground(Color.CYAN);
        jFrame.add(jPanel);
        JPanel jPanel2 = new JPanel();
        jPanel2.setSize(20,20);
        //jPanel.setBounds(10,10,200,200);
        jPanel2.setBackground(Color.GRAY);
        jFrame.add(jPanel2);
        JLabel jLabel = new JLabel("hello world!");
        //设置水平居中
        jLabel.setHorizontalAlignment(SwingConstants.CENTER);
        jFrame.add(jLabel);
        //设置退出
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
    }
    public static void main(String[] args) {
        new WindowDemo().init();
    }
}

2、JDialog

package www.xiaoxiao.com.Swing;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

//弹窗
public class JDialogDemo {
    public JDialogDemo() {
        JFrame jFrame = new JFrame();
        jFrame.setBounds(100,100,800,400);
        Container contentPane = jFrame.getContentPane();
        contentPane.setBackground(Color.BLUE);
        JButton button = new JButton("click me");
        button.setBounds(100,100,200,50);
        //button监听
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new MyJDialogDemo();
            }
        });
        jFrame.add(button);
        //绝对布局
        jFrame.setLayout(null);
        //设置关闭退出
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
    }
    public static void main(String[] args) {
        new JDialogDemo();
    }
}
//JDialog框
class MyJDialogDemo extends JDialog{
    public MyJDialogDemo() {
        setBounds(200,200,90,90);
        setLayout(null);
        JLabel jLabel = new JLabel("1234567890");
        jLabel.setBounds(1,1,70,70);
        add(jLabel);
        this.setVisible(true);
    }
}

3、Icon和ImageIcon

  • 图标可以加到label和button等组件上。

  • 要实现Icon的重绘,需要实现Icon。

  • Icon:

    • package www.xiaoxiao.com.Swing;
      
      import javax.swing.*;
      import java.awt.*;
      
      //要实现Icon的绘制需要实现Icon
      public class IconDemo extends JFrame implements Icon {
          //定义一个宽和高(图标的宽和高)
          private int Width;
          private int Height;
          public static void main(String[] args) {
              new IconDemo(20,20);
          }
          public IconDemo(int width, int height) {
              Width = width;
              Height = height;
              JLabel icontest = new JLabel("icontest",this,SwingConstants.CENTER);
              //icontest.setIcon(this);
              //icontest.setHorizontalAlignment(SwingConstants.CENTER);
              setBounds(100,100,500,500);
              add(icontest);
              setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
              setVisible(true);
          }
          @Override
          public void paintIcon(Component c, Graphics g, int x, int y) {
              g.fillOval(x,y,Width,Height);//x,y为位置
          }
          @Override
          public int getIconWidth() {
              return Width;
          }
          @Override
          public int getIconHeight() {
              return Height;
          }
      }
      
      
  • ImageIcon:是Icon的一个实现类,不是接口

    • package www.xiaoxiao.com.Swing;
      
      import javax.imageio.ImageIO;
      import javax.swing.*;
      import java.net.URL;
      
      public class ImageIconDemo extends JFrame {
          public ImageIconDemo() throws Exception{
              URL resource = ImageIconDemo.class.getResource("tx.jpg");//获取当前目录下的文件,需要重新编译
              setBounds(100,110,500,500);
              ImageIcon imageIcon = new ImageIcon(resource);//参数为url类型
              JLabel test = new JLabel("test", imageIcon, SwingConstants.CENTER);
              add(test);
              setIconImage(ImageIO.read(resource));//JFrame设置图标
              setVisible(true);
          }
          public static void main(String[] args) throws Exception{
              new ImageIconDemo();
          }
      }
      

4、面板Jpanel和JScrollPanel

  • JPanel

    package www.xiaoxiao.com.Swing;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class JpanelDemo extends JFrame {
        public JpanelDemo() throws HeadlessException {
            setLayout(new GridLayout(2,2,10,10));//第三、四个参数为间距
            setBounds(100,100,500,500);
            JPanel jPanel1 = new JPanel(new GridLayout(1, 2));
            JPanel jPanel2 = new JPanel(new GridLayout(2, 1));
            JPanel jPanel3 = new JPanel(new GridLayout(3, 2));
            JPanel jPanel4 = new JPanel(new GridLayout(2, 3));
            add(jPanel1);
            add(jPanel2);
            add(jPanel3);
            add(jPanel4);
            jPanel1.add(new JButton("1"));
            jPanel1.add(new JButton("1"));
            jPanel2.add(new JButton("2"));
            jPanel2.add(new JButton("2"));
            jPanel3.add(new JButton("3"));
            jPanel3.add(new JButton("3"));
            jPanel3.add(new JButton("3"));
            jPanel3.add(new JButton("3"));
            jPanel3.add(new JButton("3"));
            jPanel3.add(new JButton("3"));
            jPanel4.add(new JButton("4"));
            jPanel4.add(new JButton("4"));
            jPanel4.add(new JButton("4"));
            jPanel4.add(new JButton("4"));
            jPanel4.add(new JButton("4"));
            jPanel4.add(new JButton("4"));
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setVisible(true);
        }
        public static void main(String[] args) {
            new JpanelDemo();
        }
    }
    

    image-20220402190524802

  • JScrollPanel

    package www.xiaoxiao.com.Swing;
    import javax.swing.*;
    import java.awt.*;
    public class JScrollPanelDemo extends JFrame {
        public JScrollPanelDemo() throws HeadlessException {
            Container container=getContentPane();
            setBounds(100,100,500,500);
            TextArea textArea = new TextArea(20, 50);
            JScrollPane jScrollPane = new JScrollPane(textArea);
            add(jScrollPane);
            setVisible(true);
        }
        public static void main(String[] args) {
            new JScrollPanelDemo();
        }
    }
    

    image-20220402193618676

5、按钮

  • 图片按钮

    package www.xiaoxiao.com.Swing;
    
    import javax.swing.*;
    import java.awt.*;
    import java.net.URL;
    
    public class ImageButtonDemo extends JFrame {
        //图片按钮就是给普通迎按钮加个图片
        public ImageButtonDemo() {
            //获取容器,用JFrame尽量用Container进行add等操作
            Container contentPane = getContentPane();
    
            URL resource = ImageButtonDemo.class.getResource("tx.jpg");//直接获取同级目录下的图片
            ImageIcon imageIcon=new ImageIcon(resource);//创建一个ImageIcon,需要一个URL参数
            JButton but1 = new JButton();
            but1.setIcon(imageIcon);
            but1.setToolTipText("这是一个图片按钮");//设置鼠标悬浮提示
            contentPane.add(but1);
    
    
            setSize(500,400);
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setVisible(true);
    
        }
    
        public static void main(String[] args) {
            new ImageButtonDemo();
        }
    }
    
  • 单选按钮

    package www.xiaoxiao.com.Swing;
    
    import javax.swing.*;
    import java.awt.*;
    import java.net.URL;
    
    public class RadioButtonDemo extends JFrame {
        //图片按钮就是给普通迎按钮加个图片
        public RadioButtonDemo() {
            //获取容器,用JFrame尽量用Container进行add等操作
            Container contentPane = getContentPane();
            contentPane.setLayout(new GridLayout(3,1));
    
            JRadioButton jRadioButton01 = new JRadioButton("JRadioButton01");
            JRadioButton jRadioButton02 = new JRadioButton("JRadioButton02");
            JRadioButton jRadioButton03 = new JRadioButton("JRadioButton03");
            //单选按钮要实现多个按钮一个可选,需要添加到同一个组中
            ButtonGroup buttonGroup = new ButtonGroup();
            buttonGroup.add(jRadioButton01);
            buttonGroup.add(jRadioButton02);
            buttonGroup.add(jRadioButton03);
            contentPane.add(jRadioButton01);
            contentPane.add(jRadioButton02);
            contentPane.add(jRadioButton03);
    
            setSize(500,400);
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setVisible(true);
    
        }
    
        public static void main(String[] args) {
            new RadioButtonDemo();
        }
    }
    

    image-20220402222326844

  • 复选框按钮

    package www.xiaoxiao.com.Swing;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class CheckedButtonDemo extends JFrame {
        //图片按钮就是给普通迎按钮加个图片
        public CheckedButtonDemo() {
            //获取容器,用JFrame尽量用Container进行add等操作
            Container contentPane = getContentPane();
            contentPane.setLayout(new GridLayout(3, 1));
    
            JCheckBox jCheckBox1= new JCheckBox("jCheckBox1");
            JCheckBox jCheckBox2= new JCheckBox("jCheckBox2");
            JCheckBox jCheckBox3= new JCheckBox("jCheckBox3");
            jCheckBox3.setToolTipText("test");
            contentPane.add(jCheckBox1);
            contentPane.add(jCheckBox2);
            contentPane.add(jCheckBox3);
    
            setSize(500, 400);
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setVisible(true);
    
        }
    
        public static void main(String[] args) {
            new CheckedButtonDemo();
        }
    }
    
    

    image-20220402223107793

6、列表框

  • 下拉列表

    package www.xiaoxiao.com.Swing;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class JComboboxDemo extends JFrame {
    
        public JComboboxDemo() throws HeadlessException {
            Container contentPane = getContentPane();
    
            JComboBox jComboBox = new JComboBox();
            //下拉列表需要加项
            jComboBox.addItem("1");
            jComboBox.addItem("2");
            jComboBox.addItem("3");
            contentPane.add(jComboBox);
            setSize(400,500);
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setVisible(true);
    
        }
    
        public static void main(String[] args) {
            new JComboboxDemo();
        }
    }
    
  • 列表框

    package www.xiaoxiao.com.Swing;
    
    import javax.swing.*;
    import java.awt.*;
    import java.util.ArrayList;
    import java.util.Vector;
    
    public class DropListDemo  extends JFrame {
    
        public DropListDemo() throws HeadlessException {
            Container contentPane = getContentPane();
            //String[] arrs={"","1","2"};
            //下拉列表,一般使用可动态扩容的数据类型,如Vector,这个地方不能用ArrayList,会报错,用数组可以
            Vector vector=new Vector();
            vector.add("1");
            vector.add("2");
            vector.add("3");
            JList jList = new JList(vector);
            contentPane.add(jList);
            setSize(400,500);
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setVisible(true);
    
        }
    
        public static void main(String[] args) {
            new DropListDemo();
        }
    }
    

7、文本框

  • 文本框、密码框、文本域

    package www.xiaoxiao.com.Swing;
    
    import javafx.scene.control.PasswordField;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class TextFiledDemo extends JFrame {
        public TextFiledDemo() throws HeadlessException {
            Container contentPane = getContentPane();
            contentPane.setLayout(new GridLayout(4,1));
            //文本框
            JTextField jTextField = new JTextField("1",20);
            JTextField jTextField2 = new JTextField("2");
            //密码文本框
            JPasswordField passwordField = new JPasswordField();
            //passwordField.setEchoChar('*');
    
            TextArea textArea = new TextArea();
    
            contentPane.add(jTextField);
            contentPane.add(jTextField2);
            contentPane.add(passwordField);
            contentPane.add(textArea);
    
    
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setSize(500,500);
            setVisible(true);
    
    
        }
    
        public static void main(String[] args) {
            new TextFiledDemo();
        }
    }
    
    

四、贪吃蛇小游戏

  • 帧的概念:

    • 时间片足够小,就形成了动画,一般游戏一秒30帧或60帧,拆开就是静态的图片。
    • 要注意绘制顺序
    //Snake类
    import javax.swing.*;
    //程序主入口
    public class Snake  {
        public static void main(String[] args) {
            JFrame jFrame = new JFrame();
            jFrame.add(new GamePanel());
            jFrame.setResizable(false);
            jFrame.setBounds(100,100,920,800);
            jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            jFrame.setVisible(true);
        }
    }
    
    
    
    //面板绘制类GamePanel
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.Random;
    
    import static java.awt.Font.BOLD;
    import static java.awt.Font.ITALIC;
    
    //面板,所有操作均在面板上实现
    public class GamePanel extends JPanel implements KeyListener, ActionListener {
        //定义小蛇数据结构
        int length;//小蛇长度
        int snakeX[];//小蛇的X坐标位置数据
        int snakeY[];//小蛇的Y坐标位置数据
        String orientation;//蛇头方向
        boolean status;//定义游戏状态:开始-停止
        boolean fail;//定义失败状态
        //食物坐标
        int foodx;
        int foody;
        Random random;
        int score;
        Timer timer = new Timer(100, this);//创建一个定时器
    
        public GamePanel() {
            init();
            //设置焦点,默认为false
            setFocusable(true);
            //加键盘监听
            addKeyListener(this);
        }
    
        //初使化
        private void init() {
            length = 3;//默认长度为3
            score=0;//分数
            snakeX = new int[34];//小蛇的X坐标位置数据
            snakeY = new int[26];//小蛇的Y坐标位置数据
            snakeX[0] = 125;
            snakeY[0] = 100;//小蛇头
            snakeX[1] = 100;
            snakeY[1] = 100;//小蛇身体
            snakeX[2] = 75;
            snakeY[2] = 100;//小蛇身体
            orientation = "right";//默认方向为向右
            status = false;
            timer.start();//计时器开始
            random = new Random();//生成食物用
            //绘制食物
            foodx = 25 + 25 * random.nextInt(33);
            foody = 75 + 25 * random.nextInt(25);
            fail = false;
        }
    
        //绘制方法,显示时自动调用
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);//有清屏功能,如果不清屏会闪烁
            //绘制静态面板
            setBackground(Color.WHITE);
            g.setColor(Color.CYAN);
            //g.fillRect(25, 15, 850, 55);//游戏界面面板
            //给一个组件绘制Icon
            Data.headerIcon.paintIcon(this, g, 0, 15);//头部广告栏绘制
            g.setColor(Color.BLUE);
            g.setFont(new Font("宋体", BOLD | ITALIC, 32));
            g.drawString("小狗平招商位", 75, 55);
            g.setColor(Color.RED);
            g.setFont(new Font("宋体", BOLD | ITALIC, 16));
            g.drawString("小蛇长度:"+length, 750, 45);
            g.drawString("得分:"+score, 750, 58);
    
            g.setColor(Color.BLACK);
            g.fillRect(25, 75, 850, 650);//游戏界面面板
            //小蛇静态绘制
            //通过循环绘制身体
            for (int i = 1; i <length; i++) {
                Data.bodyIcon.paintIcon(this, g, snakeX[i], snakeY[i]);
            }
            //根据方向画蛇头
            switch (orientation) {
                case "right":
                    Data.rightIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
                    break;
                case "left":
                    Data.leftIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
                    break;
                case "up":
                    Data.upIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
                    break;
                case "down":
                    Data.downIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
                    break;
            }
            Data.foodIcon.paintIcon(this, g, foodx, foody);
    
    
            if (status == false) {
                g.setColor(Color.WHITE);
                g.setFont(new Font("微软雅黑", BOLD | ITALIC, 32));
                g.drawString("按下空格开始游戏", 320, 400);
            }
            if (fail==true){
                g.setColor(Color.red);
                g.setFont(new Font("微软雅黑", BOLD | ITALIC, 32));
                g.drawString("失败喽,按下空格重新开始游戏", 320, 400);
            }
        }
    
        //键盘按下
        @Override
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();
    
            switch (keyCode) {
                case KeyEvent.VK_SPACE:
                    //按下空格取反,并重绘
                    if (fail==false){
                        status = !status;
                    }else{
                        fail=true;
                        init();
                    }
                    repaint();
                    break;
    
                case KeyEvent.VK_UP:
                    orientation = "up";
                    break;
                case KeyEvent.VK_DOWN:
                    orientation = "down";
                    break;
                case KeyEvent.VK_RIGHT:
                    orientation = "right";
                    break;
                case KeyEvent.VK_LEFT:
                    orientation = "left";
                    break;
            }
        }
    
        @Override
        public void keyReleased(KeyEvent e) {
    
        }
    
        @Override
        public void keyTyped(KeyEvent e) {
    
        }
    
        //事件监听,用于定时器,每100ms执行一次,让小蛇动起来
        @Override
        public void actionPerformed(ActionEvent e) {
            if (status && !fail) {
    
                //如果状态为true,让小蛇动起来
                for (int i = length - 1; i > 0; i--) {
                    //前一项赋值给后一项
                    snakeX[i] = snakeX[i-1];
                    snakeY[i] = snakeY[i-1];
                }
                switch (orientation) {
                    case "right"://向右
                        snakeX[0] = snakeX[0] + 25;//头动起来
                        if (snakeX[0] > 850) {
                            snakeX[0] = 25;
                        }
                        break;
                    case "left"://向左
                        snakeX[0] = snakeX[0] - 25;//头动起来
                        if (snakeX[0] < 25) {
                            snakeX[0] = 850;
                        }
                        repaint();
                        break;
                    case "up"://向上
                        snakeY[0] = snakeY[0] - 25;//头动起来
                        if (snakeY[0] < 75) {
                            snakeY[0] = 700;
                        }
                        repaint();
                        break;
                    case "down"://向下
                        snakeY[0] = snakeY[0] + 25;//头动起来
                        if (snakeY[0] > 700) {
                            snakeY[0] = 75;
                        }
                        break;
                }
    
                //判断小蛇死亡
                for (int j = 1; j < length; j++) {
                    if (snakeX[0]==snakeX[j] && snakeY[0]==snakeY[j]){
                        fail=true;
                        repaint();
                    }
                }
                if (snakeX[0] == foodx && snakeY[0] == foody) {
                    //重绘食物
                    foodx = 25 + 25 * random.nextInt(33);
                    foody = 75 + 25 * random.nextInt(25);
                    length++;//小蛇长度+1
                    snakeX[length-1]=snakeX[length-2];
                    snakeY[length-1]=snakeY[length-2];
                    score+=10;
    
                }
    
                repaint();
            }
    
        }
    }
    
    
    //静态资源类Data
    import javax.swing.*;
    import java.awt.*;
    import java.net.URL;
    
    public class Data {
        //Data.class.getResource这个路径是src的路径
        public static URL header =Data.class.getResource("/static/header.png");
        public static ImageIcon headerIcon=new ImageIcon(header);
        public static URL up =Data.class.getResource("/static/up.png");
        public static ImageIcon upIcon=new ImageIcon(up);
        public static URL down =Data.class.getResource("/static/down.png");
        public static ImageIcon downIcon=new ImageIcon(down);
        public static URL left =Data.class.getResource("/static/left.png");
        public static ImageIcon leftIcon=new ImageIcon(left);
        public static URL right =Data.class.getResource("/static/right.png");
        public static ImageIcon rightIcon=new ImageIcon(right);
        public static URL food =Data.class.getResource("/static/food.png");
        public static ImageIcon foodIcon=new ImageIcon(food);
        public static URL body =Data.class.getResource("/static/body.png");
        public static ImageIcon bodyIcon=new ImageIcon(body);
    }
    

    image-20220406200740107

posted @ 2022-04-07 22:09  是韩信啊  阅读(143)  评论(0编辑  收藏  举报