iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0

今日內容:KeyListener、Inner Class、KeyBinding


keyListener

在MyFrame中implements KeyListener
會有三個需要Override的method (KeyTyped, KeyPressed , KeyReleased)

import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.Color;
import javax.swing.ImageIcon;

public class MyFrame extends JFrame implements KeyListener {
    JLabel label;
    ImageIcon icon;
    MyFrame(){
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(500, 500);
        this.setLayout(null);
        this.addKeyListener(this);

        icon = new ImageIcon("rocket.png");

        label = new JLabel();
        label.setBounds(0, 0, 100, 100);
        label.setIcon(icon);

        this.getContentPane().setBackground(Color.black);
        this.add(label);
        this.setVisible(true);
    }

    @Override
    public void keyTyped(KeyEvent e) {
        // 當key被輸入,回傳char
        // 可以用來接收wasd
        switch(e.getKeyChar()){
            case 'a', 'A' -> label.setLocation(label.getX()-10, label.getY());
            case 'w', 'W' -> label.setLocation(label.getX(), label.getY()-10);
            case 's', 'S' -> label.setLocation(label.getX(), label.getY()+10);
            case 'd', 'D' -> label.setLocation(label.getX()+10, label.getY());
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        // 當鍵盤上的按鍵被按,回傳int
        // 可以用來接收上下左右(arrow)
        switch(e.getKeyCode()){
            case 37 -> label.setLocation(label.getX()-10, label.getY());
            case 38 -> label.setLocation(label.getX(), label.getY()-10);
            case 40 -> label.setLocation(label.getX(), label.getY()+10);
            case 39 -> label.setLocation(label.getX()+10, label.getY());
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // 當按鍵被放開
        System.out.println("You released key char: " + e.getKeyChar());
        System.out.println("You released key code: " + e.getKeyCode());
        System.out.println();
    }
}

image


Inner Class

一個class裡面可以有另一個class,(很像nested loop)
通常被設為private,但不是必要
用來方便存取兩個class之間的內容

public class Outside {
    String x = "Hello ";
    public class Inside{
        String y = "World!";

        public void greeting(){
            System.out.println(x+y);
        }
    }
}
public class Main {
    public static void main(String[] args){
        Outside out = new Outside();
        Outside.Inside in = out.new Inside();
        in.greeting();
        
        // Hello World!
    }
}


keyBinding

另一種接收使用者按鍵輸入的模式,更適合用於遊戲開發

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

public class Game {
    JFrame frame;
    JLabel label;

    // 這邊設Action變數,並建立Inner Class
    Action upAction;
    Action downAction;
    Action leftAction;
    Action rightAction;

    Game(){
        frame = new JFrame("KeyBinding Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);
        frame.setLayout(null);

        label = new JLabel();
        label.setBackground(Color.red);
        label.setBounds(100, 100, 100, 100);
        label.setOpaque(true);

        upAction = new UpAction();
        downAction = new DownAction();
        leftAction = new LeftAction();
        rightAction = new RightAction();

        label.getInputMap().put(KeyStroke.getKeyStroke("UP"), "upAction");
        label.getActionMap().put("upAction", upAction);
        label.getInputMap().put(KeyStroke.getKeyStroke("DOWN"), "downAction");
        label.getActionMap().put("downAction", downAction);
        label.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "leftAction");
        label.getActionMap().put("leftAction", leftAction);
        label.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "rightAction");
        label.getActionMap().put("rightAction", rightAction);

        frame.add(label);
        frame.setVisible(true);
    }

    // 下面的Action都是Inner Class,都extends AbstractAction
    public class UpAction extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {
            label.setLocation(label.getX(), label.getY()-10);
        }
    }
    public class DownAction extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {
            label.setLocation(label.getX(), label.getY()+10);
        }
    }
    public class LeftAction extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {
            label.setLocation(label.getX()-10, label.getY());
        }
    }
    public class RightAction extends AbstractAction{
        @Override
        public void actionPerformed(ActionEvent e) {
            label.setLocation(label.getX()+10, label.getY());
        }
    }
}

結語

今天是接觸Java GUI的第五天,順著這五天以來學到的東西,似乎已經可以大概抓到整個製作遊戲的雛型了,我目前的想法是先創建frame,然後在frame中新增panel,然後調整panel的內容,用來抓使用者按鍵輸入之類的,就可以進行遊戲了。
今天也是快樂學習的一天,明天繼續!/images/emoticon/emoticon34.gif


上一篇
Day 15:Java GUI (四)
下一篇
Day 17:Java GUI (六)
系列文
30天從基礎學起Java,直到做出我的第一個遊戲18
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言