简体   繁体   English

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

[英]Can paintComponent() be used in an AbstractAction class?

I am trying to make a program that creates a JPanel, and when the user presses W, A, S, and D, a cube that is drawn will navigate around in the window (by a certain amount every time a key is pressed), I have created the MoveCubeUp class, and I override the paintComponent method in it to repaint the cube when it is called, but it will not work. 我正在尝试创建一个创建JPanel的程序,并且当用户按下W,A,S和D时,绘制的多维数据集将在窗口中四处导航(每次按下某个键都将移动一定量),我已经创建了MoveCubeUp类,并且在其中重写了paintComponent方法,以便在调用多维数据集时重新绘制该多维数据集,但是它将无法正常工作。 Could someone explain why? 有人可以解释为什么吗?

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
}

I apologize if that was poorly formatted. 抱歉,如果格式化不正确。 1st post :/ Does the paint method need to be defined within the class that extends JFrame, and if so, how can I use it with an abstractAction class (or how can I avoid the AbstractAction class altogether)? 第一篇文章:/是否需要在扩展JFrame的类中定义paint方法,如果是的话,如何将其与abstractAction类一起使用(或者如何完全避免AbstractAction类)?

The crux of your problem is that you need to learn to separate your model from your view from your control. 问题的症结在于,您需要学习将模型与视图与控件分开。 Here the model is the location of your sprite, the view is the GUI that draws this position, and the control will hold the actions including your AbstractAction, and they all should be separate from each other if possible. 这里的模型是精灵的位置,视图是绘制此位置的GUI,控件将保存包括AbstractAction在内的动作,并且如果可能的话,它们应该彼此分开。

So to answer your direct question -- no paintComponent should definitely not be inside of an AbstractAction, since the former is a key part of the view while the latter is a key part of the control. 因此,要回答您的直接问题-绝对不应将paintComponent放在AbstractAction内,因为前者是视图的关键部分,而后者是控件的关键部分。 Instead have your view reflect the state of the model, and the model's state will be changed by the control (the actions). 而是让您的视图反映模型的状态,并且模型的状态将由控件(操作)更改。

Regarding your other question, should all painting methods be part of the JFrame: none of the painting methods should be in a class extending JFrame since this class is a complex class that creates a top level window and several sub components to display your GUI, and if you override its painting, you can effect painting of sub components in bad ways. 关于您的另一个问题,所有绘画方法都应属于JFrame:绘画方法均不应在扩展JFrame的类中,因为此类是一个复杂的类,可创建顶级窗口和几个子组件来显示GUI,并且如果覆盖其绘画,则可能会以不良方式影响子组件的绘画。 Instead draw in the paintComponent method of a class that extends JPanel, and then display this object in your JFrame. 而是绘制扩展JPanel的类的paintComponent方法,然后在JFrame中显示此对象。

For example: 例如:

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();
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM