2016-09-18 2 views
2

Я программирую программу Tower of Hanoi в соответствии с инструкциями, приведенными в классе. Прежде чем продолжить, я хотел бы заявить, что я искал похожие ответы и понимаю, что лучше использовать KeyBinding. Мы должны использовать KeyListener в классе.KeyPressed() не отвечает (Regular Java)

Если вы хотите увидеть, как Башня Ханоя работает, пожалуйста, читайте здесь: https://en.wikipedia.org/wiki/Tower_of_Hanoi

Моя программа использует ключи 1, 2 и 3 для каждого из трех стержней. Вы нажимаете эти два раза, чтобы сделать один ход: первый щелчок, чтобы указать направляющий стержень, а второй - указать приемный стержень.

Я добавил addKeyListener(this) в свой конструктор вместе с письмом addNotify() способ, который делает {requestFocus();}. Компиляция не создает ошибок. Я добавил System.out.println("This ran!"); внутри нескольких областей метода KeyPressed, чтобы проверить, не работает ли он.

Единственная другая информация, которая может быть полезна, заключается в том, что я использую метод getKeyChar() для определения того, какой ключ нажат.

Любая помощь или комментарий, если я упустил какой-либо аспект использования KeyListener и KeyPressed правильно, будет очень признателен. Спасибо.

Вот минимальный код, необходимый для воссоздания пример:

Main Class:

class MainFile { 
    public static void main(String[] args) { 
     new TFrame("Frame"); 
    } 
} 

Группа Класс:

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

public class TPanel extends JPanel implements KeyListener { 
    boolean towerA; 
    boolean towerB; 
    boolean towerC; 

    public TPanel() { 
     super(); 
     setSize(600, 600); 
     addKeyListener(this); 
    } 

    public void keyTyped(KeyEvent e) { 
    } 

    public void addNotify() { 
     requestFocus(); 
    } 

    public void paint(Graphics g) { 
     addNotify(); 
     if (towerA == true) { 
      g.setColor(Color.GREEN); 
      g.fillRect(20, getHeight(), 40, 100); 
     } else { 
      g.setColor(Color.RED); 
      g.fillRect(20, 0, 40, 100); 
     } 
     if (towerB == true) { 
      g.setColor(Color.GREEN); 
      g.fillRect(100, 0, 40, 100); 
     } else { 
      g.setColor(Color.RED); 
      g.fillRect(100, 0, 40, 100); 
     } 
     if (towerC == true) { 
      g.setColor(Color.GREEN); 
      g.fillRect(180, 0, 40, 100); 
     } else { 
      g.setColor(Color.RED); 
      g.fillRect(180, 0, 40, 100); 
     } 
     repaint(); 
    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
     // TODO Auto-generated method stub 
     addNotify(); 
     if (e.getKeyChar() == '1') { 
      towerA = true; 
     } 
     if (e.getKeyChar() == '2') { 
      towerB = true; 

     } 
     if (e.getKeyChar() == '3') { 
      towerC = true; 

     } 
    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 
} 

Класс Рама:

import javax.swing.JFrame; 
import java.awt.Insets; 
import java.awt.event.KeyEvent; 
import java.awt.Dimension; 

public class TFrame extends JFrame implements java.awt.event.KeyListener { 
    public TFrame(String title) { 
     super(title); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setResizable(false); 
     pack(); 
     addKeyListener(this); 

     TPanel p = new TPanel(); 
     Insets frameInsets = getInsets(); 

     int frameWidth = p.getWidth() + (frameInsets.left + frameInsets.right); 
     int frameHeight = p.getHeight() + (frameInsets.top + frameInsets.bottom); 

     setPreferredSize(new Dimension(frameWidth, frameHeight)); 

     setLayout(null); 
     add(p); 
     pack(); 
     setVisible(true); 
    } 

