3

ボールをペイントし、矢印キーを押すと、押した方向にボールが画面上を移動するプログラムを作成しようと思いました。最初に、「上」矢印キーの動きだけを行うプログラムを作成することから始めました。

解決策を探しましたが、このコードの何が問題なのかわかりません。入力マップとアクション マップの問題 (つまり、キーの押下を認識するプログラムの問題) なのか、Swing での JComponent クラスと JFrame クラスの動作の問題なのかはわかりません。問題は焦点かもしれないと思いました。コンポーネントにいつフォーカスがあるかを知る方法がよくわかりません。今のところ、キーは上ではなく CNTRL+Y に設定されていると思います。これは、ある時点で、入力マップ メーカーで上矢印を指定する文字列に問題があるのではないかと考えたからです。

この時点で、私はとてもイライラしていて、ただ何かをやらせようとしているだけなので、必要以上の入力マップを使用しています。

コードは次のとおりです。これは非常に短く、ひどくフォーマットされています (申し訳ありません)。

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

class BallMover
{
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                BallFrame frame = new BallFrame();
            }
        });

    }
}


class BallFrame extends JFrame
{
    private static final int DEFAULT_WIDTH = 500;
    private static final int DEFAULT_HEIGHT = 500;
    private BallComponent comp;

    public BallFrame()
    {
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setSize(this.DEFAULT_WIDTH, this.DEFAULT_HEIGHT);
        super.setResizable(false);
        super.add(new BallComponent());
        super.setVisible(true);
        super.setFocusable(true);
    }
}


class BallComponent extends JComponent
{
    private Ellipse2D.Double ellipse;
    private double x = 225;
    private double y = 225;
    private ActionPress actionPress;

    public BallComponent()
    {
        super();
        super.setFocusable(true);

        InputMap imap1 = this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp1");
        InputMap imap2 = this.getInputMap(JComponent.WHEN_FOCUSED);
        imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp2");
        InputMap imap3 = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);   
        imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp3");

        ActionMap amap = this.getActionMap();
        amap.put("keyUp1", actionPress);
        amap.put("keyUp2", actionPress);    
        amap.put("keyUp3", actionPress);
    }

    public void paintComponent(Graphics g)
    {
        super.repaint(); // clear component //
        Graphics2D g2d = (Graphics2D)g;
        this.ellipse = new Ellipse2D.Double(x, y, 50, 50);
        g2d.fill(this.ellipse);
    }

    private class ActionPress extends AbstractAction
    {
        public void actionPerformed(ActionEvent event)
        {
            y = y + 10;
            ellipse = new Ellipse2D.Double(x, y, 50, 50);
            repaint();
        }
    } 
}
4

3 に答える 3

2

を使用しKeyboardFocusManagerて、矢印キーのキーストロークをリッスンし、ボールの位置を更新できます。これが作り直されたコードです:

class BallFrame extends JFrame {
    private static final int DEFAULT_WIDTH = 500;
    private static final int DEFAULT_HEIGHT = 500;
    final BallComponent ball = new BallComponent();

    public BallFrame() {
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        super.setResizable(false);
        super.add(ball);
        super.setVisible(true);

        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventDispatcher(new KeyEventDispatcher() {
                    @Override
                    public boolean dispatchKeyEvent(KeyEvent e) {
                        if (e.getKeyCode() == KeyEvent.VK_UP)
                            ball.move(0, -10);
                        if (e.getKeyCode() == KeyEvent.VK_RIGHT)
                            ball.move(10, 0);
                        if (e.getKeyCode() == KeyEvent.VK_LEFT)
                            ball.move(-10, 0);
                        if (e.getKeyCode() == KeyEvent.VK_DOWN)
                            ball.move(0, 10);
                        return false;
                    }
                });

    }
}

そしてBallComponentクラスの場合:

static class BallComponent extends JComponent {
    private double x = 225;
    private double y = 225;
    private Ellipse2D.Double ellipse = new Ellipse2D.Double(x, y, 50, 50);

    public void move(int dX, int dY) {
        x += dX;
        y += dY;
        ellipse = new Ellipse2D.Double(x, y, 50, 50);
        repaint();
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.fill(ellipse);
    }
}
于 2012-07-13T21:02:17.597 に答える
2

このコード例を見てください:

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

public class PaintingPanel
{
    private CustomPanel drawingArea;
    private ActionMap actionMap;
    private int x;
    private int y;

    private enum Direction 
    {
        UP(KeyEvent.VK_UP),
        DOWN(KeyEvent.VK_DOWN),
        LEFT(KeyEvent.VK_LEFT),
        RIGHT(KeyEvent.VK_RIGHT);

        public int key;

        private Direction(int key)
        {
            this.key = key;
        }

        public int getKey()
        {
            return key;
        }
    }

    private class PanelAction extends AbstractAction
    {
        private Direction arrow;

        public PanelAction(Direction a)
        {
            arrow = a;
        }

        @Override
        public void actionPerformed(ActionEvent ae)
        {
            switch(arrow)
            {
                case UP:
                    y -= 1;
                    break;
                case DOWN:
                    y += 1;
                    break;
                case LEFT:
                    x -= 1;
                    break;
                case RIGHT:
                    x += 1;
                    break;
            }
            drawingArea.setValues(x, y);
        }
    }

    public PaintingPanel()
    {
        x = y = 5;
    }

    private void displayGUI()
    {
        JFrame frame = new JFrame("Painting Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        drawingArea = new CustomPanel();
        int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
        InputMap inputMap = drawingArea.getInputMap(condition);
        actionMap = drawingArea.getActionMap();

        for (Direction arrow : Direction.values())
        {
            int key = arrow.getKey();
            String name = arrow.name();
            inputMap.put(KeyStroke.getKeyStroke(
                            key, 0), name);
            actionMap.put(name, new PanelAction(arrow));                    
        }

        frame.setContentPane(drawingArea);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new PaintingPanel().displayGUI();
            }
        });
    }
}

class CustomPanel extends JPanel
{
    private final int SIZE = 500;
    private int x;
    private int y;
    private String text = "Hello World!";

    public CustomPanel()
    {
        x = y = 5;
        setOpaque(true);
        setBackground(Color.WHITE);
    }

    public void setValues(int x, int y)
    {
        this.x = x;
        this.y = y;
        repaint();
    }

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(SIZE, SIZE));
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.GREEN.darker());
        g.fillOval(x, y, 50, 50);
    }
}
于 2012-07-18T05:37:20.540 に答える
2

初期化していないようですactionPress- これを BallComponent コンストラクターに追加してみてください:

actionPress = new ActionPress();

つまり、コンストラクタは次のようになります

public BallComponent()
{
    super();
    super.setFocusable(true);

    InputMap imap1 = this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp1");
    InputMap imap2 = this.getInputMap(JComponent.WHEN_FOCUSED);
    imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp2");
    InputMap imap3 = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);   
    imap1.put(KeyStroke.getKeyStroke("ctrl Y"), "keyUp3");

    actionPress = new ActionPress();
    ActionMap amap = this.getActionMap();
    amap.put("keyUp1", actionPress);
    amap.put("keyUp2", actionPress);    
    amap.put("keyUp3", actionPress);
}
于 2012-07-13T19:32:06.043 に答える