5

このプログラムを変更して、城の画像を描画し、上下の矢印キーを使用してこの画像を拡大縮小できるようにしようとしています。キーリスナーを機能させることができません。プログラムは実行されますが、キーを押しても反応しません。どんな助けでも感謝します、ありがとう。

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

public class DrawImage extends JFrame implements KeyListener {
int scale = 1;
    private Image image;
    enter code here
    public static void main(String[] args) {
        new DrawImage();
    }

    public DrawImage() {
        super("DrawImage");
        setSize(600,600);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Toolkit tk = Toolkit.getDefaultToolkit();
        image = tk.getImage(getURL("castle.png"));
        addKeyListener(this);
    }

    private URL getURL(String filename) {
        URL url = null;
        try {
            url = this.getClass().getResource(filename);
        }
        catch (Exception e) { }
        return url;
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        AffineTransform trans = new AffineTransform();
        trans.scale(scale, scale);
        System.out.println("scale: " + scale);
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0, 0, getSize().width, getSize().height);
        g2d.setTransform(trans);
        g2d.drawImage(image, 0, 40, this);
        addKeyListener(this);
    }

    public void keyReleased(KeyEvent e) { }
    public void keyTyped(KeyEvent e) { }
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_UP) {
            scale++;
        }
        if (key == KeyEvent.VK_DOWN) {
            scale--;
        }
    }
}
4

1 に答える 1

8

キーリスナーを機能させることができません。プログラムは実行されますが、キーを押しても反応しません。

あなたの問題は、ここで頻繁に尋ねられる非常に一般的な問題であり、ほとんどの場合、問題はフォーカスの欠如によるものです。つまり、リッスンされているコンポーネントに現在のフォーカスがなく、KeyListener が機能するにはフォーカスが不可欠です。

簡単な答えは、リッスンされているコンポーネントにフォーカスを与えることです。

より長いより良い答えは、KeyListeners を使用せず、代わりにそのようなプロジェクトに Key Bindings を使用することです。


編集
その他の問題:

  • 上記のコードでは、KeyListener を JFrame に追加していますが、KeyListener を使用する正当な理由があったとしても、これを行うべきではありません。
  • また、望ましくない副作用のリスクがあるため、私の意見ではさらに大きな問題である JFrame に直接描画しています。
  • paint メソッド内にリスナーを追加していますが、これはさらに大きな問題です。paint メソッドは (一般に) オーバーライドすべきではありません。また、オーバーライドする必要がある場合でも、プログラム ロジック、リスナーの追加または削除、または描画以外のアクティビティの実行には決して使用しないでください。塗装・塗装専用でお願い致します。
  • 代わりに、JPanel または JComponent で直接描画する必要があります。
  • 代わりpaintComponent(Graphics g)に、ペイント JPanel または JComponent のオーバーライドで描画を行う必要があります。
  • 上記のように、このメソッドはペイントとペイント専用であり、できるだけ高速である必要があります。
  • オーバーライドのsuper.paintComponent(g)内部を呼び出す必要があります。paintComponent(Graphics g)
  • ここでも、描画コンポーネントはキー バインドを使用してキー ストロークをリッスンする必要があります (チュートリアルはこちら)。このチュートリアルでは、この違い (KeyListener とキー バインディング) が重要な理由を説明します。

編集 2
コードがここに示すように、例外を無視したくありません。これは、盲目的な運転と同等のプログラミングであるためです。

  try {
     url = this.getClass().getResource(filename);
  } catch (Exception e) {
  }

簡潔にするために投稿されたコードの例外を無視しただけなので、これが本番コードの外観ではないことを願っていますが、これを見る多くの人にとっては、黒板に釘を打つようなものだと理解してください。


KeyListeners と Key Bindings の3 つの詳細を編集
: コードが KeyListener で動作するようになったと仮定し、他のフォーカス可能なコンポーネントを GUI に追加し、ユーザーの操作を介して何らかの方法でフォーカスを取得したと仮定すると、KeyBindings はもはや仕事。キーバインディングでこれを正しく行っていれば、これは問題になりません。


編集 4
スケール フィールドを int ではなく double にする必要があります。そして、実際にはそれを増やしたり減らしたりしたくはありませんが、それを掛けて、例として1.2などの乗数定数で割りたいとします。repaint()また、スケールを変更するたびに呼び出す必要があります。


