GUI编程
一 简介
GUI的核心技术:AWT ,Swing
不流行的原因:
-
因为界面不美观
-
需要jre环境
为什么我们要学习?
- 可以写出自己心中想要的一些小工具,外挂等等
- 工作时候,也可能需要维护到swing界面,概率极小
- 了解MVC架构,了解监听
二 AWT
2.1 - AWT介绍
2.2 - 组件和容器
-
Frame
package com.gui; import java.awt.*; //GUI的第一个界面 public class GuiFrame { public static void main(String[] args) { //Frame,JDK,看源码 Frame frame = new Frame("我的第一个java图形界面窗口"); //设置可见性 frame.setVisible(true); //设置窗口大小 frame.setSize(500,500); //设置背景颜色 Color frame.setBackground(new Color(32,92,9)); //设置初始位置 frame.setLocation(300,300); //设置固定大小 frame.setResizable(false); } }
- 问题:发现装口关闭不掉,停止Java运行!
- 回顾封装:
public class GuiFrame { public static void main(String[] args) { //展示多个窗口 new MyFrame(100,100,200,200,Color.darkGray); new MyFrame(300,100,200,200,Color.blue); new MyFrame(100,300,200,200,Color.red); new MyFrame(300,300,200,200,Color.magenta); } } class MyFrame extends Frame{ static int id = 0;//可能存在多个窗口,我们需要一个计数器 public MyFrame(int x,int y,int w,int h,Color color){ super("MyFrame+ " + (++id));//Frame setVisible(true); //设置可见性 setBounds(x,y,w,h);//设置窗口大小初始位置 setBackground(color);//设置背景颜色 } }
-
Panel 面板
- 解决了关闭事件
//Panel 可以看成一个空间,但不能单独存在需要放到Frame中 public class GuiPanel { public static void main(String[] args) { Frame frame = new Frame(); //布局的概念 Panel panel = new Panel(); //设置布局 frame.setLayout(null); //坐标 frame.setBounds(300,300,500,500); frame.setBackground(new Color(128, 173, 64)); //Panel 设置坐标,相对frame panel.setBounds(50,50,400,400); panel.setBackground(new Color(179, 65, 65)); //panel加入frame frame.add(panel); frame.setVisible(true); //监听事件,监听窗口关闭事件 System.exit(0) /* 适配器模式 23种设计模式种的一种 */ frame.addWindowListener(new WindowAdapter() { //点击关闭的时候需要做的事情 @Override public void windowClosing(WindowEvent e) { // super.windowClosing(e); //结束程序 System.exit(0); } }); } }
2.3 - 布局管理器
-
流式布局
public class GuiFlowLayout { public static void main(String[] args) { Frame frame = new Frame(); //组件➡按钮 Button button1 = new Button("button1"); Button button2 = new Button("button2"); Button button3 = new Button("button3"); //设置为流式布局 // frame.setLayout(new FlowLayout()); 居中 frame.setLayout(new FlowLayout(FlowLayout.LEFT));//靠左 frame.setSize(200,200); //把按钮添加上去 frame.add(button1); frame.add(button2); frame.add(button3); //显示 frame.setVisible(true); } }
-
东西南北中
public class GuiBorderLayOut { public static void main(String[] args) { Frame frame = new Frame("BorderLayout"); //设置button 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 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); //设置frame frame.setSize(200,200); frame.setVisible(true); } }
-
表格布局
public class GuiGridLayout { public static void main(String[] args) { //设置btn Frame frame = new Frame(); Button btn1 = new Button("btn1"); Button btn2 = new Button("btn2"); Button btn3 = new Button("btn3"); Button btn4 = new Button("btn4"); Button btn5 = new Button("btn5"); Button btn6 = new Button("btn6"); //加入frame frame.setLayout(new GridLayout(3,2)); frame.add(btn1); frame.add(btn2); frame.add(btn3); frame.add(btn4); frame.add(btn5); frame.add(btn6); //frame设置 frame.pack();//Java函数!作用就是优化布局 frame.setVisible(true); } }
-
界面练习(Frame + Panel + Button)
public class GuiLayoutTest { public static void main(String[] args) { Frame frame = new Frame("界面练习"); frame.setSize(400,300); frame.setLocation(300,400); frame.setBackground(Color.GRAY); frame.setVisible(true); //上下两部分(表格布局上下-两行一列) frame.setLayout(new GridLayout(2,1)); //四个面板 //上面 Panel p1 = new Panel(new BorderLayout()); Panel p2 = new Panel(new GridLayout(2,1)); p1.add(new Button("East1"),BorderLayout.EAST); p1.add(new Button("West1"),BorderLayout.WEST); p2.add(new Button("p2-btn-1")); p2.add(new Button("p2-btn-2")); p1.add(p2,BorderLayout.CENTER); frame.add(p1); //下面 Panel p3 = new Panel(new BorderLayout()); Panel p4 = new Panel(new GridLayout(2,2)); p3.add(new Button("East2"),BorderLayout.EAST); p3.add(new Button("West2"),BorderLayout.WEST); for (int i = 1; i <= 4; i++) { p4.add(new Button("p4-btn-"+i)); } p3.add(p4); frame.add(p3); //关闭监听 frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } }
2.4 - 事件监听
-
按钮监听
public class GuiActionEvent { public static void main(String[] args) { //按下按钮,出发一些事件 Frame frame = new Frame(); Button button = new Button(); //因为,addActionListener()需要一个ActionListener,所以我们构造一个MyActionListener implements ActionListener MyActionListener myActionListener = new MyActionListener(); button.addActionListener(myActionListener); frame.add(button,BorderLayout.CENTER); frame.pack(); frame.setVisible(true); windowClosing(frame); } //关闭窗体事件监听 public static void windowClosing(Frame frame){ frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } } //事件监听 class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { System.out.println("AAA"); } }
-
多个按钮共享一个监听事件
public class GuiActionEvent { public static void main(String[] args) { /* 两个按钮实现同一个监听 开始,停止 */ Frame frame = new Frame("开始-停止"); Button startBtn = new Button("start"); Button stopBtn = new Button("stop"); /* 可以显示的定义出发会返回的命令,如果不显示定义,则会走默认的值 可以多个按钮只写一个监听类,监听类共用。 */ startBtn.setActionCommand("startBtn-start"); stopBtn.setActionCommand("stopBtn-stop"); MyMonitor myMonitor = new MyMonitor(); startBtn.addActionListener(myMonitor); stopBtn.addActionListener(myMonitor); frame.add(startBtn,BorderLayout.NORTH); frame.add(stopBtn,BorderLayout.SOUTH); frame.pack(); frame.setVisible(true); windowClosing(frame); } //关闭窗体事件监听 public static void windowClosing(Frame frame){ frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } } //事件监听 class MyMonitor implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { //e.getActionCommand() 获取按钮的信息 System.out.println("按钮被点击了:msg ➡ "+ e.getActionCommand()); if(e.getActionCommand().equals("startBtn-start")){ System.out.println("开始播放");//根据e.getActionCommand()的返回值不同会有不同的操作 } if(e.getActionCommand().equals("stopBtn-stop")){ System.out.println("停止播放"); } } }
2.5 - 输入框TextField监听
-
监听文本框种的文本
public class GuiTextField { public static void main(String[] args) { //启动 new MyFrame(); } } class MyFrame extends Frame{ public MyFrame(){ TextField textField = new TextField(); add(textField); //按下Enter,就会触发这个监听文本框输入的文字 textField.addActionListener(new MyActionListener()); //设置编码 textField.setEchoChar('*'); pack(); setVisible(true); } } class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { TextField field = (TextField) e.getSource();//获得一些资源,返回一个对象 System.out.println(field.getText());//获得输入框的文本 field.setText("");//回车清空,null是对象,”“是字符串 } }
2.6 - 简易计算器,组合+内部类回顾
-
oop原则,组合 > 继承
class A extends B{ //继承 } class A{ public B b;//组合,减小耦合性 }
-
目前的计算器
public class GuiCalc { public static void main(String[] args) { new Calculator(); } } //计算器类 class Calculator extends Frame{ public Calculator(){ //3个文本框 TextField num1 = new TextField(10); TextField num2 = new TextField(10); TextField num3 = new TextField(20); //一个标签 Label label = new Label("+"); //一个按钮 Button button = new Button("="); button.addActionListener(new CalculatorListener(num1,num2,num3)); //布局 setLayout(new FlowLayout()); add(num1); add(label); add(num2); add(button); add(num3); pack(); setVisible(true); } } //监听器类 class CalculatorListener implements ActionListener{ //获取三个变量 private TextField num1,num2,num3; public CalculatorListener(TextField num1,TextField num2,TextField num3 ){ this.num1 = num1; this.num2 = num2; this.num3 = num3; } @Override public void actionPerformed(ActionEvent e) { //1.获得num1 num2 int n1 = Integer.parseInt(num1.getText()); int n2 = Integer.parseInt(num2.getText()); //2.将这个值运算后,放到第三个框 num3.setText(""+(n1+n2)); //3.清空前两个框 num1.setText(""); num2.setText(""); } }
-
组合的方式,完全改造为oop
public class GuiCalc { public static void main(String[] args) { new Calculator().loadFrame(); } } //计算器类 class Calculator extends Frame{ //属性 TextField num1,num2,num3; //方法 public void loadFrame(){ //组件 num1 = new TextField(10);//字符数 num2 = new TextField(10); num3 = new TextField(20); Label label = new Label("+"); Button button = new Button("="); //监听 button.addActionListener(new CalculatorListener(this)); //布局 setLayout(new FlowLayout()); add(num1); add(label); add(num2); add(button); add(num3); pack(); setVisible(true); } } //监听器类 class CalculatorListener implements ActionListener{ //获取计算器这个对象,在一个类种组合另一个类 Calculator calculator = null; public CalculatorListener(Calculator calculator){ this.calculator = calculator; } @Override public void actionPerformed(ActionEvent e) { //1.获得num1 num2 int n1 = Integer.parseInt(calculator.num1.getText()); int n2 = Integer.parseInt(calculator.num2.getText()); //2.将这个值运算后,放到第三个框 calculator.num3.setText(""+(n1+n2)); //3.清空前两个框 calculator.num1.setText(""); calculator.num2.setText(""); } }
-
内部类
- 更好的包装
public class GuiCalc { public static void main(String[] args) { Calculator calculator = new Calculator(); calculator.loadFrame(); closing(calculator); } public static void closing(Frame frame){ frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } } //计算器类 class Calculator extends Frame{ //属性 TextField num1,num2,num3; //方法 public void loadFrame(){ //组件 num1 = new TextField(10);//字符数 num2 = new TextField(10); num3 = new TextField(20); Label label = new Label("+"); Button button = new Button("="); //监听 button.addActionListener(new CalculatorListener()); //布局 setLayout(new FlowLayout()); add(num1); add(label); add(num2); add(button); add(num3); pack(); setVisible(true); } //监听器类 //内部类最大的好处,就是可以畅通无阻的访问外部类的属性喝方法! private class CalculatorListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { //1.获得num1 num2 int n1 = Integer.parseInt(num1.getText()); int n2 = Integer.parseInt(num2.getText()); //2.将这个值运算后,放到第三个框 num3.setText(""+(n1+n2)); //3.清空前两个框 num1.setText(""); num2.setText(""); } } }
2.7 - 画笔
-
简单的操作
public class GuiPaint { public static void main(String[] args) { new MyPaint().loadFrame(); } } class MyPaint extends Frame{ public void loadFrame(){ setBounds(200,200,600,400); setVisible(true); } @Override public void paint(Graphics g) { //画笔需要有颜色,可以画画 g.setColor(Color.RED); // g.drawOval(100,100,100,100);//空心圆⚪ g.fillOval(100,100,100,100);//实心圆 g.setColor(Color.GREEN); g.fillRect(150,200,200,200);//实心矩形 //养成习惯,画笔用完将他还原到最初的颜色 } }
2.8 - 鼠标监听
-
目的:想要实现鼠标画画!
//鼠标监听事件 public class GuiMouseListener { public static void main(String[] args) { new MyPaintFrame("画图"); } } //自己的Frame class MyPaintFrame extends Frame{ //画画需要画笔,需要监听鼠标当前的位置,需要集合来存储这个点 ArrayList points; public MyPaintFrame(String title){ super(title); setBounds(200,200,400,300); //存鼠标的点 points = new ArrayList<>(); setVisible(true); //鼠标监听器,正对这个窗口 this.addMouseListener(new MyMouseListener()); } @Override public void paint(Graphics g) { //画画,监听鼠标的事件 Iterator iterator = points.iterator(); while (iterator.hasNext()){ Point point = (Point) iterator.next(); g.setColor(Color.BLUE); g.fillOval(point.x,point.y,10,10); } } //添加一个点到界面上面 public void addPaint(Point point){ points.add(point); } //适配器模式 private class MyMouseListener extends MouseAdapter { //鼠标: 按压,弹起,按住不放 @Override//按压 public void mousePressed(MouseEvent e) { MyPaintFrame myPaintFrame = (MyPaintFrame) e.getSource(); //这里点击的时候就会在界面产生一个点! //这个点就是鼠标的点 myPaintFrame.addPaint(new Point(e.getX(),e.getY())); //每次点击鼠标都需要重新画一次 myPaintFrame.repaint();//刷新 } } }
2.9 - 窗口监听
-
最常用窗口关闭(windowClosing)与激活(windowActivated)
public class GuiWindowListener { public static void main(String[] args) { new WindowFrame(); } } class WindowFrame extends Frame{ public WindowFrame(){ setBackground(Color.BLUE); setBounds(100,100,200,200); setVisible(true); this.addWindowListener(new WindowAdapter() { //关闭窗口 @Override public void windowClosing(WindowEvent e) { System.out.println("windowClosing"); System.exit(0); } //激活 @Override public void windowActivated(WindowEvent e) { WindowFrame source = (WindowFrame) e.getSource(); source.setTitle("被激活了"); System.out.println("windowActivated"); } }); } }
2.10 - 键盘监听
-
根据按下不同操作,产生不同结果
public class GuiKeyListener { public static void main(String[] args) { new KeyFrame(); } } class KeyFrame extends Frame{ public KeyFrame(){ setBounds(100,200,300,400); setVisible(true); this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { //键盘按下的键是哪个,当前的码 int keyCode = e.getKeyCode();//不需要记录这个16进制的值,直接使用静态属性 VK_xxx System.out.println(keyCode); if(keyCode == KeyEvent.VK_UP){ System.out.println("你按下了上键!"); } } }); } }
三 Swing
3.1 - 窗口,面板
-
第一个案例(JFrame,JLabel)
public class JFrameDemo { public static void main(String[] args) { //建立一个窗口 new MyJFrame().init(); } } class MyJFrame extends JFrame{ public void init(){ this.setBounds(10,10,200,300); this.setVisible(true); JLabel label = new JLabel("欢迎来到java世界"); this.add(label); //让文本标签居中,设置水平对齐 label.setHorizontalAlignment(SwingConstants.CENTER); //获取一个容器 Container container = this.getContentPane(); container.setBackground(Color.CYAN); } }
3.2 - 弹窗
-
JDialog,绑定JButton事件
//主窗口 public class DialogDemo extends JFrame { public static void main(String[] args) { new DialogDemo(); } public DialogDemo() { this.setVisible(true); this.setSize(700,500); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //JFrame放东西 ➡ 容器 Container container = this.getContentPane(); //绝对布局 container.setLayout(null); //按钮 JButton button = new JButton("点击弹出一个对话框");//创建 button.setBounds(30,30,200,50); container.add(button); //点击按钮的时候,弹出一个弹窗 button.addActionListener(new ActionListener() {//监听器 @Override public void actionPerformed(ActionEvent e) { //弹框 new MyDialog(); } }); } } //弹窗的窗口 class MyDialog extends JDialog{ public MyDialog(){ this.setVisible(true); this.setBounds(100,100,500,500); Container container = this.getContentPane(); container.setLayout(null); container.add(new Label("Welcome to the Java world")); } }
3.3 - 标签
-
Label
new JLabel("xxx");
-
图标 Icon
//图标,需要实现类,Frame继承 public class IconDemo extends JFrame implements Icon { private int width; private int height; /* 构造无参/有参 */ public IconDemo(){} public IconDemo(int width,int height){ this.width = width; this.height = height; } public void init(){ IconDemo icon = new IconDemo(15, 15); //图标放到标签上,也可以放到按钮上! JLabel label = new JLabel("icon test", icon, SwingConstants.CENTER); Container container = getContentPane(); container.add(label); this.setVisible(true); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new IconDemo().init(); } @Override public void paintIcon(Component c, Graphics g, int x, int y) { g.fillOval(x,y,width,height); } @Override public int getIconWidth() { return this.width; } @Override public int getIconHeight() { return this.height; } }
-
图片Icon(logo)
//图片(logo) public class ImageIconDemo extends JFrame { public ImageIconDemo() { JLabel label = new JLabel("ImageIcon"); //获取图片的地址 URL url = ImageIconDemo.class.getResource("tree.png"); ImageIcon imageIcon = new ImageIcon(url);//命名不要冲突 label.setIcon(imageIcon); label.setHorizontalAlignment(SwingConstants.CENTER); Container container = getContentPane(); container.add(label); setVisible(true); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setBounds(100,200,400,400); } public static void main(String[] args) { new ImageIconDemo(); } }
3.4 - 面板
-
JPanel
public class JPanelDemo extends JFrame { public static void main(String[] args) { new JPanelDemo(); } public JPanelDemo() { Container container = this.getContentPane(); container.setLayout(new GridLayout(2,1,10,10));//后面的参数的意思是间距 JPanel panel1 = new JPanel(new GridLayout(1, 3)); JPanel panel2 = new JPanel(new GridLayout(1, 2)); JPanel panel3 = new JPanel(new GridLayout(2, 1)); JPanel panel4 = new JPanel(new GridLayout(3, 2)); panel1.add(new JButton("1")); panel1.add(new JButton("1")); panel1.add(new JButton("1")); panel2.add(new JButton("2")); panel2.add(new JButton("2")); panel3.add(new JButton("3")); panel3.add(new JButton("3")); panel4.add(new JButton("4")); panel4.add(new JButton("4")); panel4.add(new JButton("4")); panel4.add(new JButton("4")); panel4.add(new JButton("4")); panel4.add(new JButton("4")); container.add(panel1); container.add(panel2); container.add(panel3); container.add(panel4); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); this.setVisible(true); this.setSize(500,500); } }
-
JscrollPanel
public class JScrollDemo extends JFrame { public JScrollDemo(){ Container container = this.getContentPane(); //文本域 JTextArea textArea = new JTextArea(20,50); textArea.setText("欢迎学习Java"); //Scroll面板 JScrollPane scrollPane = new JScrollPane(textArea); container.add(scrollPane); this.setVisible(true); this.setBounds(100,100,300,350); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JScrollDemo(); } }
3.5 - 按钮
-
图片按钮
public class JButtonDemo extends JFrame { public JButtonDemo(){ Container container = this.getContentPane(); //将图片编程图标 URL resource = JButtonDemo.class.getResource("tree.png"); Icon icon = new ImageIcon(resource); //把图标放到按钮上 JButton button = new JButton(); button.setIcon(icon); button.setToolTipText("图片按钮!"); //加入容器 container.add(button); this.setVisible(true); this.setSize(500,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JButtonDemo(); } }
-
单选框,圆形
public class JButtonDemo extends JFrame { public JButtonDemo(){ Container container = this.getContentPane(); //将图片编程图标 URL resource = JButtonDemo.class.getResource("tree.png"); Icon icon = new ImageIcon(resource); //单选框 JRadioButton radioButton01 = new JRadioButton("JRadioButton01"); JRadioButton radioButton02 = new JRadioButton("JRadioButton02"); JRadioButton radioButton03 = new JRadioButton("JRadioButton03"); //由于单选框只能选一个,一般分成一个组。 ButtonGroup group = new ButtonGroup(); group.add(radioButton01); group.add(radioButton02); group.add(radioButton03); //上中下 container.add(radioButton01,BorderLayout.CENTER); container.add(radioButton02,BorderLayout.SOUTH); container.add(radioButton03,BorderLayout.NORTH); this.setVisible(true); this.setSize(500,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JButtonDemo(); } }
-
多选框,方块
public class JButtonDemo extends JFrame { public JButtonDemo(){ Container container = this.getContentPane(); //将图片编程图标 URL resource = JButtonDemo.class.getResource("tree.png"); Icon icon = new ImageIcon(resource); //单选框 JCheckBox checkBox01 = new JCheckBox("checkBox01"); JCheckBox checkBox02 = new JCheckBox("checkBox02"); JCheckBox checkBox03 = new JCheckBox("checkBox03"); //多选不需要分组 //上中下 container.add(checkBox01,BorderLayout.CENTER); container.add(checkBox02,BorderLayout.SOUTH); container.add(checkBox03,BorderLayout.NORTH); this.setVisible(true); this.setSize(500,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JButtonDemo(); } }
3.6 - 列表
-
下拉框
public class ComboboxDemo extends JFrame { public ComboboxDemo(){ Container container = this.getContentPane(); JComboBox status = new JComboBox(); status.addItem(null); status.addItem("正在热映"); status.addItem("已下架"); status.addItem("即将上映"); container.add(status); this.setVisible(true); this.setSize(500,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new ComboboxDemo(); } }
-
列表框
public class ComboboxDemo extends JFrame { public ComboboxDemo(){ Container container = this.getContentPane(); //生成列表的内容 // String[] contents = {"1","2","3"}; Vector contents = new Vector(); contents.add("张三"); contents.add("李四"); contents.add("王五"); //列表需要放内容 JList list = new JList(contents); container.add(list); this.setVisible(true); this.setSize(500,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new ComboboxDemo(); } }
-
应用场景
- 下拉,选择地区,或者一些单项选项
- 列表,展示信息,一般是动态扩容
3.7 - 文本框
-
文本框
public class TextDemo extends JFrame { public TextDemo(){ Container container = this.getContentPane(); JTextField field01 = new JTextField("hello"); JTextField field02 = new JTextField("world",20); container.add(field01,BorderLayout.NORTH); container.add(field02,BorderLayout.SOUTH); this.setVisible(true); this.setSize(500,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new TextDemo(); } }
-
密码框
public class TextDemo extends JFrame { public TextDemo(){ Container container = this.getContentPane(); //面板 JPasswordField field = new JPasswordField();//**** field.setEchoChar('*'); container.add(field); this.setVisible(true); this.setSize(500,300); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new TextDemo(); } }
-
文本域
public class JScrollDemo extends JFrame { public JScrollDemo(){ Container container = this.getContentPane(); //文本域 JTextArea textArea = new JTextArea(20,50); textArea.setText("欢迎学习Java"); //Scroll面板 JScrollPane scrollPane = new JScrollPane(textArea); container.add(scrollPane); this.setVisible(true); this.setBounds(100,100,300,350); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); } public static void main(String[] args) { new JScrollDemo(); } }
贪吃蛇
-
帧,如果时间片足够小,就是动画,一秒30帧, 60帧通过人眼跟30帧差不多。连起来是动画,拆开就是静态的图片!
-
键盘监听
-
定时器 Timer
//数据中心 public class Data { private static URL headerURL = Data.class.getResource("statics/header.png"); public static ImageIcon header = new ImageIcon(headerURL); private static URL upURL = Data.class.getResource("statics/up.png"); private static URL downURL = Data.class.getResource("statics/down.png"); private static URL leftURL = Data.class.getResource("statics/left.png"); private static URL rightURL = Data.class.getResource("statics/right.png"); public static ImageIcon up = new ImageIcon(upURL); public static ImageIcon down = new ImageIcon(downURL); public static ImageIcon left = new ImageIcon(leftURL); public static ImageIcon right = new ImageIcon(rightURL); private static URL bodyURL = Data.class.getResource("statics/body.png"); public static ImageIcon body = new ImageIcon(bodyURL); private static URL foodURL = Data.class.getResource("statics/food.png"); public static ImageIcon food = new ImageIcon(foodURL); } //游戏的主启动类 public class GameStart { public static void main(String[] args) { JFrame frame = new JFrame(); frame.setBounds(10,10,900,720); frame.setResizable(false);//窗口大小不可变 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //正常游戏界面都应该在面板上! frame.add(new GamePanel()); frame.setVisible(true); } } //游戏的面板➡主操作 public class GamePanel extends JPanel implements KeyListener , ActionListener { //定义蛇的数据结构 int length;//蛇的长度 int[] snakeX = new int[600];//蛇的X坐标 25*30 int[] snakeY = new int[500];//蛇的Y坐标 25*25 String direction;//初始方向 //是否失败 boolean isFail = false; //失败状态 //食物的坐标 int foodX; int foodY; Random random = new Random(); //游戏当前的状态:开始/停止 boolean isStart = false; //默认停止 //定时器,以毫秒为单位 1000ms = 1s Timer timer = new Timer(100,this);//100毫秒执行一次 //积分 int score; public GamePanel(){ init(); //获得焦点和键盘事件 this.setFocusable(true);//获得焦点事件 this.addKeyListener(this);//获得键盘监听事件 timer.start();//游戏一开始就启动 score = 0; } //初始化方法 public void init(){ length = 3; snakeX[0] = 100; snakeY[0] = 100; //头坐标 snakeX[1] = 75; snakeY[1] = 100; //第一个身体的坐标 snakeX[2] = 50; snakeY[2] = 100; //第二个身体的坐标 direction = "R"; //初始方向向右 //把食物随机分布在界面上 foodX = 25 + 25*random.nextInt(34); foodY = 75 + 25*random.nextInt(24); } //绘制面板,我们游戏中的所有东西,都是用这个画笔 @Override protected void paintComponent(Graphics g) { super.paintComponent(g);//清屏 this.setBackground(Color.WHITE);//背景白色,默认 //绘制静态面板 Data.header.paintIcon(this,g,25,11);//头部广告栏画上去 g.fillRect(25,75,850,600);//默认的游戏界面 //画积分 g.setColor(Color.WHITE); g.setFont(new Font("微软雅黑",Font.BOLD,18));//设置字体 g.drawString("长度 "+length,750,35); g.drawString("分数 "+score,750,50); //画食物 Data.food.paintIcon(this,g,foodX,foodY); //把小蛇画上去 if(direction.equals("R")){ Data.right.paintIcon(this,g,snakeX[0],snakeY[0]); //蛇头初始化向右,通过方向来判断 }else if(direction.equals("L")){ Data.left.paintIcon(this,g,snakeX[0],snakeY[0]); //蛇头初始化向右,通过方向来判断 }else if(direction.equals("U")){ Data.up.paintIcon(this,g,snakeX[0],snakeY[0]); //蛇头初始化向右,通过方向来判断 }else if(direction.equals("D")){ Data.down.paintIcon(this,g,snakeX[0],snakeY[0]); //蛇头初始化向右,通过方向来判断 } for (int i = 1; i < length; i++) { Data.body.paintIcon(this,g,snakeX[i],snakeY[i]); //初始化第一个身体 } //游戏状态 if(isStart==false) { g.setColor(Color.WHITE); g.setFont(new Font("微软雅黑", Font.BOLD, 40));//设置字体 g.drawString("按下空格键开始游戏", 300, 300); } //失败状态 if(isFail){ g.setColor(Color.RED); g.setFont(new Font("微软雅黑",Font.BOLD,40));//设置字体 g.drawString("游戏失败,按下空格重新开始",300,300); } } //键盘监听事件 @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode();//获得键盘按键时哪个 if(keyCode == KeyEvent.VK_SPACE){//空格 if(isFail){ //重新开始 isFail = false; init(); }else{ isStart = !isStart;//取反 } repaint(); } //小蛇移动 if(keyCode == KeyEvent.VK_UP){ direction = "U"; }else if(keyCode == KeyEvent.VK_DOWN){ direction = "D"; }else if(keyCode == KeyEvent.VK_LEFT){ direction = "L"; }else if(keyCode == KeyEvent.VK_RIGHT){ direction = "R"; } } //事件监听 ➡ 需要通过固定事件来刷新,1s = 10次 @Override public void actionPerformed(ActionEvent e) { if(isStart && !isFail){//如果游戏时开始状态,就让小蛇动起来 //吃食物 if(snakeX[0] == foodX && snakeY[0] == foodY){ length++;//长度+1 score = score + 10;//积分+10 //再次随机分布食物 foodX = 25 + 25*random.nextInt(34); foodY = 75 + 25*random.nextInt(24); } //移动 for (int i = length - 1; i > 0; i--) {//后一节移动前一节的位置 snakeX[i] = snakeX[i-1]; snakeY[i] = snakeY[i-1]; } if(direction.equals("R")){ snakeX[0] = snakeX[0]+25; if(snakeX[0] > 850){snakeX[0] = 25;} }else if(direction.equals("L")){ snakeX[0] = snakeX[0]-25; if(snakeX[0] < 25){snakeX[0] = 850;} }else if(direction.equals("U")){ snakeY[0] = snakeY[0]-25; if(snakeY[0] < 75){snakeY[0] = 650;} }else if(direction.equals("D")){ snakeY[0] = snakeY[0]+25; if(snakeY[0] > 650 ){snakeY[0] = 75;} } //失败判定,撞到自己算失败 for (int i = 1; i < length; i++) { if(snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i]){ isFail = true; } } repaint();//重画页面 } timer.start();//定时器开启 } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } }
-
所需附件