Почему перестает работать keylistener?

В моей Java-программе всякий раз, когда я выбираю какой-либо текст из JTextField, keyListener прекращает обнаружение нажатий клавиш. Я заметил, что то же самое происходит, когда нажимается JButton. Нужно ли удалять keyListener из объектов после их использования? Если так, то как мне это сделать?

Вот копия программы, с которой у меня проблемы:

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

public class ColourDropper extends JPanel implements KeyListener, ActionListener {

    private Color background = Color.WHITE;
    private int mouseX, mouseY;
    private Timer t;
    private JTextField rgb, hsb, hex, alp;
    private JLabel tRgb, tHsb, tHex, tHold, tAlp;
    private String hexString;
    private boolean hold = false;

    public ColourDropper() {
        this.setFocusable(true);
        t = new Timer(100, this);
        t.start();
        rgb = new JTextField(7);
        hsb = new JTextField(9);
        hex = new JTextField(6);
        alp = new JTextField(3);
        tRgb = new JLabel("RGB");
        tHsb = new JLabel("HSB");
        tHex = new JLabel("Hex");
        tAlp = new JLabel("Alpha");

        rgb.setEditable(false);
        hsb.setEditable(false);
        hex.setEditable(false);
        alp.setEditable(false);

        add(tRgb);
        add(rgb);
        add(tHex);
        add(hex);
        add(tHsb);
        add(hsb);
        add(tAlp);
        add(alp);
        addKeyListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        if(!hold) {
            mouseX = MouseInfo.getPointerInfo().getLocation().x;
            mouseY = MouseInfo.getPointerInfo().getLocation().y;

            try {   
                Robot robot = new Robot();
                background = robot.getPixelColor(mouseX, mouseY);
                hexString = "#" + Integer.toHexString(background.getRGB()).toUpperCase().substring(2);
            } catch(AWTException a) {
                System.out.println(a.getMessage());
            } catch(Exception x) {
                System.out.println(x.getMessage());
            }

            try {
                rgb.setText(background.getRed() + " " + background.getGreen() + " " + background.getBlue());
                float[] cHsb = Color.RGBtoHSB(background.getRed(), background.getGreen(), background.getBlue(), null);
                int hue = (int)(cHsb[0] * 360);
                int sat = (int)(cHsb[1] * 100);
                int bri = (int)(cHsb[2] * 100);
                hsb.setText(hue + "� " + sat + "% " + bri + "%");
                hex.setText(hexString);
                alp.setText("" + background.getAlpha());
            } catch(NullPointerException n) {
                System.out.println(n.getMessage());
            }

            repaint();
        }
    }

    public void keyPressed(KeyEvent e) {        
        if(e.getKeyCode() == KeyEvent.VK_SPACE) hold = !hold;
        if(hold) {
            rgb.setForeground(Color.RED);
            hex.setForeground(Color.RED);
            hsb.setForeground(Color.RED);
            alp.setForeground(Color.RED);
        } else {
            rgb.setForeground(Color.BLACK);
            hex.setForeground(Color.BLACK);
            hsb.setForeground(Color.BLACK);
            alp.setForeground(Color.BLACK);
        }
    }

    public void paintComponent(Graphics g) {
        g.setColor(new Color(238, 238, 238));
        g.fillRect(0, 0, 246, 120);
        g.setColor(background);
        g.fillRect(5, 57, 230, 30);
    }

    public void keyTyped(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}

    public static void main(String[] args) {
        JFrame frame = new JFrame("Colour Dropper");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(246, 120));
        frame.pack();
        frame.setVisible(true);
        ColourDropper frameContent = new ColourDropper();
        frame.add(frameContent);
        frame.setResizable(false);
        frame.setLocation(100, 100);
        frame.setAlwaysOnTop(true);
        frame.setIconImage(Toolkit.getDefaultToolkit().getImage("dropper.png"));
    }
}

3 ответа

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

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

Тем не менее, основная проблема в этом случае заключается в том, что вы сделали рамку видимой перед добавлением компонентов в рамку. Метод setVisible(true) всегда должен выполняться после добавления всех компонентов в GUI. Добавление компонентов после того, как рамка стала видимой, вызвало проблему с фокусировкой панели. По крайней мере, это проблема с использованием JDK6_7 на XP.

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

Вам просто нужно добавить следующие строки:

frame.setFocusable(true);

в пустоте

а также

requestFocus();

в конце недействительного действия выполнено

Я надеялся, что это исправит ваши проблемы;)

Другие вопросы по тегам