Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> События клавиатуры. К чему цеплять листенер? 
V
    Опции темы
Mirkes
Дата 28.3.2012, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Есть некое окно для отображения графиков.
Ниже его полный код
Код

public class ErrFrame extends JFrame implements ActionListener, KeyListener {

    @SuppressWarnings("compatibility:-6367160726117705553")
    private static final long serialVersionUID = -1889562533017921122L;

    private BorderLayout borderLayout1 = new BorderLayout();
    private JPanel jPanel1 = new JPanel();
    private JLabel jLabel1 = new JLabel();
    private JLabel lFVU = new JLabel();
    private JButton jSave = new JButton();
    private JLabel jNodes = new JLabel();
    private JLabel jLabel4 = new JLabel();
    private JLabel jLabel5 = new JLabel();
    private JLabel lEnergy = new JLabel();
    private JPanel drawPane = new JPanel();
    private MyDrawPane nodesPane = new MyDrawPane(Color.BLUE);
    private MyDrawPane fvuPane = new MyDrawPane(Color.GREEN);
    private MyDrawPane energyPane = new MyDrawPane(Color.MAGENTA);
    private MyDrawPane stepsPane = new MyDrawPane(Color.RED);
    private int steps = 0;

    /**
     * @throws HeadlessException
     */
    public ErrFrame() throws HeadlessException {
        super();
        try {
            jbInit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void jbInit() throws Exception {
        this.getContentPane().setLayout(borderLayout1);
        jLabel1.setText("   FVU");
        jLabel1.setForeground(Color.GREEN);
        lFVU.setText("100.000%");
        lFVU.setForeground(Color.GREEN);
        jSave.setText("Save to file");
        jSave.addActionListener(this);
        jNodes.setText("500");
        jNodes.setForeground(Color.BLUE);
        jLabel4.setText("Nodes");
        jLabel4.setForeground(Color.BLUE);
        jLabel5.setText("   Energy");
        jLabel5.setForeground(Color.MAGENTA);
        lEnergy.setText("1000.0000");
        lEnergy.setForeground(Color.MAGENTA);
        drawPane.setLayout(new OverlayLayout(drawPane));
        jPanel1.add(jLabel4, null);
        jPanel1.add(jNodes, null);
        jPanel1.add(jLabel1, null);
        jPanel1.add(lFVU, null);
        jPanel1.add(jLabel5, null);
        jPanel1.add(lEnergy, null);
        jPanel1.add(jSave, null);
        this.getContentPane().add(jPanel1, BorderLayout.NORTH);
        drawPane.setBackground(Color.WHITE);
        drawPane.add(nodesPane);
        drawPane.add(fvuPane);
        drawPane.add(energyPane);
        drawPane.add(stepsPane);
        this.getContentPane().add(drawPane, BorderLayout.CENTER);
        jSave.addKeyListener(this);
    }

    /**
     * @param step - number of step to show
     */
    public void setStep(int step) {
        // test for correctness
        if (step >= steps)
            return;
        stepsPane.setStep(step);
        double x = fvuPane.getData(step);
        String s = String.format(Locale.US, "%7.3f", x);
        lFVU.setText(s + "%");
        x = energyPane.getData(step);
        s = String.format(Locale.US, "%9.4g", x);
        lEnergy.setText(s);
        x = nodesPane.getData(step);
        s = String.format(Locale.US, "%4.0f", x);
        jNodes.setText(s);
    }

    /**
     * @param fvu array to  use
     * @param energy array to  use
     * @param nod array to  use
     */
    public void setData(double[] fvu, double[] energy, double[] nod) {
        nodesPane.setDots(nod);
        fvuPane.setDots(fvu);
        energyPane.setDots(energy);
        if (nod == null) {
            stepsPane.setStep(0, 0);
            steps = 0;
        } else {
            steps = nod.length;
            stepsPane.setStep(0, steps);
        }
        setStep(0);
    }

    /**
     * @param e - action;
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        // Save to file
        // Request file name
        JFileChooser fd = PicsWriter.getFileChooser(PicsWriter.TEXT);
        int ret = fd.showSaveDialog(this);
        if (ret != JFileChooser.APPROVE_OPTION)
            return;
        File fi = fd.getSelectedFile();
        BufferedWriter bw;
        try {
            bw = new BufferedWriter(new FileWriter(fi));
        } catch (IOException f) {
            return;
        }
        double x;
        for (int i = 0; i < steps; i++) {
            try {
                bw.write("" + (i + 1) + ((char)9));
            } catch (IOException f) {
                System.out.println(f.getMessage());
            }
            x = nodesPane.getData(i);
            try {
                bw.write(String.format(Locale.US, "%4.0f", x) + ((char)9));
            } catch (IOException f) {
                System.out.println(f.getMessage());
            }
            x = fvuPane.getData(i);
            try {
                bw.write(String.format(Locale.US, "%7.3f", x) + ((char)9));
            } catch (IOException f) {
                System.out.println(f.getMessage());
            }
            x = energyPane.getData(i);
            try {
                bw.write(String.format(Locale.US, "%12.5g", x) + ((char)9));
            } catch (IOException f) {
                System.out.println(f.getMessage());
            }
            try {
                bw.newLine();
            } catch (IOException f) {
                System.out.println(f.getMessage());
            }
        }
        try {
            bw.close();
        } catch (IOException f) {
            System.out.println(f.getMessage());
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if ((e.getKeyCode() == 154) && (e.getModifiersEx() == 128)) {
            System.out.println("Key released with code '" + e.getKeyCode() + "' (" +
                               KeyEvent.getKeyText(e.getKeyCode()) + ") with modifyer '" + e.getModifiersEx() + "' (" +
                               KeyEvent.getModifiersExText(e.getModifiersEx()) + ")");
            PicsWriter.savePicture(drawPane);
        }
    }
}


Пытался прицепить листенер событий клавиатуры к разным объектам. Работает только если прицеплено к кнопке. Насколько я понимаю это потому, что только кнопка в данном окне может иметь фокус.

У меня есть другое окно, в котором есть много разных компонентов, способных иметь фокус (кнопки, метки). Мне нужно, чтобы при нажатии PrtScr вызывался некий метод. Вопрос, к какому компоненту я должен прицепить слушателя событий клавиатуры? Очень не хочется цеплять ко всем компонентам.
Подскажите, пожалуйста, как выбрать компонент, который слушать.


--------------------
Mirkes
PM MAIL   Вверх
Dummy
Дата 28.3.2012, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 2
Всего: 19



Попробуйте вот такое:
Код

KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor(new KeyEventPostProcessor() {
    @Override
    public boolean postProcessKeyEvent(KeyEvent ke) {
        if (ke.getID() == KeyEvent.KEY_RELEASED && ke.getKeyCode() == KeyEvent.VK_PRINTSCREEN) {
            yourMethod();          
        }
        return false;
    }
});

Причем для кода VK_PRINTSCREEN у меня событие KEY_PRESSED не приходило - только KEY_RELEASED. Говорят, специфика Windows.
PM MAIL   Вверх
Mirkes
Дата 29.3.2012, 03:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Спасибо, попробую.


--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 29.3.2012, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Dummy, спасибо, все работает, только событие прилетает три раза. Это нормально?


--------------------
Mirkes
PM MAIL   Вверх
Dummy
Дата 29.3.2012, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 2
Всего: 19



Вы имеете в виду, что postProcessKeyEvent дергается три раза? Это нормально: первый раз приходит событие KEY_PRESSED, второй - KEY_TYPED, третий - KEY_RELEASED.

Это сообщение отредактировал(а) Dummy - 29.3.2012, 14:55
PM MAIL   Вверх
Mirkes
Дата 29.3.2012, 17:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Мне не жалко. Есть одна проблема - я попробовал отрезасть создание и открытие этого окна в отдельный проект и получил одиночный вызов. :(
Я могу сбросить весь апплет, он не секретный. Но там куча классов и т.д. Если готовы копаться напишите - сброшу.

Пока собрался ответить, Ваш пост изменился. Событие в усеченной версии вызывается один раз. А в полной три. И все три - release.

Это сообщение отредактировал(а) Mirkes - 29.3.2012, 17:17


--------------------
Mirkes
PM MAIL   Вверх
Dummy
Дата 29.3.2012, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 2
Всего: 19



Скидывайте. Этот вопрос хочется до конца довести smile
PM MAIL   Вверх
Mirkes
Дата 30.3.2012, 03:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Отправил на личную почту. К сожалению отправить личным сообщением на форуме не получилось, поскольку к сообщению нельзя прицепить файл.

Причина именно тройного вызова метода установлена. У меня есть три экземпляра окна этого типа. Иногда они отображаются, иногда не все, иногда ни одного. Но они есть. Осталась мелочь - понять в каком окне была нажата кнопка PrintScreen. Наверное можно подняться от того компнента, который передается в событии и найти по дороге рамку. Прошу прощения за беспокойство, только сейчас сообразил добавить имя окна в отладочную информацию.

Это сообщение отредактировал(а) Mirkes - 30.3.2012, 03:53


--------------------
Mirkes
PM MAIL   Вверх
Dummy
Дата 30.3.2012, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 21.5.2007

Репутация: 2
Всего: 19



Для получения фокусного окна можно использовать такое:
Код

Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();

Чтобы узнать, какой конкретно элемент находится в фокусе:
Код

Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();

PM MAIL   Вверх
Mirkes
Дата 1.4.2012, 07:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Dummy, спасибо большое - помогло. Правда из головного апплета получением активного окна обойтись не удалось, пришлось идти к предку от активного компонента:
Код

    private boolean myKeyEvent(KeyEvent e) {
        if (e.getID() == KeyEvent.KEY_RELEASED && e.getKeyCode() == KeyEvent.VK_PRINTSCREEN &&
            e.getModifiersEx() == InputEvent.CTRL_DOWN_MASK) {
            Component comp = e.getComponent();
            while (comp != null && !comp.equals(this)) {
                comp = comp.getParent();
            }
            if (comp == null)
                return false;
            PicsWriter.savePicture(deskTop);
            return true;
        }
        return false;
    }

Это связано с тем, что при автономном запуске апплет вставляется во фрейм. И при указании активного окна указывается фрейм, а не апплет.
Спасибо большое за помощь. Поставил +1


--------------------
Mirkes
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.0499 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.