Java paintComponent()可以在AbstractAction类中使用吗?

Java paintComponent()可以在AbstractAction类中使用吗?,java,swing,animation,abstract-action,Java,Swing,Animation,Abstract Action,我正在尝试制作一个创建JPanel的程序,当用户按下W、a、S和D时,绘制的立方体将在窗口中四处导航(每次按下一个键时按一定量),我创建了MoveCubeUp类,并重写其中的paintComponent方法,以便在调用立方体时重新绘制立方体,但这是行不通的。有人能解释一下原因吗 public MyPanel(){ … MoveSquareUp m=new MoveSquareUp(squareX, squareY); getInputMap().put(KeyStroke

我正在尝试制作一个创建JPanel的程序,当用户按下W、a、S和D时,绘制的立方体将在窗口中四处导航(每次按下一个键时按一定量),我创建了MoveCubeUp类,并重写其中的paintComponent方法,以便在调用立方体时重新绘制立方体,但这是行不通的。有人能解释一下原因吗

public MyPanel(){
    …
    MoveSquareUp m=new MoveSquareUp(squareX, squareY);
    getInputMap().put(KeyStroke.getKeyStroke(("W"), "pressed"));
getActionMap().put("pressed", m)
}
class MoveSquareUp extends AbstractAction{
    public int squareXX, squareYY;
    public moveSquare(){
    squareXX=squareX+5;
    }
//I define the paintComponent method to draw the rectangle with its set height        
//at squareXX, squareYY
//action method is null (I am still trying to figure out binding keys to    
//actions but the paintComponent not working is preventing that
}
如果格式不好,我很抱歉。第一个职位:/
是否需要在扩展JFrame的类中定义paint方法,如果需要,我如何将其用于abstractAction类(或者如何完全避免abstractAction类)?

问题的关键在于,您需要学会将模型与视图和控件分开。在这里,模型是精灵的位置,视图是绘制此位置的GUI,控件将保存包括AbstractAction在内的操作,如果可能,它们都应该彼此分离

因此,为了回答您的直接问题,任何paintComponent都不应该位于抽象操作内部,因为前者是视图的关键部分,而后者是控件的关键部分。相反,让视图反映模型的状态,模型的状态将由控件(操作)更改

关于你的另一个问题,所有的绘制方法都应该是JFrame的一部分吗:所有的绘制方法都不应该在扩展JFrame的类中,因为这个类是一个复杂的类,它创建了一个顶级窗口和几个子组件来显示你的GUI,如果你覆盖了它的绘制,子零部件的绘制效果可能不好。而是在扩展JPanel的类的paintComponent方法中绘制,然后在JFrame中显示此对象

例如:

package pkg3;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

public class GamePanel extends JPanel {
    private static final int ANIMATION_DELAY = 15;
    private final int HEIGHT = 400;
    private final int WIDTH = 600;
    private Square square;
    private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
    private Map<Integer, Direction> keyToDir = new HashMap<>();
    // !! private Circle circle;
    private Timer animationTimer;

    public GamePanel() {
        for (Direction dir : Direction.values()) {
            dirMap.put(dir, Boolean.FALSE);
        }
        keyToDir.put(KeyEvent.VK_UP, Direction.UP);
        keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
        keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
        keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
        setKeyBindings();
        setBackground(Color.white);
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setFocusable(true);
        square = new Square();
        animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
        animationTimer.start();
    }

    private void setKeyBindings() {
        int condition = WHEN_IN_FOCUSED_WINDOW;
        final InputMap inputMap = getInputMap(condition);
        final ActionMap actionMap = getActionMap();
        boolean[] keyPressed = { true, false };
        for (Integer keyCode : keyToDir.keySet()) {
            Direction dir = keyToDir.get(keyCode);
            for (boolean onKeyPress : keyPressed) {
                boolean onKeyRelease = !onKeyPress; // to make it clear how
                                                    // bindings work
                KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0, onKeyRelease);
                Object key = keyStroke.toString();
                inputMap.put(keyStroke, key);
                actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
            }
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        square.display(g);
    }

    private class AnimationListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent evt) {
            boolean repaint = false;
            for (Direction dir : Direction.values()) {
                if (dirMap.get(dir)) {
                    square.move(dir);
                    repaint = true;
                }
            }
            if (repaint) {
                repaint();
            }
        }
    }

    private class KeyBindingsAction extends AbstractAction {
        private Direction dir;
        boolean pressed;

        public KeyBindingsAction(Direction dir, boolean pressed) {
            this.dir = dir;
            this.pressed = pressed;
        }

        @Override
        public void actionPerformed(ActionEvent evt) {
            dirMap.put(dir, pressed);
        }
    }

    private static void createAndShowGUI() {
        GamePanel gamePanel = new GamePanel();
        JFrame frame = new JFrame("GamePanel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(gamePanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        gamePanel.requestFocusInWindow();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

enum Direction {
    UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
    private int incrX;
    private int incrY;

    private Direction(int incrX, int incrY) {
        this.incrX = incrX;
        this.incrY = incrY;
    }

    public int getIncrX() {
        return incrX;
    }

    public int getIncrY() {
        return incrY;
    }
}

class Square {
    private int x = 0;
    private int y = 0;
    private int w = 20;
    private int h = w;
    private int step = 1;
    private Color color = Color.red;
    private Color fillColor = new Color(255, 150, 150);
    private Stroke stroke = new BasicStroke(3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);

    public void display(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setColor(fillColor);
        g2d.fillRect(x, y, w, h);
        g2d.setStroke(stroke);
        g2d.setColor(color);
        g2d.drawRect(x, y, w, h);
        g2d.dispose();
    }

    public void setStep(int step) {
        this.step = step;
    }

    public void move(Direction dir) {
        x += step * dir.getIncrX();
        y += step * dir.getIncrY();
    }

}
pkg3包;
导入java.awt.*;
导入javax.swing.*;
导入java.awt.event.*;
导入java.util.EnumMap;
导入java.util.HashMap;
导入java.util.Map;
公共类游戏面板扩展了JPanel{
专用静态最终int动画_延迟=15;
私人最终内部高度=400;
专用最终整数宽度=600;
私人广场;
私有EnumMap dirMap=新EnumMap(Direction.class);
私有映射keyToDir=newhashmap();
//!!私人圈子;
私人定时器动画定时器;
公共游戏小组(){
for(Direction dir:Direction.values()){
dirMap.put(dir,Boolean.FALSE);
}
keyToDir.put(KeyEvent.VK_UP,Direction.UP);
keyToDir.put(KeyEvent.VK_DOWN,Direction.DOWN);
keyToDir.put(KeyEvent.VK_左,Direction.LEFT);
keyToDir.put(KeyEvent.VK_RIGHT,Direction.RIGHT);
setKeyBindings();
挫折地面(颜色:白色);
setPreferredSize(新尺寸(宽度、高度));
设置聚焦(真);
正方形=新正方形();
animationTimer=新计时器(ANIMATION_DELAY,new AnimationListener());
animationTimer.start();
}
私有void setKeyBindings(){
int condition=当在聚焦窗口中时;
最终InputMap InputMap=getInputMap(条件);
final ActionMap ActionMap=getActionMap();
布尔[]键按下={true,false};
for(整数键代码:keyToDir.keySet()){
Direction dir=keyToDir.get(keyCode);
用于(布尔onKeyPress:keyPressed){
boolean onKeyRelease=!onKeyPress;//说明如何
//绑定工作
击键击键=击键。getKeyStroke(keyCode,0,onKeyRelease);
Object key=keyStroke.toString();
inputMap.put(击键,键);
put(key,newkeybindingsaction(dir,onKeyPress));
}
}
}
公共组件(图形g){
超级组件(g);
方形显示器(g);
}
私有类AnimationListener实现ActionListener{
@凌驾
已执行的公共无效操作(操作事件evt){
布尔重绘=假;
for(Direction dir:Direction.values()){
if(dirMap.get(dir)){
方。移动(直接);
重新绘制=真;
}
}
如果(重新喷漆){
重新油漆();
}
}
}
私有类KeyBindingsAction扩展了AbstractAction{
私人指导主任;
布尔按下;
公钥绑定操作(方向方向,按布尔值){
this.dir=dir;
this.pressed=pressed;
}
@凌驾
已执行的公共无效操作(操作事件evt){
dirMap.put(dir,按下);
}
}
私有静态void createAndShowGUI(){
GamePanel GamePanel=新建GamePanel();
JFrame=新JFrame(“游戏面板”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(游戏面板);
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
gamePanel.requestFocusInWindow();
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGUI();
}
});
}
}
枚举方向{
向上(0,-1),向下(0,1),左(-1,0),右(1,0);
私人int incrX;
私营企业;
私人方向(内部控制,内部控制){
this.incrX=incrX;
this.incrY=incrY;
}
public int getIncrX(){
返回incrX;
}
public int getIncrY(){
返回incrY;
}
}
阶级广场{
私有整数x=0;
私有整数y=0;
私人int w=20;
私有int h=w;
私有整数步长=1;
私有颜色=Color.red;
私有颜色fillColor=新颜色(255、150、150);
私人住宅