目录
Java GUI编程,分为AWT和Swing两种,Swing为AWT封装之上的一种。
一、AWT
1、容器
1、Frame是一个顶级窗口;
2、Panel是一个面板,无法单独显示,需要添加到某个容器中;
3、布局管理器:
i:流式布局(默认)
ii:网格布局
iii:Border布局(东西南北中)
练习:
代码:
Frame frame = new Frame("练习窗口布局");
frame.setSize(500, 500);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Panel upPanCenter = new Panel();
Panel downPanCenter = new Panel();
frame.setLayout(new GridLayout(2, 3));
frame.add(new Button("bt1"));
frame.add(upPanCenter);
frame.add(new Button("bt2"));
frame.add(new Button("bt3"));
frame.add(downPanCenter);
frame.add(new Button("bt4"));
upPanCenter.setLayout(new GridLayout(2,1));
upPanCenter.add(new Button("upbt1"));
upPanCenter.add(new Button("upbt2"));
downPanCenter.setLayout(new GridLayout(2,2));
downPanCenter.add(new Button("downbt1"));
downPanCenter.add(new Button("downbt2"));
downPanCenter.add(new Button("downbt3"));
downPanCenter.add(new Button("downbt4"));
2、事件监听
以按钮为例,通过addActionListener()方法添加一个监听事件,可以给每个控件添加一个actionCommand,然后通过actionCOmmand来进行区分,这样就可以将所有控件的监听事件用同一个来完成。
public class TestActionEvent {
public static void main(String[] args) {
Frame frame = new Frame("frame");
frame.setLayout(new FlowLayout());
Button button1 = new Button("bt1");
Button button2 = new Button("bt2");
button1.setActionCommand("bt1");
button2.setActionCommand("bt2");
CustomActionListener listener = new CustomActionListener();
button1.addActionListener(listener);
button2.addActionListener(listener);
frame.add(button1);
frame.add(button2);
frame.setSize(200, 100);
frame.setVisible(true);
closeWin(frame);
}
private static void closeWin(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class CustomActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
}
3、文本输入框
public class TestTextField {
public static void main(String[] args) {
new TextFieldFrame("测试文本框");
}
}
class TextFieldFrame extends Frame {
public TextFieldFrame(String title) {
super(title);
TextField field = new TextField();
add(field);
field.addActionListener(new TextFieldListener());
//替换编码,输入框输入的文本替换成的文本
field.setEchoChar('*');
setVisible(true);
//自适应窗口大小
pack();
closeWin(this);
}
private static void closeWin(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class TextFieldListener implements ActionListener {
//回车出发监听事件,执行监听的方法
@Override
public void actionPerformed(ActionEvent e) {
//监听谁,e.getSource()就会获得对应的实体对象
TextField textField = (TextField) e.getSource();
//获得文本框的输入
System.out.println(textField.getText());
//文本框输入清空
textField.setText("");
}
}
4、简易计算器实现
实现框图:
步骤:
1、计算文本框1和文本框2中的数字之和,填充到文本框3中;
2、文本框1和文本框2中的数字清空;
代码:
public class textCalculator {
public static void main(String[] args) {
new Calculator("简易计算器").load();
}
}
class Calculator extends Frame {
private TextField field1;
private TextField field2;
private TextField field3;
private Label label;
private Button button;
public Calculator(String title) {
super(title);
}
public void load() {
field1 = new TextField();
field1.setColumns(10);
field2 = new TextField();
field2.setColumns(10);
field3 = new TextField();
field3.setColumns(20);
label = new Label("+");
button = new Button("=");
button.addActionListener(new CuActionListener());
button.setActionCommand("calculator_start");
add(field1);
add(label);
add(field2);
add(button);
add(field3);
setLayout(new FlowLayout());
setVisible(true);
pack();
closeWin(this);
}
private static void closeWin(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
private class CuActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if ("calculator_start".equals(e.getActionCommand())) {
int i1 = Integer.valueOf(field1.getText());
int i2 = Integer.valueOf(field2.getText());
field3.setText(String.valueOf(i1 + i2));
field1.setText("");
field2.setText("");
}
}
}
}
5、监听
监听事件的Listener接口过多,实际使用中并不会用到所有的接口,所以可以用对应的Adapter抽象类,只需要实现我们所需要的接口就行。
鼠标监听
监听鼠标动作事件,实现画点
实现:
代码:
public class TextMouseListener {
public static void main(String[] args) {
new MyFrame("画点");
}
}
class MyFrame extends Frame {
private List<Point> pointList;
public MyFrame(String title) {
super(title);
pointList = new ArrayList<>();
setBounds(100, 100, 400, 300);
//设置鼠标监听
addMouseListener(new MyMouseListener());
setVisible(true);
closeWin(this);
}
private static void closeWin(Frame frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
@Override
public void paint(Graphics g) {
Iterator<Point> iterator = pointList.iterator();
while (iterator.hasNext()) {
Point point = iterator.next();
g.setColor(Color.BLUE);
g.fillOval(point.x, point.y, 10, 10);
}
}
//添加点到集合中
private void addPoint(Point point) {
pointList.add(point);
}
private class MyMouseListener extends MouseAdapter {
//鼠标按下
@Override
public void mousePressed(MouseEvent e) {
MyFrame frame = (MyFrame) e.getSource();
frame.addPoint(new Point(e.getX(), e.getY()));
//每次点击鼠标重新画一遍
frame.repaint();
}
}
}
窗口监听
窗口监听最常见的只有窗口关闭和激活两种,其他的不常用。
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
@Override
public void windowActivated(WindowEvent e) {
super.windowActivated(e);
}
});
键盘监听
键盘案件监听,可以通过keycode来实现某些操作。
Frame frame = new Frame("监听键盘事件");
frame.setVisible(true);
frame.setSize(200,100);
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//keycode是键盘案件的类型
System.out.println(e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_ENTER){
System.out.println("enter键");
}
}
});
二、Swing
Swing比AWT多了Container容器的概念
1、面板、容器
JFrame.setBackground(Color.GREEN)直接设置颜色不生效,是因为在你直接调用setBackground(Color.red)这个方法后,你的确设置了JFrame的背景颜色,而你看到的却不是直接的JFrame,而是JFrame.getContentPane()。而JFrame上的contentPane默认是Color.WHITE的,所以,无论你对JFrame怎么设置背景颜色,你看到的都只是contentPane.所以需要设置contentPane的颜色。
JFrame jFrame = new JFrame("JFrame面板");
jFrame.setVisible(true);
jFrame.setSize(100, 100);
// jFrame.setBackground(Color.GREEN);
Container container = jFrame.getContentPane();
container.setBackground(Color.yellow);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel jLabel = new JLabel();
jLabel.setText("一段文本");
//文本文字居中
jLabel.setHorizontalAlignment(JLabel.CENTER);
jFrame.add(jLabel);
2、弹框
public static void main(String[] args) {
JFrame jFrame = new JFrame();
jFrame.setBounds(100,100,500,300);
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = jFrame.getContentPane();
JButton jButton = new JButton("按钮操作");
jButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
new MyDialog();
}
});
container.add(jButton);
}
private static class MyDialog extends JDialog{
public MyDialog(){
this.setVisible(true);
this.setBounds(200,100,200,100);
Container contentPane = this.getContentPane();
contentPane.setLayout(null);
contentPane.add(new JLabel("ainegoaioedghioan g"));
}
}
3、标签
JFrame jFrame = new JFrame();
jFrame.setVisible(true);
jFrame.setBounds(100,100,200,200);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = jFrame.getContentPane();
JLabel jLabel = new JLabel();
jLabel.setText("这是一段文本,前面是标签图片");
URL url = TestIconLabel.class.getResource("img.png");
ImageIcon imageIcon = new ImageIcon(url);
jLabel.setIcon(imageIcon);
container.add(jLabel);
4、面板
JPanel不再叙述
... ...
JScrollPane 滚动面板
JFrame jFrame = new JFrame();
jFrame.setVisible(true);
jFrame.setBounds(100, 100, 200, 200);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = jFrame.getContentPane();
TextArea textArea = new TextArea(10, 15);
textArea.setText("欢迎来到此处学习");
JScrollPane jScrollPane = new JScrollPane(textArea);
// jScrollPane.add(textArea);
container.add(jScrollPane);
5、其他控件
图片按钮
JButton jButton = new JButton("图片按钮");
URL url = TestIconLabel.class.getResource("img.png");
ImageIcon imageIcon = new ImageIcon(url);
jButton.setIcon(imageIcon);
jButton.setToolTipText("这是一个图片按钮");
container.add(jButton);
单选框
单选框是JRadioButton
如果多个单选框时只能在同一时刻选中一个,那么需要将他们添加到一个group中
JRadioButton jRadioButton1 = new JRadioButton("JRadioButton1");
JRadioButton jRadioButton2 = new JRadioButton("JRadioButton2");
JRadioButton jRadioButton3 = new JRadioButton("JRadioButton3");
ButtonGroup group = new ButtonGroup();
group.add(jRadioButton1);
group.add(jRadioButton2);
group.add(jRadioButton3);
container.add(jRadioButton1);
container.add(jRadioButton2);
container.add(jRadioButton3);
多选框
//多选框
JCheckBox checkBox1 = new JCheckBox("checkbox1");
JCheckBox checkBox2 = new JCheckBox("checkbox2");
container.add(checkBox1);
container.add(checkBox2);
下拉框
addItemListener监听每个下拉列表取消和选中的变化,这个方法会被执行两次itemStateChanged,一次是上次选中的,一次是本次选中的,如下,就是将已上架切换到热映中,根据e.getStateChange()来进行区分。
JComboBox comboBox = new JComboBox();
comboBox.addItem("");
comboBox.addItem("已上架");
comboBox.addItem("已下架");
comboBox.addItem("热映中");
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
System.out.println("ItemListener... ...");
if (e.getStateChange()==ItemEvent.SELECTED){
System.out.println(e.getItem().toString()+"选中");
}
else if (e.getStateChange()==ItemEvent.DESELECTED){
System.out.println(e.getItem().toString()+"取消选中");
}
}
});
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("actionPerformed..."+(JComboBox)e.getSource());
}
});
container.add(comboBox);
列表
//列表
String[] list = {"张三", "李斯", "王武"};
JList jList = new JList(list);
container.add(jList);
文本框|文本域|密码框
//文本框
JTextField jTextField = new JTextField("文本框",15);
container.add(jTextField);
//密码框
JPasswordField jPasswordField = new JPasswordField(15);
jPasswordField.setEchoChar('*');
container.add(jPasswordField);
//文本域
JTextArea jTextArea = new JTextArea(10,15);
JScrollPane jScrollPane = new JScrollPane(jTextArea);
container.add(jScrollPane);
三、贪吃蛇小游戏
贪吃蛇小游戏参考网上部分案例:
案例资源文件见最后部分
效果图:
代码:
public class Data {
public static URL headerUrl = Data.class.getResource("statics/img.png");
public static URL bodyUrl = Data.class.getResource("statics/body.png");
public static URL foodUrl = Data.class.getResource("statics/food.png");
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 headerIcon = new ImageIcon(headerUrl);
public static ImageIcon bodyIcon = new ImageIcon(bodyUrl);
public static ImageIcon foodIcon = new ImageIcon(foodUrl);
public static ImageIcon upIcon = new ImageIcon(upUrl);
public static ImageIcon downIcon = new ImageIcon(downUrl);
public static ImageIcon leftIcon = new ImageIcon(leftUrl);
public static ImageIcon rightIcon = new ImageIcon(rightUrl);
}
public class StartGame {
public static void main(String[] args) {
JFrame frame = new JFrame("贪吃蛇");
//窗口大小一般首先要计算好
frame.setBounds(10,10,900,720);
//设置窗口大小不可变
frame.setResizable(false);
frame.setVisible(true);
frame.add(new GamePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
public class GamePanel extends JPanel implements KeyListener, ActionListener {
//小蛇的数据
int length; //蛇的长度
int[] snakeX = new int[600]; //蛇的坐标x
int[] snakeY = new int[500]; //蛇的坐标y
//方向
String fx;
//游戏状态
boolean start;
//失败状态
boolean fail;
Timer timer;
Random random = new Random();
int foodX;
int foodY;
int score;
public GamePanel() {
init();
//获得焦点
this.setFocusable(true);
//键盘按键监听
this.addKeyListener(this);
//timer 200ms执行一次
timer = new Timer(100, this);
timer.start();
}
private void init() {
length = 3;
snakeX[0] = 100;
snakeY[0] = 100;
snakeX[1] = 75;
snakeY[1] = 100;
snakeX[2] = 50;
snakeY[2] = 100;
fx = "R";
//食物地点随机分配,850/25=34 600/25=24
foodX = 25 + 25 * random.nextInt(34);
foodY = 75 + 25 * random.nextInt(24);
//初始化游戏分数
score = 0;
}
/**
* 绘制面板
*
* @param g
*/
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.white);
//绘画头部
Data.headerIcon.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);
//绘画蛇的静态初始位置
if ("R".equals(fx)) {
Data.rightIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if ("L".equals(fx)) {
Data.leftIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if ("U".equals(fx)) {
Data.upIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if ("D".equals(fx)) {
Data.downIcon.paintIcon(this, g, snakeX[0], snakeY[0]);
}
for (int i = 1; i < length; i++) {
Data.bodyIcon.paintIcon(this, g, snakeX[i], snakeY[i]);
}
if (!start) {
g.setColor(Color.WHITE);
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
g.drawString("按下空格开始游戏", 300, 300);
}
if (fail) {
g.setColor(Color.RED);
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
g.drawString("失败了,按下空格重新开始", 300, 300);
}
Data.foodIcon.paintIcon(this, g, foodX, foodY);
}
/**
* 按键监听
*
* @param e
*/
@Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
if (keycode == KeyEvent.VK_SPACE) {
if (fail) {
fail = false;
init();
} else {
start = !start;
}
repaint();
} else if (keycode == KeyEvent.VK_UP) {
this.fx = "U";
} else if (keycode == KeyEvent.VK_DOWN) {
this.fx = "D";
} else if (keycode == KeyEvent.VK_LEFT) {
this.fx = "L";
} else if (keycode == KeyEvent.VK_RIGHT) {
this.fx = "R";
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (start && !fail) {
if (snakeX[0] == foodX && snakeY[0] == foodY) {
length++;
score += 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 ("R".equals(fx)) {
snakeX[0] += 25;
//边界判断
if (snakeX[0] > 850) {
snakeX[0] = 25;
}
} else if ("L".equals(fx)) {
snakeX[0] -= 25;
//边界判断
if (snakeX[0] < 25) {
snakeX[0] = 850;
}
} else if ("U".equals(fx)) {
snakeY[0] -= 25;
//边界判断
if (snakeY[0] < 75) {
snakeY[0] = 650;
}
} else if ("D".equals(fx)) {
snakeY[0] += 25;
//边界判断
if (snakeY[0] > 650) {
snakeY[0] = 75;
}
}
for (int i = 1; i < length; i++) {
if (snakeX[i] == snakeX[0] && snakeY[i] == snakeY[0]) {
fail = true;
}
}
repaint();
}
timer.start();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
资源文件: