JavaSE:GUI编程入门到游戏实战
JavaSE:GUI编程入门到游戏实战
文章目录
- 前言
- 一、GUI编程简介
- 二、AWT(底层的实现)
- 1. Awt介绍
- 1. 简单介绍
- 2. 组件
- 2. 组件和容器(核心)
- 2.1 容器、组件
- 1. Frame
- 2. Panel面板详解
- 3. 布局管理器(3种)
- 4. 小总结
- 2.2 事件监听
- 5. 事件监听
- 6. 输入框(TextField)事件监听
- 7. 简易计算器、组合+内部类 回顾复习!
- 8. 画笔 paint
- 9. 鼠标监听事件、模拟画图工具
- 10. 窗口监听事件
- 11. 键盘监听事件
- 三、Swing(界面)
- Ⅰ、窗口
- 1. JFrame窗体
- Ⅱ、弹窗
- 2. JDialog弹窗
- Ⅲ、标签
- 3. Icon、ImageIcon标签
- Ⅳ、面板
- 4. 文本域JScroll面板
- Ⅴ、按钮
- 5. 图片按钮、单选框、多选框
- Ⅵ、列表
- 6. 下拉框、列表框
- Ⅶ、文本框
- 7. 文本框、密码框、文本域
- 四、一小时开发贪吃蛇游戏
- 0. 游戏演示和动画帧的概念
- 1. 贪吃蛇之界面绘制
- 2. 绘制静态的小蛇
- 3. 让小蛇动起来
- 4. 键盘控制小蛇移动
- 5. 小蛇吃食物长大
- 6. 失败判定、积分系统
- 7. 小总结
- 总结:GUI阶段回顾与总结
前言
即使再小的帆也能远航
一、GUI编程简介
- 图形界面编程
- 组件
- 窗口
- 弹窗
- 面板
- 文本框
- 列表框
- 按钮
- 图片
- 交互
- 监听事件
- 鼠标事件
- 键盘事件
- 外挂
- 破解工具
- 核心开发技术:
- Swing/AWT(类)
- 不流行原因:
- 因为界面不美观
- 需要jre环境
- 学习GUI原因:
- 可以写出一些自己心中想要的小工具
- 工作时候,也可以需要维护到swing界面,概率极小
- 了解MVC架构,了解监听(MVC架构的基础)
二、AWT(底层的实现)
1. Awt介绍
1. 简单介绍
- 抽象的窗口工具 abstract Windows tools
- new 类!
- 包含了很多类和接口!
- GUI:图形、用户、界面、编程
- eclipse:用Java写的
- 元素:窗口、按钮、文本框…
- java核心包(文件管理器 文件夹中: environment - jdk - jre - lib - rt.jar - java - awt)
2. 组件
- 组件 Component
- 按钮 button(基本组件(存放在容器中add))
- 文本域 TextArea
- 标签 label
- 容器 Container
- 窗口实现 Windows
- 窗口 frame
- 弹窗 dialog
- 面板 panel
- 对话 applet
- 窗口实现 Windows
2. 组件和容器(核心)
2.1 容器、组件
1. Frame
package com.demo8_gui.demo01_awt;import java.awt.*;//GUI的第一个界面
public class TestFrame {public static void main(String[] args) {//Frame,JDK,看源码(Ctrl+鼠标点击代码,进入源码,点击窗口左侧structure,查看更多相关)!Frame frame = new Frame("我的第一个Java图像界面窗口");//需要设置可见性frame.setVisible(true);//设置窗口大小 w hframe.setSize(400,400);//设置背景颜色 Color
// public Color(int r, int g, int b) { //三原色,红绿蓝
// this(r, g, b, 255);
// }
// frame.setBackground(Color.BLACK);frame.setBackground(new Color(139, 231, 82));//弹出的初始位置frame.setLocation(960,540);//设置大小固定 默认true (false 大小不可变)frame.setResizable(false);//窗口默认功能:可以最小化,不可以关闭(可以通过终止程序运行)}
}
发现问题:窗口关闭不掉,停止java程序运行
回顾封装:
(多个窗口)
package com.demo8_gui.demo01_awt;import java.awt.*;public class TestFrame2 {public static void main(String[] args) {//展示多个窗口 newMyFrame myFrame1 = new MyFrame(100, 100, 200, 200, Color.red);MyFrame myFrame2 = new MyFrame(300, 100, 200, 200, Color.green);MyFrame myFrame3 = new MyFrame(100, 300, 200, 200, Color.blue);MyFrame myFrame4 = new MyFrame(300, 300, 200, 200, Color.black);}
}class MyFrame extends Frame{static int id = 0;//可能存在多个窗口,我们需要一个计数器public MyFrame(int x,int y,int w,int h,Color color){super("MyFrame+"+(++id));setVisible(true);setBounds(x,y,w,h);setBackground(color);}
}
2. Panel面板详解
frame窗口唯一
将Panel面板放入frame
按钮等组件放在面板上
解决了关闭事件!
package com.demo8_gui.demo01_awt;import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;//Panel 可以看成一个空间,但是不能单独存在
public class TestPanel {public static void main(String[] args) {Frame frame = new Frame();//布局的概念Panel panel = new Panel();//设置布局 不设置这个布局,panel会完全覆盖掉frame的窗口内部frame.setLayout(null);//坐标frame.setBounds(300,300,500,500);frame.setBackground(Color.green);//Panel设置坐标,相对于framepanel.setBounds(50,50,400,400);panel.setBackground(new Color(246, 62, 39));//往frame里添加一个Panelframe.add(panel);frame.setVisible(true);//监听事件,监听窗口关闭事件 System.exit(0)//适配器模式 :写个抽象类,里面的方法空实现,实现类负责重写指定方法即可frame.addWindowListener(new WindowAdapter() {//窗口点击关闭时需要做的事情@Overridepublic void windowClosing(WindowEvent e) {//结束程序System.exit(0);}});}
}
3. 布局管理器(3种)
- 流式布局
package com.demo8_gui.demo01_awt;import java.awt.*;public class TestFlowLayout {public static void main(String[] args) {Frame frame = new Frame();frame.setSize(200,200);//组件-按钮Button button1 = new Button("button1");Button button2 = new Button("button2");Button button3 = new Button("button3");//设置为流式布局frame.setLayout(new FlowLayout());//水平居中
// frame.setLayout(new FlowLayout(0));
// frame.setLayout(new FlowLayout(FlowLayout.RIGHT));//把按钮添加上去frame.add(button1);frame.add(button2);frame.add(button3);frame.setVisible(true);}
}
- 东西南北中
package com.demo8_gui.demo01_awt;import java.awt.*;public class TestBorderLayout {public static void main(String[] args) {Frame frame = new Frame("TestBorderLayout");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.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.setSize(200,200);frame.setVisible(true);}
}
- 表格布局
package com.demo8_gui.demo01_awt;import java.awt.*;public class TestGridLayout {public static void main(String[] args) {Frame frame = new Frame("TestGridLayout");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.setLayout(new GridLayout(3,2));//3行2列frame.add(btn1);frame.add(btn2);frame.add(btn3);frame.add(btn4);frame.add(btn5);frame.add(btn6);frame.pack();//Java函数!自动选择一个最优秀的布局frame.setVisible(true);}
}
练习
package com.demo8_gui.demo01_awt;import java.awt.*;public class ExecDemo {public static void main(String[] args) {Frame frame = new Frame("test");//总 frameframe.setBounds(200,200,400,300);frame.setVisible(true);frame.setLayout(new GridLayout(2,1));//2行1列Panel p1 = new Panel(new BorderLayout());//第一行Panel p2 = new Panel(new GridLayout(2,1));//第一行centerPanel p3 = new Panel(new BorderLayout());//第二行Panel p4 = new Panel(new GridLayout(2,2));//第二行center//第一行p1.add(new Button("east-1"),BorderLayout.EAST);p1.add(new Button("west-1"),BorderLayout.WEST);p2.add(new Button("center-1-1"));p2.add(new Button("center-1-2"));p1.add(p2,BorderLayout.CENTER);//第二行p3.add(new Button("east-2"),BorderLayout.EAST);p3.add(new Button("west-2"),BorderLayout.WEST);for (int i = 0; i < 4; i++) {p4.add(new Button("center-2-"+(i+1)));}p3.add(p4,BorderLayout.CENTER);frame.add(p1);frame.add(p3);frame.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});}
}
4. 小总结
- Frame是一个顶级窗口
- Panel无法单独显示,必须添加到某个容器中
- 布局管理器
- 流式
- 东西南北中
- 表格
- 大小,定位,背景颜色,可见性,监听!
2.2 事件监听
5. 事件监听
package com.demo8_gui.demo02_awt2;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 TestAction {public static void main(String[] args) {//按下按钮,触发一些事件Frame frame = new Frame();Button button = new Button("click");//因为,addActionListener()需要一个ActionListener,所以我们需要构造一个ActionListener//这里的ActionListener是函数式接口,最好用lambda表达式写MyActionListener myActionListener = new MyActionListener();button.addActionListener(myActionListener);frame.add(button,BorderLayout.CENTER);frame.pack();//自适应(大小)windowClose(frame);frame.setVisible(true);}//关闭窗体的事件private static void windowClose(Frame frame){frame.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);//这样并不是关掉这个窗口,而是关掉整个程序}});}
}//事件监听
class MyActionListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("aaa");}
}
多个按钮,共享一个事件
package com.demo8_gui.demo02_awt2;import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class TestAction2 {public static void main(String[] args) {// 两个按钮,实现同一个监听// 开始 停止Frame frame = new Frame("开始-停止");Button btn1 = new Button("start");Button btn2 = new Button("stop");//显式定义了触发按钮会返回的值,默认是按钮的label值//好处:可以多个按钮只写一个监听(通过显式定义不同返回值)btn2.setActionCommand("btn2-stop");MyMonitor myMonitor = new MyMonitor();btn1.addActionListener(myMonitor);btn2.addActionListener(myMonitor);frame.add(btn1,BorderLayout.NORTH);frame.add(btn2,BorderLayout.SOUTH);frame.pack();frame.setVisible(true);}
}class MyMonitor implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {//e.getActionCommand();//获取按钮的信息System.out.println("按钮被点击了:"+e.getActionCommand());if (e.getActionCommand().equals("start")){}}
}
6. 输入框(TextField)事件监听
package com.demo8_gui.demo02_awt2;import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class TestText01 {public static void main(String[] args) {//启动!new MyFrame();}
}class MyFrame extends Frame{public MyFrame() {TextField textField = new TextField();add(textField);
// this.add(textField);//完整写法,上面省略了this//监听这个文本框输入的文字MyActionListener2 myActionListener2 = new MyActionListener2();//按下enter,就会触发这个输入框的事件textField.addActionListener(myActionListener2);//设置替换编码textField.setEchoChar('*');pack();setVisible(true);}
}//事件监听器
class MyActionListener2 implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {TextField field = (TextField)e.getSource();//获得一些资源,返回一个对象System.out.println(field.getText());//获得输入框的文本field.setText("");//null(对象) ""(空字符串)}
}
7. 简易计算器、组合+内部类 回顾复习!
oop原则:组合,大于继承!(优先使用组合)
//继承
class A extends B{}//组合
class A{public B b;
}
简易计算机
package com.demo8_gui.demo02_awt2;import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;//简易计算器
public class TestCalc {public static void main(String[] args) {new Calculator();}
}//计算器类
class Calculator extends Frame{public Calculator(){//3个文本框 1个按钮 1个标签TextField num1 = new TextField(10);//字符数,长度最大取10TextField num2 = new TextField(10);//字符数TextField num3 = new TextField(20);//字符数Button button = new Button("=");button.addActionListener(new MyCalculatorListener(num1,num2,num3));Label label = new Label("+");//布局setLayout(new FlowLayout());add(num1);add(label);add(num2);add(button);add(num3);pack();setVisible(true);}
}//监听器类
class MyCalculatorListener implements ActionListener{//获取三个变量private TextField num1;private TextField num2;private TextField num3;public MyCalculatorListener(TextField num1,TextField num2,TextField num3){this.num1 = num1;this.num2 = num2;this.num3 = num3;}@Overridepublic void actionPerformed(ActionEvent e) {//1.获得两个加数int n1 = Integer.parseInt(num1.getText());int n2 = Integer.parseInt(num2.getText());//2.将”+“法运算后的值放到第三个框num3.setText(""+(n1+n2));//3.清除前两个框num1.setText("");num2.setText("");}
}
优化后
组合(的思想,提高耦合度):完全改造为面向对象写法
package com.demo8_gui.demo02_awt2;import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;//简易计算器
public class TestCalc {public static void main(String[] args) {new Calculator().loadFrame();}
}//计算器类
class Calculator extends Frame{//属性TextField num1,num2,num3;//方法public void loadFrame(){//所有组件:3个文本框 1个按钮 1个标签 ---> ? + ? = ?TextField num1 = new TextField(10);//字符数,长度最大取10TextField num2 = new TextField(10);//字符数TextField num3 = new TextField(20);//字符数Label label = new Label("+");Button button = new Button("=");button.addActionListener(new MyCalculatorListener(this));//布局setLayout(new FlowLayout());//流式布局add(num1);add(label);add(num2);add(button);add(num3);pack();//自适应setVisible(true);//显式窗口}}//监听器类
class MyCalculatorListener implements ActionListener{//获取监听器这个对象Calculator calculator = null;public MyCalculatorListener(Calculator calculator){this.calculator = calculator;}@Overridepublic void actionPerformed(ActionEvent e) {//1.获得两个加数//2.将”+“法运算后的值放到第三个框//3.清除前两个框int n1 = Integer.parseInt(calculator.num1.getText());int n2 = Integer.parseInt(calculator.num2.getText());calculator.num3.setText(""+(n1+n2));calculator.num1.setText("");calculator.num2.setText("");}
}
(组合+)内部类:更好的包装
package com.demo8_gui.demo02_awt2;import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;//简易计算器
public class TestCalc {public static void main(String[] args) {new Calculator().loadFrame();}
}//计算器类
class Calculator extends Frame{//属性TextField num1,num2,num3;//方法public void loadFrame(){//所有组件:3个文本框 1个按钮 1个标签 ---> ? + ? = ?TextField num1 = new TextField(10);//字符数,长度最大取10TextField num2 = new TextField(10);//字符数TextField num3 = new TextField(20);//字符数Label label = new Label("+");Button button = new Button("=");button.addActionListener(new MyCalculatorListener());//布局setLayout(new FlowLayout());//流式布局add(num1);add(label);add(num2);add(button);add(num3);pack();//自适应setVisible(true);//显式窗口}//监听器类//内部类最大的好处,就是可以畅通无阻的访问外部的属性和方法!private class MyCalculatorListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {//1.获得两个加数//2.将”+“法运算后的值放到第三个框//3.清除前两个框int n1 = Integer.parseInt(num1.getText());int n2 = Integer.parseInt(num2.getText());num3.setText(""+(n1+n2));num1.setText("");num2.setText("");}}
}
8. 画笔 paint
package com.demo8_gui.demo03_awt3;import java.awt.*;public class TestPaint {public static void main(String[] args) {new MyPaint().loadFrame();}
}class MyPaint extends Frame{public void loadFrame(){setBounds(200,200,600,400);setVisible(true);}//画笔@Overridepublic 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);//养成习惯,画笔用完,将它还原成最初的颜色}
}
9. 鼠标监听事件、模拟画图工具
目的:想要实现鼠标画画!
package com.demo8_gui.demo03_awt3;import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Iterator;//测试鼠标监听事件
public class TestMouseListener {public static void main(String[] args) {new MyFrame("画图");}
}//自己的类
class MyFrame extends Frame{//画画需要画笔,需要监听鼠标当前的位置,需要集合来存储这个点ArrayList points;public MyFrame(String title){super(title);setBounds(200,200,400,300);setVisible(true);//存鼠标点击时在Frame上的坐标points = new ArrayList<>();//鼠标监听器,正对这个窗口this.addMouseListener(new MyMouseListener());}@Overridepublic 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{//鼠标 按下,弹起,按住不放@Overridepublic void mousePressed(MouseEvent e) {MyFrame frame = (MyFrame) e.getSource();//给谁加的监听器,就返回谁的source
// e.getPoint();//存的是点的坐标
// points.add(new Point(e.getX(),e.getY()));frame.addPaint(new Point(e.getX(),e.getY()));//每次点击鼠标都需要重新画一遍frame.repaint();//刷新}}//paint是根据坐标画点,监听器是生产坐标,然后调用addPaint方法把坐标存到集合。画笔遍历集合拿到坐标就开始画点//因为myframe里面有鼠标监听器,点击鼠标就会产生点,把这个点通过addpaint存起来,然后paint方法里面判断一下,有点的话就开始画画//addpaint把鼠标的点存在集合points中,然后paint判断points里面有没有点,有点就画画//思路://创建鼠标监听器类,得到鼠标当前位置,并形成一个点//把这个点传到容器中//画笔依次从这个容器中取点,然后画出来}
自己理解的优化
package com.demo8_gui.demo03_awt3;import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Iterator;//思路:
//创建窗口,需要一个鼠标监听器,监听到点集,再需要一个存 点集 的集合,最后通过刷新repaint画出来
//1. 创建鼠标监听器类,得到鼠标当前位置,并形成一个点
//2. 把这个点传到容器中
//3. 画笔依次从这个容器中取点,然后画出来//测试鼠标监听器类:点的画板
public class TestMouseListener{public static void main(String[] args) {new FrameForPaint();}
}//点的画板 类
class FrameForPaint extends Frame{public FrameForPaint(){setVisible(true);setBounds(200,200,400,300);//存鼠标点击时在Frame上的坐标points = new ArrayList<>();//鼠标监听器,正对这个窗口this.addMouseListener(new MyMouseListener());}ArrayList points;//适配器模式private class MyMouseListener extends MouseAdapter{//鼠标 按下,弹起,按住不放@Overridepublic void mousePressed(MouseEvent e) {FrameForPaint frame = (FrameForPaint)e.getSource();//给谁加的监听器,就返回谁的sourcePoint point = e.getPoint();//存的是点的坐标points.add(point);//每次点击鼠标都需要重新画一遍frame.repaint();//刷新}}@Overridepublic void paint(Graphics g) {//画画,监听鼠标的事件Iterator<Point> iterator = points.iterator();while (iterator.hasNext()){Point point = (Point) iterator.next();g.setColor(Color.BLUE);g.fillOval(point.x,point.y,10,10);}// for (Object point : points) {// g.setColor(Color.BLUE);
// g.fillOval(((Point) point).x,((Point) point).y,10,10);
// }}
}
10. 窗口监听事件
package com.demo8_gui.demo03_awt3;import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;public class TestWindow {public static void main(String[] args) {new WindowFrame();}
}class WindowFrame extends Frame{public WindowFrame(){setBackground(Color.blue);setBounds(100,100,400,300);setVisible(true);
// addWindowListener(new MyWindowListener());this.addWindowListener(//匿名内部类new WindowAdapter() {//关闭窗口@Overridepublic void windowClosing(WindowEvent e) {System.out.println("windowClosing");System.exit(0);//正常退出}//激活窗口@Overridepublic void windowActivated(WindowEvent e) {WindowFrame source = (WindowFrame) e.getSource();source.setTitle("被激活了");System.out.println("windowActivated");}});}class MyWindowListener extends WindowAdapter{@Overridepublic void windowClosing(WindowEvent e) {setVisible(false);//隐藏窗口,通过按钮,隐藏当前窗口System.exit(0);//正常退出}}
}
11. 键盘监听事件
package com.demo8_gui.demo03_awt3;import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;//键
public class TestKeyListener {public static void main(String[] args) {new KeyFrame();}
}class KeyFrame extends Frame{public KeyFrame(){setVisible(true);setBounds(100,200,300,400);this.addKeyListener(new KeyAdapter() {//键盘按下@Overridepublic void keyPressed(KeyEvent e) {//获得键盘下的键是哪一个,当前的码int keyCode = e.getKeyCode();//不需要去记录这个数值,直接使用静态属性 VK_XXXSystem.out.println(keyCode);if (keyCode == KeyEvent.VK_UP){System.out.println("你按下了上键");}//根据按下不同操作,产生不同结果:}});}
}
三、Swing(界面)
Ⅰ、窗口
1. JFrame窗体
package com.demo8_gui.demo04_swing;import javax.swing.*;
import java.awt.*;public class JFrameDemo {//init(); 初始化public void init(){//顶级窗口JFrame jf = new JFrame("这是一个JFrame窗口");jf.setVisible(true);jf.setBounds(100,100,200,200);jf.setBackground(Color.cyan);//设置文字 JLabelJLabel label = new JLabel("欢迎来到王者荣耀");jf.add(label);
// //容器实例化
// jf.get//关闭事件jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {//建立一个窗口new JFrameDemo().init();}
}/*** DO_NOTHING_ON_CLOSE 什么都不做的关闭* HIDE_ON_CLOSE 隐藏窗口* DISPOSE_ON_CLOSE 死亡线程* EXIT_ON_CLOSE 终止运行*/
标签居中
package com.demo8_gui.demo04_swing;import javax.swing.*;
import java.awt.*;public class JFrameDemo02 {public static void main(String[] args) {new MyJFrame2().init();}
}class MyJFrame2 extends JFrame{public void init(){this.setBounds(10,10,200,300);this.setVisible(true);JLabel label = new JLabel("欢迎来到王者荣耀");this.add(label);//让文本标签居中 设置水平对齐label.setHorizontalAlignment(SwingConstants.CENTER);
// new JLabel("欢迎",SwingConstants.CENTER);//获得一个容器Container container = this.getContentPane();container.setBackground(Color.YELLOW);}
}
结合
package com.demo8_gui.demo04_swing;import javax.swing.*;
import java.awt.*;public class JFrameDemo03 {public static void main(String[] args) {//建立一个窗口new JFrameDemo03().init();}//init(); 初始化public void init(){//顶级窗口JFrame jf = new JFrame("这是一个JFrame窗口");jf.setVisible(true);jf.setBounds(100,100,200,200);
// jf.setBackground(Color.cyan);//设置文字 JLabelJLabel label = new JLabel("欢迎来到王者荣耀");jf.add(label);//让文本标签居中 设置水平对齐label.setHorizontalAlignment(SwingConstants.CENTER);
// new JLabel("欢迎",SwingConstants.CENTER);//容器实例化,获得一个容器Container container = jf.getContentPane();container.setBackground(Color.YELLOW);//关闭事件jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}
}
Ⅱ、弹窗
2. JDialog弹窗
JDialog,用来被弹出,默认就有关闭事件!
package com.demo8_gui.demo04_swing;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;//主窗口
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);//点击这个按钮的时候,弹出一个弹窗button.addActionListener(new ActionListener() {//监听器@Overridepublic void actionPerformed(ActionEvent e) {//弹窗new MyDialogDemo();}});container.add(button);}
}//弹窗的窗口
class MyDialogDemo extends JDialog{public MyDialogDemo(){this.setVisible(true);this.setBounds(100,100,500,500);
// this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// JDialog退出必须是前三个退出选项之一Container container = this.getContentPane();container.setBackground(Color.YELLOW);container.setLayout(null);JLabel label = new JLabel("今天吃的兔兔");label.setBounds(100,100,400,400);label.setForeground(Color.green);//设置颜色container.add(label);}
}//Font arial = new Font("Arial", Font.ITALIC, 50);
//label.setFont(arial);/*
Font mf = new Font(String 字体,int 风格,int 字号);
字体:TimesRoman, Courier, Arial等
风格:三个常量 lFont.PLAIN, Font.BOLD, Font.ITALIC
字号:字的大小(磅数)
设置组件当前使用的字体:setFont(Font fn)
获取组件当前使用的字体:getFont()*/
Ⅲ、标签
label
new JLabel("xxx");
3. Icon、ImageIcon标签
图标标签
package com.demo8_gui.demo04_swing;import javax.swing.*;
import java.awt.*;//图标,需要实现类,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 iconDemo = new IconDemo(15, 15);//图标放在标签上,也可以放在按钮上!JLabel label = new JLabel("icontest",iconDemo,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();}@Overridepublic void paintIcon(Component c, Graphics g, int x, int y) {//组件 Component,画笔 Graphicsg.fillOval(x,y,width,height);}@Overridepublic int getIconWidth() {return this.width;}@Overridepublic int getIconHeight() {return this.height;}
}
图片标签
package com.demo8_gui.demo04_swing;import javax.swing.*;
import java.awt.*;
import java.net.URL;public class ImageIconDemo extends JFrame {public ImageIconDemo(){//获取图片的地址JLabel label = new JLabel("ImagIcon");URL url = ImageIconDemo.class.getResource("1.jpg");//放的是绝对路径下的资源(不同电脑,设置可能不一样)ImageIcon imageIcon = new ImageIcon(url);//命名不要冲突了!原来的类名为ImageIcon,产生冲突了报错label.setIcon(imageIcon);label.setHorizontalAlignment(SwingConstants.CENTER);Container container = getContentPane();container.add(label);setVisible(true);setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);setBounds(100,100,200,200);}public static void main(String[] args) {new ImageIconDemo();}
}
Ⅳ、面板
JPanel
package com.demo8_gui.demo05_Swing2;import javax.swing.*;
import java.awt.*;public class JPanelDemo extends JFrame {public JPanelDemo(){Container container = this.getContentPane();container.setLayout(new GridLayout(2,1,10,10));//后面的参数的意思:间距;面板间会有10的间距;原来是2行1列,但是可以自动扩展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.setVisible(true);this.setSize(500,500);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {new JPanelDemo();}
}
4. 文本域JScroll面板
package com.demo8_gui.demo05_Swing2;import javax.swing.*;
import java.awt.*;public class JScrollDemo extends JFrame {public JScrollDemo(){Container container = this.getContentPane();//文本域JTextArea textArea = new JTextArea(20, 50);textArea.setText("欢迎来到王者荣耀");//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();}
}
Ⅴ、按钮
- 单选按钮(单选框)
- 复选按钮(多选框)
5. 图片按钮、单选框、多选框
图片按钮
package com.demo8_gui.demo05_Swing2;import javax.swing.*;
import java.awt.*;
import java.net.URL;public class JButtonDemo01 extends JFrame {public JButtonDemo01(){Container container = this.getContentPane();//将一个图片变为图标URL resource = JButtonDemo01.class.getResource("2.jpg");Icon icon = new ImageIcon(resource);//把这个图标放在按钮上JButton button = new JButton();button.setIcon(icon);button.setToolTipText("图片按钮");//addcontainer.add(button);this.setVisible(true);this.setSize(500,300);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {new JButtonDemo01();}
}
单选框
package com.demo8_gui.demo05_Swing2;import javax.swing.*;
import java.awt.*;
import java.net.URL;public class JButtonDemo02 extends JFrame {public JButtonDemo02(){Container container = this.getContentPane();//将一个图片变为图标URL resource = JButtonDemo01.class.getResource("2.jpg");Icon icon = new ImageIcon(resource);//单选框JRadioButton radioButton1 = new JRadioButton("JRadioButton01");JRadioButton radioButton2 = new JRadioButton("JRadioButton02");JRadioButton radioButton3 = new JRadioButton("JRadioButton03");//由于是单选框只能选择一个,所以进行分组,使得一个组中只能选择一个ButtonGroup group = new ButtonGroup();group.add(radioButton1);group.add(radioButton2);group.add(radioButton3);container.add(radioButton1,BorderLayout.CENTER);container.add(radioButton2,BorderLayout.NORTH);container.add(radioButton3,BorderLayout.SOUTH);this.setVisible(true);this.setSize(500,300);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {new JButtonDemo02();}
}
多选框
package com.demo8_gui.demo05_Swing2;import javax.swing.*;
import java.awt.*;
import java.net.URL;public class JButtonDemo03 extends JFrame {public JButtonDemo03(){Container container = this.getContentPane();//将一个图片变为图标URL resource = JButtonDemo01.class.getResource("2.jpg");Icon icon = new ImageIcon(resource);//多选框JCheckBox checkBox01 = new JCheckBox("checkBox01");JCheckBox checkBox02 = new JCheckBox("checkBox02");container.add(checkBox01,BorderLayout.NORTH);container.add(checkBox02,BorderLayout.SOUTH);this.setVisible(true);this.setSize(500,300);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {new JButtonDemo03();}
}
Ⅵ、列表
- 下拉框
- 列表框
6. 下拉框、列表框
下拉框
package com.demo8_gui.demo06_Swing3;//combobox
//下拉列表框;组合下拉框;组合框;组合框控件;下拉框import javax.swing.*;
import java.awt.*;public class TestComboboxDemo01 extends JFrame {public TestComboboxDemo01(){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 TestComboboxDemo01();}
}
列表框
package com.demo8_gui.demo06_Swing3;import javax.swing.*;
import java.awt.*;
import java.util.Vector;public class TestComboboxDemo02 extends JFrame {public TestComboboxDemo02(){Container container = this.getContentPane();//生成列表的内容//String[] contents = {"1","2","3"};Vector contents = new Vector();//列表中需要放入内容JList jList = new JList(contents);contents.add("zhangsan");contents.add("lisi");contents.add("wangwu");container.add(jList);this.setVisible(true);this.setSize(500,300);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {new TestComboboxDemo02();}
}
- 应用场景
- 选择地区,或者一些单个选项(下拉框进行单选)
- 列表,展示信息,一般是动态扩容!
Ⅶ、文本框
- 文本框
- 密码框
- 文本域
7. 文本框、密码框、文本域
文本框
package com.demo8_gui.demo06_Swing3;import javax.swing.*;
import java.awt.*;public class TestTextDemo01 extends JFrame {public TestTextDemo01(){Container container = this.getContentPane();JTextField textField = new JTextField("hello");JTextField textField2 = new JTextField("world",20);container.add(textField,BorderLayout.NORTH);container.add(textField2,BorderLayout.SOUTH);this.setVisible(true);this.setSize(500,300);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {new TestTextDemo01();}
}
密码框
package com.demo8_gui.demo06_Swing3;import javax.swing.*;
import java.awt.*;public class TestTextDemo02 extends JFrame {public TestTextDemo02(){Container container = this.getContentPane();//尽量用面板做JPasswordField passwordField = new JPasswordField();//****passwordField.setEchoChar('*');container.add(passwordField);this.setVisible(true);this.setSize(500,300);this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);}public static void main(String[] args) {new TestTextDemo02();}
}
文本域
package com.demo8_gui.demo05_Swing2;import javax.swing.*;
import java.awt.*;public class JScrollDemo extends JFrame {public JScrollDemo(){Container container = this.getContentPane();//文本域JTextArea textArea = new JTextArea(20, 50);textArea.setText("欢迎来到王者荣耀");//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();}
}
…
HTML + Servlet
MVC
C/S
B/S
…
四、一小时开发贪吃蛇游戏
0. 游戏演示和动画帧的概念
静态素材获取:https://gitee.com/kuangstudy/JavaGames
博客笔记:https://blog.kuangstudy.com/
步骤:
- 图纸设计
- 静态页面绘制
- 让小蛇动起来
- 吃食物
- 积分展示
- 展望
帧:如果时间片足够小,就是动画,一秒30帧、60帧。连起来就是动画,拆开就是静态的图片!
键盘监听
定时器Timer
1. 贪吃蛇之界面绘制
2. 绘制静态的小蛇
3. 让小蛇动起来
4. 键盘控制小蛇移动
5. 小蛇吃食物长大
6. 失败判定、积分系统
7. 小总结
package com.demo8_gui.demo07_snake;import javax.swing.*;//游戏的主启动类
public class StartGame {public static void main(String[] args) {JFrame frame = new JFrame();frame.setBounds(200,150,900,720);//主窗口位置、大小frame.setResizable(false);//窗口大小不可变frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//设置关闭操作//正常游戏界面都应该在面上!frame.add(new GamePanel());frame.setVisible(true);//窗口设置可见}
}
package com.demo8_gui.demo07_snake;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;//游戏的画板
public class GamePanel extends JPanel implements KeyListener, ActionListener {//定义蛇的数据结构int length;//蛇的长度int[] snakeX = new int[600];//蛇的X坐标 25*25int[] snakeY = new int[500];//蛇的Y坐标 25*25String fx;//蛇头的方向//食物的坐标int foodX;int foodY;Random random = new Random();//随机//可以设置每10颗食物出现一颗 毒食物 或者 大积分食物int score;//成绩( 也可以根据:身体目前长度 - 原始长度 :(length - 3)*10 )//游戏当前的状态:开始,停止boolean isStart = false;//默认是未开始!boolean isFail = false;//游戏是否失败状态,默认是未失败!//定时器 以ms为单位 1000ms = 1sTimer timer = new Timer(100,this);//100毫秒执行一次!//可以设置每30s提速一次的操作,但是一般是吃到一定颗数提速定时器//构造器public GamePanel(){init();//获得焦点和键盘事件this.setFocusable(true);//获得焦点事件this.addKeyListener(this);//获得监听事件timer.start();//游戏一开始定时器就启动}//初始化方法public void init(){length = 3;//初始长度为 3snakeX[0] = 100;snakeY[0] = 100;//脑袋的坐标snakeX[1] = 75;snakeY[1] = 100;//第一个身体的坐标snakeX[2] = 50;snakeY[2] = 100;//第二个身体的坐标fx = "R";//初识方向向右//把食物随机分布在界面上!foodX = 25 + 25*random.nextInt(34);foodY = 75 + 25*random.nextInt(24);score = 0;}//绘制面板,我们游戏中的所有东西,都是用这个画笔来画@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);//清屏//绘制静态的画板this.setBackground(Color.WHITE);Data.header.paintIcon(this,g,0,0);//头部广告栏画上去g.fillRect(25,75,850,600);//默认的游戏界面//画积分g.setColor(Color.GREEN);g.setFont(new Font("微软雅黑",Font.BOLD,22));//设置字体g.drawString("长度:"+length,700,30);g.drawString("分数:"+score,700,55);//画食物Data.food.paintIcon(this,g,foodX,foodY);//把小蛇画上去,画蛇头if (fx.equals("R")) {Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化向右,需要通过方向来判断}else if (fx.equals("L")) {Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);}else if (fx.equals("U")) {Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);}else if (fx.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);}}//键盘监听事件@Overridepublic void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();//获得键盘按键是哪一个if (keyCode == KeyEvent.VK_SPACE){//如果按下的是空格键if (isFail){//重新开始isFail = false;init();//重新初始化}else {isStart = !isStart;//取反repaint();}}//小蛇移动(切换蛇头方向)(判断如果当前的头向右边,则左键无效,即不能回头)//此处有bug,4个按键按太快还是会出现回头bug,此处不懂怎么改if (keyCode==KeyEvent.VK_UP && fx!="D"){fx = "U";}else if (keyCode==KeyEvent.VK_DOWN && fx!="U"){fx = "D";}else if (keyCode==KeyEvent.VK_LEFT && fx!="R"){fx = "L";}else if (keyCode==KeyEvent.VK_RIGHT && fx!="L"){fx = "R";}}//事件监听---需要通过固定时间来刷新,1s=10次@Overridepublic void actionPerformed(ActionEvent e) {if(isStart&&isFail==false){//如果游戏是开始并且未失败状态,就让小蛇动起来!//吃食物if (snakeX[0] == foodX && snakeY[0] == foodY){//判断蛇头与食物重叠了//长度 + 1length++;//分数+10
// int flag = length-3;
// if (flag%5==0&&flag!=0) {//每吃5个食物来个大积分食物(可以找个其他图片做大积分食物的图片,每50分食物更换为大积分食物图片)
// score = score + 30;
// }else {score = score + 10;
// }//再次随机事物,应该防止食物与身体重合boolean isSame=true;while(isSame) {foodX = 25 + 25 * random.nextInt(34);foodY = 75 + 25 * random.nextInt(24);for (int i = 0; i < length; i++) {if (foodX==snakeX[i]||foodY==snakeY[i]){isSame=false;//不相同了}}}}//移动for (int i = length-1;i>0;i--){//后一节移到前一节的位置 snakeX[1] = snakeX[0];snakeX[i] = snakeX[i-1];snakeY[i] = snakeY[i-1];}//走向if (fx.equals("R")){snakeX[0] = snakeX[0]+25;if (snakeX[0]>850){ snakeX[0] = 25; }//边界判断 (默认可穿墙,把这句改为当此情况发生时游戏状态为失败)
// if (snakeX[0]>850){ isFail=true; }//不可穿墙}else if (fx.equals("L")){snakeX[0] = snakeX[0]-25;if (snakeX[0]<25){ snakeX[0] = 850; }//边界判断 25+850-25=850}else if (fx.equals("U")){snakeY[0] = snakeY[0]-25;if (snakeY[0]<75){ snakeY[0] = 650; }//边界判断 75+600-25=650}else if (fx.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();//定时器开启!}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void keyTyped(KeyEvent e) {}}
package com.demo8_gui.demo07_snake;import javax.swing.*;
import java.net.URL;//数据中心
public class Data {//相对路径 tx.jpg//绝对路径 / 相当于当前项目public static URL headerURL = Data.class.getResource("statics/header.png");public static ImageIcon header = new ImageIcon(headerURL);public static URL upURL = Data.class.getResource("statics/up.png");public static URL downURL = Data.class.getResource("statics/down.png");public static URL leftURL = Data.class.getResource("statics/left.png");public 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);public static URL bodyURL = Data.class.getResource("statics/body.png");public static ImageIcon body = new ImageIcon(bodyURL);public static URL foodURL = Data.class.getResource("statics/food.png");public static ImageIcon food = new ImageIcon(foodURL);
}/*
statics 里放素材图片
获取图片路径: URL headerURL = Data.class.getResource("statics/header.png");
图片标签: ImageIcon header = new ImageIcon(headerURL);*/
1. 定义数据
2. 画上去
3. 监听事件:键盘、事件
总结:GUI阶段回顾与总结
- GUI编程
- GUI
- AWT
- 组件
- 容器
- 面板
- 事件监听
- 文本框监听
- 画图类 paint(g)
- 鼠标监听器
- 键盘监听器
- Swing
- 容器
- 面板
- 可以带滚动条的
- label
- 普通标签
- 图片标签
- 图像标签
- 按钮
- 普通按钮
- 带图片的按钮
- 单选框
- 多选框
- 列表
- 下拉框
- 列表框
- 文本框
- 普通文本
- 密码框
- 文本框
- 贪吃蛇
JavaSE:GUI编程入门到游戏实战相关推荐
- python游戏编程入门 免费-python游戏编程入门 python游戏编程入门课
python游戏编程入门 python游戏编程入门课 什么是python游戏编程入门?首先我们需要认识什么是Python Python既是一个软件工具包,也是一种语言.Python软件包包含了一个名为 ...
- pythonguitkinter编程入门_Python Tkinter GUI编程入门介绍
一.Tkinter介绍 Tkinter是一个python模块,是一个调用Tcl/Tk的接口,它是一个跨平台的脚本图形界面接口.Tkinter不是唯一的python图形编程接口,但是是其中比较流行的一个 ...
- python游戏编程入门免费_python游戏编程入门 python游戏编程入门课
python游戏编程入门 python游戏编程入门课 什么是python游戏编程入门?首先我们需要认识什么是Python Python既是一个软件工具包,也是一种语言.Python软件包包含了一个名为 ...
- GUI编程笔记入门到游戏实战
0x01 GUI编程 Frame 窗口 packagegui; importjava.awt.*; publicclassMyFrameextendsFrame {staticintid=0; ...
- python游戏编程入门p_Python游戏编程入门 PDF高清完整版
Python游戏编程入门 PDF高清完整版 作者: 哈伯 (Jonathan S.Harbour) 译者: 李强 出版年: 2015-1-1 页数: 292 装帧: 平装 ISBN: 97871153 ...
- python游戏编程入门-python游戏编程入门
<Python游戏编程入门> 这些文章负责整理在这本书中的知识点.注意事项和课后习题的尝试实现. 并且对每一个章节给出的最终实例进行分析和注释. 初识pygame:pie游戏 pygame ...
- python3.6 messagebox_Python Tkinter GUI编程入门介绍
一.Tkinter介绍 Tkinter是一个python模块,是一个调用Tcl/Tk的接口,它是一个跨平台的脚本图形界面接口.Tkinter不是唯一的python图形编程接口,但是是其中比较流行的一个 ...
- python gui编程 从入门到项目实战_python GUI编程 QT5开发项目实战
目录:├─01-PyQT简介及优势├─02-PyQT5开发环境搭建├─03-PyQT5应该学什么├─04-PyQT5库结构├─05-PyQT5程序基本结构分析├─06-PyQT5-Pycharm活动模 ...
- python编程入门 pdf-PYTHON游戏编程入门 PDF 下载
相关截图: 图书简介: Python是一种解释型.面向对象.动态数据类型的高级程序设计语言,在游戏开发领域,Python也得到越来越广泛的应用,并由此受到重视. 本书教授用Python开发精彩游戏所需 ...
- python编程入门pdf-Python游戏编程入门 中文pdf扫描版[41MB]
Python是一种解释型.面向对象.动态数据类型的程序设计语言,在游戏开发领域,Python也得到越来越广泛的应用,并由此受到重视. 本书教授用Python开发精彩游戏所需的[]为重要的该你那.本书不 ...
最新文章
- c++ 实例精通(1)
- 我的Ubuntu9.10安装与配置100
- python爬虫beautifulsoup爬当当网_Python爬虫包 BeautifulSoup 递归抓取实例详解_python_脚本之家...
- php mysql 索引_MySQL索引
- LeetCode--5.最长回文子串(滑动窗口)
- Silverlight开发之MVVM模式
- WFDB软件包简介——ECG数据在Matlab下的读取/显示方法
- 关键字 : this /self / parent
- 有一种记录叫“时光轴”!
- 字符集、ASCII、Unicode
- 数据可视化大屏 - 大屏云极简使用手册
- 用Windows自带工具给U盘4k对齐
- CSS系列之修改滚动条的样式
- IMU预积分的简单理解
- 计算机清理软件,想要清理你的 Windows 电脑?用这 4 款清理软件就对了
- 【工具】OmniGraffle 激活码、UML模板型版
- 我的世界服务器唱片修改,我的世界怎么修改音乐 音乐资源包使用教程
- 【推荐算法论文阅读】LightGCN: Simplifying and Powering Graph Convolution Network for Recommendation
- 互联网公司招聘解读!
- 自动售货机软件工程课设_软件工程 自动售货机
热门文章
- 012-P2P加速Docker镜像分发(阿里Dragonfly)
- storm风暴英雄 tempo_【风暴英雄】锐派专区 - fb.replays.net | 风暴英雄官网合作中文站...
- 网络公益信息特征和用户行为规律研究以微博为例
- Endnote X9 插入参考文献、设置参考文献格式
- HTML学生个人网站作业设计:旅游景点网站设计——北京故宫(9页) HTML+CSS+JavaScript 简单DIV布局个人介绍网页模板代码 DW学生个人网站制作成品下载
- 电子设计教程35:LC振荡电路
- 3315 时空跳跃者的魔法(一个超级恶心的题目)
- [半监督学习] Tri-Training: Exploiting Unlabeled Data Using Three Classifiers
- H3C设备网吧万兆光模块解决方案
- 将手机流氓软件彻底赶出去