2013-08-09 2 views
5

Я пытаюсь изменить эту программу, чтобы она рисовала изображение замка, и я могу масштабировать это изображение с помощью клавиш со стрелками вверх и вниз. Я не могу заставить keylistener работать, программа запускается, но не реагирует на нажатия клавиш. Любая помощь будет оценена, спасибо.Java KeyListener не обнаруживает ввод клавиатуры

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--; 
     } 
    } 
} 
+0

Пожалуйста, см редактирует, 1, 2, 3, и 4, чтобы ответить. Прокомментируйте, если что-то неясно. –

ответ

8

Я не могу управлять, чтобы получить KeyListener работать, прогоны программы, но он не реагирует на нажатие клавиш.

У вас очень распространенная проблема, которая задается здесь часто, и почти всегда проблема связана с отсутствием фокуса - что слушаемый компонент не имеет текущего фокуса, а фокус необходим для KeyListener для работы.

Короткий ответ - предоставить компонент, который прослушивается в фокусе.

Чем длиннее лучший ответ - не используйте KeyListeners и вместо этого используйте Key Bindings для такого проекта.


Редактировать
Другие проблемы:

  • В коде выше, вы добавляете KeyListener к JFrame, и это не должно быть сделано, даже если у вас была уважительная причина использовать KeyListeners.
  • Вы также рисуете непосредственно в JFrame, который, на мой взгляд, является еще более серьезной проблемой, поскольку вы рискуете нежелательными побочными эффектами.
  • Вы добавляете слушателя внутри метода краски, еще более серьезная проблема. Метод рисования не должен быть переопределен (в общем), и если вам нужно его переопределить, его никогда не следует использовать для логики программы, для добавления или удаления прослушивателей или для выполнения каких-либо действий, не связанных с окраской. Это должно быть только для рисования и рисования.
  • Вместо этого вы должны нарисовать непосредственно в JPanel или JComponent.
  • Вместо этого вы должны сделать рисунок в paintComponent(Graphics g) переопределить в своей картине JPanel или JComponent.
  • Как и описано выше, этот метод должен быть предназначен только для окраски и окраски и должен быть как можно быстрее.
  • Вы должны позвонить super.paintComponent(g) внутри вашего paintComponent(Graphics g) переопределить.
  • Снова компонент рисования должен прослушивать ключевые штрихи с помощью клавишных привязок (учебник here). В учебнике объясняется, почему это различие (KeyListener и Key Bindings) важно.

Edit 2
Вы никогда не хотите игнорировать исключения, как ваш код показывает здесь, так как это программирование эквивалентно вождения слепых

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

Надеюсь, это не то, как ваш код продукции похоже, что вы только проигнорировали исключения из вашего опубликованного кода ради краткости, но понимаете, что многие из нас видят, что это похоже на слуховые гвозди на доске.


Edit 3
Подробнее о KeyListeners против Key Bindings: Предположим, что вы получили ваш код для работы с KeyListener, то предположим, что вы добавили любые другие фокусируемые компоненты графического интерфейса пользователя, и они каким-то образом получили фокус через взаимодействие с пользователем, то ваши KeyBindings больше не будут работать. Если вы сделали это правильно с Key Bindings, это не будет проблемой.


Edit 4
Вы действительно хотите, чтобы ваш масштаб поля, чтобы быть двойной, а не инт. И вы действительно не хотите увеличивать и уменьшать его, а скорее хотите размножить его и разделить на некоторую константу множителя, скажем, 1.2 в качестве примера. Вы также захотите позвонить repaint() всякий раз, когда вы меняете масштаб.


Edit 5
Пожалуйста, проверьте две программы образца, первый, называется DrawImagePanelKeyListener.java, использует в KeyListener, в то время как второй, называемый DrawImagePanelKeyBindings, использует привязок ключей. Оба они должны компилироваться, запускаться и функционировать так, как ожидалось: при нажатии клавиш со стрелками вверх или вниз отображаемое изображение сжимается и растет. Различие в их поведении можно увидеть, когда нажата кнопка JButton. Нажмите кнопку и посмотрите, что произойдет с ответом вашего ключа. Когда компонент, у которого KeyListener теряет фокус, его KeyListener перестает работать, но то же самое не относится к компоненту, который использует привязки клавиш.

Клод, который может обойти эту проблему, может заключаться в том, чтобы не допустить попадания всех других компонентов в фокус, но это не практично или желательно с большинством графических интерфейсов.

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(); 
    } 
} 
Смежные вопросы