Страницы

Поиск по вопросам

понедельник, 15 июля 2019 г.

swing KeyListener не отлавливает нажатие

import javax.swing.*; import java.awt.*;
public class Main { public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() { public void run() {
JFrame frameMain = new JFrame(); frameMain.setLayout(new BorderLayout()); JPanel label = new JPanel(); JButton button = new JButton("Button"); label.add(button); // Вопрос 3
frameMain.add(label, BorderLayout.NORTH); HelloComponent helloComponent = new HelloComponent(); frameMain.add(helloComponent, BorderLayout.CENTER); frameMain.addKeyListener(helloComponent); // Вопрос 2
frameMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frameMain.setSize(400, 400); frameMain.setVisible(true);
} });
} }

import javax.swing.*; import java.awt.*; import java.awt.event.*;
public class HelloComponent extends JComponent implements KeyListener, MouseMotionListener {
String theMessage = "Hello"; int x = 10; int y = 10;
public HelloComponent() {
//addKeyListener(this); // Вопрос 1 addMouseMotionListener(this); }
public void paintComponent (Graphics g){ g.drawString(theMessage, x, y); }
@Override public void keyTyped(KeyEvent e) { }
@Override public void keyPressed(KeyEvent e) { }
@Override public void keyReleased(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_LEFT){ theMessage = "olleH"; repaint(); } else if(e.getKeyCode() == KeyEvent.VK_RIGHT){ theMessage = "Hello"; repaint(); } }
@Override public void mouseDragged(MouseEvent e) { x = e.getX(); y = e.getY(); repaint();
}
@Override public void mouseMoved(MouseEvent e) { } }
Вопрос 1
Если в конструкторе добавлять addKeyListener(this), то он не работает и при этом addMouseMotionListener(this) работает нормально.
Вопрос 2
Если добавлять во Farame frameMain.addKeyListener(helloComponent); все работает, но перестает если добавлять кнопку.
Вопрос 3
Потом не удается установить фокус. При этом мышка перерисовывает как нужно.
Подскажите где и что не так?


Ответ

Компонент порождает KeyEventы, только когда находится в фокусе. Чтобы ваш компонент мог получить фокус автоматически, нужно вызвать для него setFocusable( true ), или сделать привязку клавиш через Input Map (да, isFocusable() возвращает true, но фокус не передается, так задумано (JDK-6530201)). Поскольку окно не содержит компонентов, которым может отдать фокус, оно оставляет его себе, поэтому ваш компонент получает события, порождаемые окном. Кнопка может получить фокус и получает, а ваш компонент снова не видит нажатия.
Небольшие доработки для иллюстрации:
public HelloComponent() { setFocusable( true );
addKeyListener(this); // Вопрос 1 addMouseMotionListener(this);
addFocusListener( new FocusListener() { // перерисовка при получении и потере фокуса @Override public void focusLost(FocusEvent e) { repaint(); } @Override public void focusGained(FocusEvent e) { repaint(); } });
addMouseListener( new MouseAdapter() { // запрос фокуса при нажатии мыши @Override public void mousePressed( MouseEvent e ) { requestFocusInWindow(); } }); }
public void paintComponent (Graphics g){ g.setColor( isFocusOwner() ? Color.RED : Color.ORANGE ); g.fillRect(0, 0, getWidth(), getHeight() ); g.setColor( Color.BLACK ); g.drawString(theMessage, x, y); }
Java Turtorials: How to use focus subsystem

Комментариев нет:

Отправить комментарий