KeyListener на Canvas: запуск keyReleased, но без keyPressed или keyTyped

У меня есть JFrame с Canvas (кощунство, я знаю). Canvas имеет прикрепленные MouseListener и KeyListener и запросил фокус с помощью:

canvas.setFocusable(true);
canvas.requestFocusInWindow();

Когда я впервые запускаю его, все работает так, как ожидалось, события летают повсюду. Через несколько секунд он перестает реагировать на обычный ввод с клавиатуры (keyPressed и keyTyped не запускаются). Как ни странно, удерживание клевера (я на OSX) заставляет все работать нормально.

Что происходит? Почему это происходит и что я могу сделать, чтобы это исправить?

Изменить: я выяснил, какое поведение вызывает ошибку. Это начинается только тогда, когда вы удерживаете клавишу. Когда вы его отпускаете, события keyPressed перестают запускаться. Ниже мой MCVE.

import java.awt.Canvas;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.image.BufferStrategy;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;

public class Listener implements MouseListener,KeyListener {

    JFrame frame;
    Canvas screen;

    public Listener() {
        // initialize the screen canvas
        screen = new Canvas();
        Dimension size = new Dimension(640, 480);
        screen.setMinimumSize(size);
        screen.setMaximumSize(size);
        screen.setPreferredSize(size);
        screen.addMouseListener(this);
        screen.addKeyListener(this);
        screen.setFocusable(true);

        // initialize the frame
        frame = new JFrame("Parasite");
        frame.add(screen);
        frame.pack();
        frame.setVisible(true);

        screen.requestFocusInWindow();

        // create buffer strategy (after showing frame)
        screen.createBufferStrategy(2);
    }

    public static void main(String[] args) {
        Listener listener = new Listener();
    }

    public void mouseClicked(MouseEvent e) {
        System.out.println("click");
    }

    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}

    public void keyTyped(KeyEvent e) {
        System.out.println("t " + e.getKeyChar());
    }

    public void keyPressed(KeyEvent e) {
        System.out.println("p " + e.getKeyChar());
    }

    public void keyReleased(KeyEvent e) {
        System.out.println("r " + e.getKeyChar());
    }
}

person Shriken    schedule 24.11.2014    source источник
comment
Рассмотрите возможность предоставления исполняемого примера, демонстрирующего вашу проблему. Это приведет к меньшему количеству путаницы и лучшим ответам. Вы можете добавить MouseListener на холст и вызывать requestFocusInWindow всякий раз, когда по нему щелкают   -  person MadProgrammer    schedule 25.11.2014
comment
Я не могу это воспроизвести. Пожалуйста, предоставьте MCVE.   -  person Radiodef    schedule 25.11.2014
comment
Спасибо за совет. Я написал MCVE, и это помогло мне более точно определить ситуацию, в которой возникает ошибка. Подробности в редактировании выше.   -  person Shriken    schedule 25.11.2014


Ответы (1)


Оказывается, ошибка была вызвана каким-то коварным взаимодействием с меню акцентов в OSX. Системное значение по умолчанию (по крайней мере, для Йосемити) - это всплывающее меню, предлагающее вам акцентированные гласные, когда вы удерживаете буквенную клавишу. Хотя он не отображал меню, он, должно быть, делал что-то за кулисами, что мешало фокусировке.

Отключение меню акцентов устранило проблему. Для тех, кто не хочет переходить по ссылке, введите в свой терминал следующее.

defaults write -g ApplePressAndHoldEnabled -bool false
person Shriken    schedule 26.11.2014