Java2 ME: keyPressed() не работает внутри GameCanvas

Я знаю, что J2ME довольно устарел, но я должен сделать это по заданию. В настоящее время я использую класс GameCanvas, и моя игра представляет собой поток, поэтому мой код выглядит примерно так.

class Game extends GameCanvas implements Runnable {
    public GameCanvas() {
        super(false);
    }

    public void run() {
        while (true) {
            draw();
            flushGraphics();
        }
    }

    protected void keyPressed(int keyCode) {
        System.out.println("Hey, it actually worked.");
        // other code to handle key press...
    }
}

Печально то, что метод keyPressed никогда не вызывается, как бы сильно я ни спамил на цифровой клавиатуре эмулятора. Я знаю о методе getKeyStates(), который есть у GameCanvas, но я не хочу его использовать, потому что хочу захватить не только игровые клавиши, но и цифровые клавиши 1~9.

Кто-нибудь знает, почему мой код не входит в мой метод keyPressed() и что я могу с этим поделать? Большое спасибо.


Не знаю, где я ошибся... но после небольшой настройки тут и там все заработало отлично. Большое спасибо, ребята! :)


person matt    schedule 12.12.2011    source источник
comment
Прежде всего, вы не закодировали constructor ! Вместо этого вы написали конструктор superclass!   -  person pheromix    schedule 12.12.2011
comment
Виноват. Я просто спешил с грубым примером того, как выглядит мой класс, лол.   -  person matt    schedule 12.12.2011
comment
Я не эксперт по Java ME, но разве ваш класс не должен реализовывать ActionListener или что-то в этом роде?   -  person Mr1159pm    schedule 12.12.2011


Ответы (2)


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

Для простого теста, если приведенное выше предположение верно, просто вставьте sleep в цикл, примерно как показано ниже:

    while (true) {
        draw();
        flushGraphics();
        try { Thread.sleep(100); } // sleep for 1/10 sec
        catch (InterruptedException ie) { System.out.println(ie); }
    }

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

person gnat    schedule 12.12.2011
comment
Хм, спасибо за идею. Я попробовал, но, к сожалению, я все еще не могу заставить keyPressed() срабатывать, как в классе Canvas... :( Если это поможет, я попытался реализовать метод input(), вызываемый внутри цикла while, при этом я пытаюсь использовать getKeyStates() GameCanvas. Это тоже не работает, и я понятия не имею, почему... - person matt; 12.12.2011
comment
@matt при экспериментировании дважды проверьте, вызываете ли вы super в конструкторе со значением параметра false — это значение может вызвать или прервать доставку ключевых событий, см. Документация API для конструктора GameCanvas. Также на время отбросьте использование getKeyStates — оставьте для последующей отладки - person gnat; 12.12.2011
comment
Да, я использую super(false), но это все равно не работает. Я не уверен, в чем именно проблема... если это поможет, этот класс вызывается потоком и вызывает другие потоки, все используя .start(). - person matt; 12.12.2011
comment
@matt хм звучит интересно. То, как вы описываете, выглядит нормально для меня, потоки, начало и тому подобное. Как вы отлаживаете? вы используете эмулятор? Кроме того, попробуйте усилить сон — скажем, sleep(1000) — обновление, вероятно, будет выглядеть ужасно, но вы, по крайней мере, убедитесь, что это не узкое место. - person gnat; 12.12.2011
comment
Пробовал с sleep(5000), обновления были ужасными, но все равно не работает.. Да, я использую эмулятор, DefaultFxPhone1, если это поможет.. - person matt; 12.12.2011
comment
@matt, вы пробовали тестировать с помощью эмулятора телефона cldc - iirc в WTK/ME SDK называется DefaultColorPhone? Я немного больше доверяю этому старому эмулятору, чем новому блестящему эффекту :) - person gnat; 12.12.2011
comment
Я думаю, что у меня его нет... Пробовал с DefaultCldcPhones, и мне сказали, что слишком мало памяти. Во всяком случае, я создал совершенно новое приложение Java ME с реализацией, и, похоже, оно отлично работает. Я думаю, что проблема может заключаться в чем-то другом... Собираюсь сделать перерыв. В любом случае спасибо за все идеи! :) - person matt; 12.12.2011

Выдержка из документации MIDP для GameCanvas(...)

Если разработчику нужно только запросить статус ключа с помощью метода getKeyStates, механизм обычных событий ключа можно отключить для игровых ключей, пока отображается этот GameCanvas. Если приложению это не нужно, подавление ключевых событий может повысить производительность за счет исключения ненужных системных вызовов методов keyPressed, keyRepeated и keyReleased.

Обратите внимание, что ключевые события могут быть подавлены только для определенных игровых клавиш (UP, DOWN, FIRE и т. д.); ключевые события всегда генерируются для всех остальных клавиш.

Таким образом, super(false) подавляет ключевые методы прослушивания событий Canvas в GameCanvas. В этом случае, если вы все еще хотите зарегистрировать ключевые события, используйте getKeyEvents(...) в своем run(), файле пример приведен ниже.

 // Get the Graphics object for the off-screen buffer
 Graphics g = getGraphics();

 while (true) {
    // Check user input and update positions if necessary
    int keyState = getKeyStates();
    if ((keyState & LEFT_PRESSED) != 0) {
          sprite.move(-1, 0);
    }
    else if ((keyState & RIGHT_PRESSED) != 0) {
          sprite.move(1, 0);
    }

    // Clear the background to white
    g.setColor(0xFFFFFF);
    g.fillRect(0,0,getWidth(), getHeight());

    // Draw the Sprite
    sprite.paint(g);

    // Flush the off-screen buffer
    flushGraphics();
 }
person Vimal    schedule 12.12.2011