編集 5
2 つのサンプル プログラムを確認してください。1 つ目は DrawImagePanelKeyListener.java と呼ばれ、KeyListener を使用し、2 つ目は DrawImagePanelKeyBindings と呼ばれ、キー バインディングを使用します。どちらも期待どおりにコンパイル、実行、機能するはずです。上矢印キーまたは下矢印キーを押すと、表示された画像が縮小または拡大します。ただし、両方の JButton が押されたときに、それらの動作の違いを見ることができます。ボタンを押して、キーの反応がどうなるか見てみましょう。KeyListener を持つコンポーネントがフォーカスを失うと、その KeyListener は機能しなくなりますが、キー バインディングを使用するコンポーネントには当てはまりません。

この問題を回避するには、他のすべてのコンポーネントがフォーカスされるのを防ぐことができますが、ほとんどの GUI では実用的ではなく、望ましくありません。

DrawImagePanelKeyListener.java

import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.io.IOException;
import java.net.*;
import java.awt.event.*;

@SuppressWarnings("serial")
public class DrawImagePanelKeyListener extends JPanel implements KeyListener {
   public static final String IMAGE_PATH = "https://duke.kenai.com/"
         + "nyanya/.Midsize/NyaNya.jpg.png";
   private static final double MULTIPLIER = 1.2;
   double scale = 1.0;
   private Image image;
   private Dimension initialSize = new Dimension(0, 0);

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            DrawImagePanelKeyListener drawImage = new DrawImagePanelKeyListener();
            drawImage.add(new JButton("Foo"));
            JFrame frame = new JFrame("Draw Image");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(drawImage);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
         }
      });
   }

   public DrawImagePanelKeyListener() {
      setFocusable(true);
      requestFocusInWindow();
      URL imgURL;
      try {
         imgURL = new URL(IMAGE_PATH);
         image = ImageIO.read(imgURL);
         initialSize = new Dimension(image.getWidth(this),
               image.getHeight(this));
         addKeyListener(this);
         setVisible(true);
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return initialSize;
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.BLACK);
      g.fillRect(0, 0, getSize().width, getSize().height);
      Graphics2D g2d = (Graphics2D) g.create();
      g2d.scale(scale, scale);
      g2d.drawImage(image, 0, 0, this);
   }

   public void keyReleased(KeyEvent e) {
   }

   public void keyTyped(KeyEvent e) {
   }

   public void keyPressed(KeyEvent e) {
      int key = e.getKeyCode();
      if (key == KeyEvent.VK_UP) {
         scale *= MULTIPLIER;
      }
      if (key == KeyEvent.VK_DOWN) {
         scale /= MULTIPLIER;
      }
      repaint();
   }
}

DrawImagePanelKeyBindings.java

import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.io.IOException;
import java.net.*;
import java.awt.event.*;

@SuppressWarnings("serial")
public class DrawImagePanelKeyBindings extends JPanel {
   public static final String IMAGE_PATH = "https://duke.kenai.com/"
         + "nyanya/.Midsize/NyaNya.jpg.png";
   private static final double MULTIPLIER = 1.2;
   double scale = 1.0;
   private Image image;
   private Dimension initialSize = new Dimension(0, 0);

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            DrawImagePanelKeyBindings drawImage = new DrawImagePanelKeyBindings();
            drawImage.add(new JButton("Foo"));
            JFrame frame = new JFrame("Draw Image");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(drawImage);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
         }
      });
   }

   public DrawImagePanelKeyBindings() {
      setBindings();
      URL imgURL;
      try {
         imgURL = new URL(IMAGE_PATH);
         image = ImageIO.read(imgURL);
         initialSize = new Dimension(image.getWidth(this),
               image.getHeight(this));
         setVisible(true);
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   private void setBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      final KeyStroke[] keyStrokes = {
            KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),
            KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)
      };
      for (final KeyStroke keyStroke : keyStrokes) {
         inputMap.put(keyStroke, keyStroke.toString());
         actionMap.put(keyStroke.toString(), new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent evt) {
               myKeyPressed(keyStroke.getKeyCode());
            }
         });
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return initialSize;
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.BLACK);
      g.fillRect(0, 0, getSize().width, getSize().height);
      Graphics2D g2d = (Graphics2D) g.create();
      g2d.scale(scale, scale);
      g2d.drawImage(image, 0, 0, this);
   }

   public void myKeyPressed(int key) {
      if (key == KeyEvent.VK_UP) {
         scale *= MULTIPLIER;
      }
      if (key == KeyEvent.VK_DOWN) {
         scale /= MULTIPLIER;
      }
      repaint();
   }
}
于 2013-08-09T21:38:16.943 に答える