    @Override 
    public void keyTyped(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
     // TODO Auto-generated method stub 

    } 

} 

UPDATE : Я положил некоторые дальнейшие исследования и обнаруживают, что это может быть что-то, фокусирующее компонент. Я добавил много фокусов и вызовов addNotify() во всей программе, и это, похоже, не имеет эффекта.

+0

Вы уверены, что используете метод addNotify? Иногда вам нужно предшествовать requestFocus() с помощью setFocusable (true). Альтернативно, в зависимости от вашей настройки вам может потребоваться requestFocusInWindow(). Если моя память служит мне правильно, то для JApplets. –

+1

Вам нужно будет добавить соответствующие части вашего кода. –

+0

@ Perry Monschau Я действительно называю это методом paint() и в KeyListener, чтобы быть уверенным. – AeroFighter76

ответ

2

Это, будучи одной копией/вставкой, скомпилировать, запустить MCVE. Существует ряд проблем с кодом, рассматриваемым в вопросе. Я исправил некоторые из них (см. Комментарии в коде), прежде чем споткнуться о фундаментальную причину проблемы, поскольку код переопределяет метод addNotify(). Обратите внимание, что вызов в requestFocus() в это время не будет выполнен в любом случае, учитывая, что компонент должен быть не только фокусируемым, но и видимым на экране для его работы.

Эта часть оставлена ​​в качестве упражнения для вас, но если у вас есть проблемы, отправьте другой вопрос с MCVE.

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

public class TPanel extends JPanel implements KeyListener { 

    boolean towerA; 
    boolean towerB; 
    boolean towerC; 

    public TPanel() { 
     super(); 
     setSize(600, 600); 
     // for testing 
     setBackground(Color.BLACK); 
     addKeyListener(this); 
     // A component must BE focusable before it can hop to accept the focus. 
     setFocusable(true); 
     // create an animation listener 
     ActionListener animationListener = new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       repaint(); 
      } 
     }; 
     // create and start an animation timer 
     Timer timer = new Timer(200, animationListener); 
     timer.start(); 
     requestFocus(); 
    } 

    public void keyTyped(KeyEvent e) { 
    } 

    @Override 
    /* I've never bothered to find out what addNotify() method is for. 
    Inadvisable to use it to request the focus! 
    public void addNotify() { 
     requestFocus(); 
    } */ 

    /* For any JComponent, we should override the paintComponent(Graphics) 
    method rather than the paint(Graphics) method. */ 
    public void paintComponent(Graphics g) { 
     /* 1st thing should be done in any overridden paint method is to 
     call the super method. */ 
     super.paintComponent(g); 
     //addNotify(); 
     if (towerA == true) { 
      g.setColor(Color.GREEN); 
      g.fillRect(20, getHeight(), 40, 100); 
     } else { 
      g.setColor(Color.RED); 
      g.fillRect(20, 0, 40, 100); 
     } 
     if (towerB == true) { 
      g.setColor(Color.GREEN); 
      g.fillRect(100, 0, 40, 100); 
     } else { 
      g.setColor(Color.RED); 
      g.fillRect(100, 0, 40, 100); 
     } 
     if (towerC == true) { 
      g.setColor(Color.GREEN); 
      g.fillRect(180, 0, 40, 100); 
     } else { 
      g.setColor(Color.RED); 
      g.fillRect(180, 0, 40, 100); 
     } 
     /* As mentioned in comment, this will cause an infinite loop & block 
     the EDT! Use a Swing Timer for animation. */ 
     // repaint(); 
    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
     // for testing 
     System.out.println("e: " + e); 
     addNotify(); 
     if (e.getKeyChar() == '1') { 
      towerA = true; 
     } 
     if (e.getKeyChar() == '2') { 
      towerB = true; 

     } 
     if (e.getKeyChar() == '3') { 
      towerC = true; 

     } 
    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
    } 

    public static void main(String[] args) { 
     new TFrame("Frame"); 
    } 
} 

class TFrame extends JFrame implements java.awt.event.KeyListener { 

    public TFrame(String title) { 
     super(title); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setResizable(false); 
     pack(); 
     addKeyListener(this); 

     TPanel p = new TPanel(); 
     Insets frameInsets = getInsets(); 

     int frameWidth = p.getWidth() + (frameInsets.left + frameInsets.right); 
     int frameHeight = p.getHeight() + (frameInsets.top + frameInsets.bottom); 

     setPreferredSize(new Dimension(frameWidth, frameHeight)); 

     // Java GUIs were designed to work with layouts. Use them! 
     // setLayout(null); 
     add(p); 
     pack(); 
     setVisible(true); 
    } 

    @Override 
    public void keyTyped(KeyEvent e) { 
    } 

    @Override 
    public void keyPressed(KeyEvent e) { 
    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
    } 
} 
+1

В качестве дополнения, поясняйте, когда следует переопределять paint/paintComponent: http://stackoverflow.com/questions/9389187/difference-between-paint-paintcomponent-and-paintcomponents-in-swing –

+0

Метод AddNotify не вызывал requestFocus правильно, как вы сказали. Отмечено правильно – AeroFighter76