правильный способ слушать нажатия клавиш Java - PullRequest
4 голосов
/ 05 октября 2011

Каков наилучший способ обработки нажатий клавиш в Java?Я пытался настроить свой код KeyListener, но потом я увидел, что следует использовать KeyBinding в Интернете, но после прочтения

http://download.oracle.com/javase/tutorial/uiswing/misc/keybinding.html

и не имея возможности найти какие-либо учебные пособия в Интернете, я дажеболее запутанный.

Вот то, что я пытался:

frame = new JFrame("Jay's Game Title");
Container panel = (JPanel)frame.getContentPane();
...
panel.setFocusable(true);
panel.requestFocus();
panel.addKeyListener(this);//TODO:fix me please, this is not working
frame.setSize(1024, 768);
frame.setVisible(true);
frame.setFocusable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

но безрезультатно.Любая помощь очень ценится, и в то же время я буду продолжать просматривать посты других и вычесывать больше своих волос.

примечание: мой код для моих кнопок работает просто замечательно, и я хотел бы, чтобы мойнажатия клавиш обрабатываются в другом файле keypresses.java или в каком-либо другом порядке, чтобы сохранить его организованным

package com.jayavon.game.client;
/****************************************************************
 *  Author      :   ***REMOVED***
 *  Start Date  :   09/04/2011
 *  Last Update :   10/04/2011
 *  
 *  Description
 *  This is the video game application
 *  This application is used to sending and receiving the messages
 *  and all of the game data(soon, hopefully :p).
 *  
 *  Remarks
 *  Before running the client application make sure the server is 
 *  running.
 ******************************************************************/
import javax.swing.*;

import java.awt.Container;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;

public class MyClient extends JFrame implements ActionListener, KeyListener{
    JFrame frame;
    JTextField chatBoxTxt;
    JButton sendButton, exitButton, onlineButton, backpackButton, characterButton, helpButton, optionsButton, questsButton, skillsButton;
    JInternalFrame skillsFrame, onlineFrame;
    DefaultListModel modelChatList;
    JList listForChat;
    JScrollPane chatScrollPane;
    DefaultListModel modelUserList;
    JList listForUsers;
    JScrollPane userListScrollPane;
    String name, password;
    Socket s, s1, s2;
    DataInputStream messageIn;
    DataOutputStream messageOut;
    DataInputStream userNameIn;
    DataOutputStream userNameOut;
    DataOutputStream userLogOut;

    MyClient(String name, String password) throws IOException{
        this.name = name;
        initGUI();
        s = new Socket("localhost",1004);   //creates a socket object
        s1 = new Socket("localhost",1004);
        s2 = new Socket("localhost",1004);
        //create input-stream for a particular socket
        messageIn = new DataInputStream(s.getInputStream());
        //create output-stream
        messageOut = new DataOutputStream(s.getOutputStream());
        //sending a message for login
        messageOut.writeUTF(name + " has joined the game.");    
        userLogOut = new DataOutputStream(s1.getOutputStream());
        userNameOut = new DataOutputStream(s2.getOutputStream());
        userNameIn = new DataInputStream(s2.getInputStream());
        //creating a thread for maintaining the list of user name
        MyUserNameReciever userNameReciever = new MyUserNameReciever(userNameOut, modelUserList, name, userNameIn);
        Thread userNameRecieverThread = new Thread(userNameReciever);
        userNameRecieverThread.start();         
        //creating a thread for receiving a messages
        MyMessageReciever messageReciever = new MyMessageReciever(messageIn, modelChatList);
        Thread messageRecieverThread = new Thread(messageReciever);
        messageRecieverThread.start();
    }

    public void initGUI(){
        frame = new JFrame("Jay's Game Title");
        Container panel = (JPanel)frame.getContentPane();
        chatBoxTxt = new JTextField();
        panel.add(chatBoxTxt);
        chatBoxTxt.setBounds(5,605,650,30);
        chatBoxTxt.setVisible(false);
        sendButton = new JButton("Send");
        sendButton.addActionListener(this);
        panel.add(sendButton);
        sendButton.setBounds(260,180,90,30);
        modelChatList = new DefaultListModel();
        listForChat = new JList(modelChatList);
        chatScrollPane = new JScrollPane(listForChat);
        panel.add(chatScrollPane);
        chatScrollPane.setBounds(5,640,650,80);
        modelUserList = new DefaultListModel();
        listForUsers = new JList(modelUserList);
        userListScrollPane = new JScrollPane(listForUsers);
        userListScrollPane.setSize(100,250);
        userListScrollPane.setVisible(false);  

        backpackButton = new JButton(new ImageIcon("images/gui/button_backpack.png"));
        backpackButton.addActionListener(this);
        backpackButton.setBounds(660,686,33,33);
        backpackButton.setBorderPainted(false);backpackButton.setFocusPainted(false);
        backpackButton.setToolTipText("Backpack[B]");
        panel.add(backpackButton);
        characterButton = new JButton(new ImageIcon("images/gui/button_character.png"));
        characterButton.addActionListener(this);
        characterButton.setBounds(695,686,33,33);
        characterButton.setBorderPainted(false);characterButton.setFocusPainted(false);
        characterButton.setToolTipText("Character[C]");
        panel.add(characterButton);
        skillsButton = new JButton(new ImageIcon("images/gui/button_skills.png"));
        skillsButton.addActionListener(this);
        skillsButton.setBounds(730,686,33,33);
        skillsButton.setBorderPainted(false);skillsButton.setFocusPainted(false);
        skillsButton.setToolTipText("Skills[V]");
        panel.add(skillsButton);
        questsButton = new JButton(new ImageIcon("images/gui/button_quests.png"));
        questsButton.addActionListener(this);
        questsButton.setBounds(765,686,33,33);
        questsButton.setBorderPainted(false);questsButton.setFocusPainted(false);
        questsButton.setToolTipText("Quests[N]");
        panel.add(questsButton);
        onlineButton = new JButton(new ImageIcon("images/gui/button_online.png"));
        onlineButton.addActionListener(this);
        onlineButton.setBounds(800,686,33,33);
        onlineButton.setBorderPainted(false);onlineButton.setFocusPainted(false);
        onlineButton.setToolTipText("Online List[U]");
        panel.add(onlineButton);
        helpButton = new JButton(new ImageIcon("images/gui/button_help.png"));
        helpButton.addActionListener(this);
        helpButton.setBounds(835,686,33,33);
        helpButton.setBorderPainted(false);helpButton.setFocusPainted(false);
        helpButton.setToolTipText("Help[I]");
        panel.add(helpButton);
        optionsButton = new JButton(new ImageIcon("images/gui/button_options.png"));
        optionsButton.addActionListener(this);
        optionsButton.setBounds(870,686,33,33);
        optionsButton.setBorderPainted(false);optionsButton.setFocusPainted(false);
        optionsButton.setToolTipText("Options[O]");
        panel.add(optionsButton);
        exitButton = new JButton(new ImageIcon("images/gui/button_exit.png"));
        exitButton.addActionListener(this);
        exitButton.setBounds(905,686,33,33);
        exitButton.setBorderPainted(false);exitButton.setFocusPainted(false);
        exitButton.setToolTipText("Exit[none]");
        panel.add(exitButton);

        skillsFrame = new JInternalFrame("Skills", true, true, false, false);
        skillsFrame.setBounds(600, 10, 400, 500);
        skillsFrame.setVisible(false);
        panel.add(skillsFrame);
        onlineFrame = new JInternalFrame("Users", true, true, false, false);
        onlineFrame.setContentPane(userListScrollPane);
        onlineFrame.setBounds(850, 10, 150, 300);
        onlineFrame.setVisible(false);
        panel.add(onlineFrame);

        panel.setLayout(null);
        panel.setFocusable(true);
        panel.requestFocus();
        panel.addKeyListener(this);//TODO:fix me please, this is not working

        frame.setSize(1024, 768);
        frame.setVisible(true);
        frame.setFocusable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void actionPerformed(ActionEvent e){
        // sending the messages
        if(e.getSource() == sendButton && chatBoxTxt.isVisible() == false){ 
            chatBoxTxt.setVisible(true);
            chatBoxTxt.requestFocus(true);
        } else if (e.getSource() == sendButton && chatBoxTxt.isVisible() == true){
            String str = "";
            str = chatBoxTxt.getText();
            if (str != ""){
                str = name + ": > " + str;
                try{
                    messageOut.writeUTF(str);
                    System.out.println(str);
                    messageOut.flush();
                }catch(IOException ae)
                {System.out.println(ae);}
            }
            //and hide chatBoxTxt
            chatBoxTxt.setText("");
            chatBoxTxt.setVisible(false);
        }
        // show user list
        if (e.getSource() == onlineButton){
            if (userListScrollPane.isVisible()){
                userListScrollPane.setVisible(false);
            } else {
                userListScrollPane.setVisible(true);
            }
            if (onlineFrame.isVisible()){
                onlineFrame.setVisible(false);
            } else {
                onlineFrame.setVisible(true);
            }
        }
        // show skill list
        if (e.getSource() == skillsButton){
            if (skillsFrame.isVisible()){
                skillsFrame.setVisible(false);
            } else {
                skillsFrame.setVisible(true);
            }
        }
        // client logout
        if (e.getSource() == exitButton){
            int exit = JOptionPane.showConfirmDialog(this, "Are you sure you want to exit?");
            if (exit == JOptionPane.YES_OPTION){
                frame.dispose();
                try{
                    //sending the message for logout
                    messageOut.writeUTF(name + " has logged out.");
                    userLogOut.writeUTF(name);
                    userLogOut.flush();
                    Thread.currentThread().sleep(1000);
                    System.exit(1);
                }catch(Exception oe){}
            }
        }
    }

    public void windowClosing(WindowEvent w){
        try{
            userLogOut.writeUTF(name + " has logged out.");
            userLogOut.flush(); 
            Thread.currentThread().sleep(1000);
            System.exit(1);
        }catch(Exception oe){}
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int id = e.getID();
        //open up chatBoxTxt for typing
        if (id == KeyEvent.VK_ENTER && !chatBoxTxt.isVisible()){
            chatBoxTxt.setVisible(true);
            chatBoxTxt.requestFocus(true);
        } //it is open so want to send text
        else if (id == KeyEvent.VK_ENTER && chatBoxTxt.isVisible()) {
            //send message
            String str = "";
            str = chatBoxTxt.getText();
            //make sure there is a message
            if (str.length() > 0){
                chatBoxTxt.setText("");
                str = name + ": > " + str;
                try{
                    messageOut.writeUTF(str);
                    System.out.println(str);
                    messageOut.flush();
                }catch(IOException ae)
                {System.out.println(ae);}
            }
            //and hide chatBoxTxt
            chatBoxTxt.setVisible(false);       
        } //press (Map) key without chatBoxTxt being open
        else if (id == KeyEvent.VK_M && !chatBoxTxt.isVisible()){

        } //press (Character) key without chatBoxTxt being open
        else if (id == KeyEvent.VK_C && !chatBoxTxt.isVisible()){

        } //press (Backpack) key without chatBoxTxt being open
        else if (id == KeyEvent.VK_B && !chatBoxTxt.isVisible()){

        }
    }   

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub  
    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub
    }

    // class is used to maintain the list of user name
    class MyUserNameReciever implements Runnable{
        DataOutputStream userNameOut;
        DefaultListModel modelUserList; 
        DataInputStream userNameIn;
        String name, lname;
        ArrayList alname = new ArrayList(); //stores the list of user names
        ObjectInputStream obj; // read the list of user names
        int i = 0;
        MyUserNameReciever(DataOutputStream userNameOut, DefaultListModel modelUserList, String name, DataInputStream userNameIn){
            this.userNameOut = userNameOut;
            this.modelUserList = modelUserList;
            this.name = name;
            this.userNameIn = userNameIn;
        }
        public void run(){
            try{
                userNameOut.writeUTF(name);  // write the user name in output stream
                while(true){
                    obj = new ObjectInputStream(userNameIn);
                    //read the list of user names
                    alname = (ArrayList)obj.readObject(); 
                    if(i>0)
                        modelUserList.clear(); 
                    Iterator i1 = alname.iterator();
                    System.out.println(alname);
                    while(i1.hasNext()){
                        lname = (String)i1.next();
                        i++;
                        //add the user names in list box
                        modelUserList.addElement(lname);
                    }
                }
            }catch(Exception oe){}
        }
    }

    //class is used to received the messages
    class MyMessageReciever implements Runnable{
        DataInputStream messageIn;
        DefaultListModel modelChatList;
        MyMessageReciever(DataInputStream messageIn, DefaultListModel modelChatList){
            this.messageIn = messageIn;
            this.modelChatList = modelChatList;
        }
        public void run(){
            String incommingMessage = "";
            while(true){
                try{
                    incommingMessage = messageIn.readUTF(); // receive the message from server
                    // add the message in list box
                    modelChatList.addElement(incommingMessage);
                    /* forces chat to bottom of screen :TODO but doesn't allow scrolling up
                chatScrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {  
                    public void adjustmentValueChanged(AdjustmentEvent e) {
                        e.getAdjustable().setValue(e.getAdjustable().getMaximum());
                    }});*/
                }catch(Exception e){}
            }
        }
    }

}

1 Ответ

4 голосов
/ 05 октября 2011

и не имея возможности найти какие-либо учебники в Интернете, я еще больше запутался.

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

мой код для моих кнопок работает просто замечательно

Похоже, вы хотите, чтобы клавиша Enter выполняла ту же обработку, что и нажатие на кнопку. В этом случае простое решение заключается в добавлении ActionListener в текстовое поле вместо использования привязок клавиш. Вы НЕ должны даже рассматривать использование KeyListener для этого.

Конечно, это означает, что вам нужно изменить дизайн своей программы, чтобы использовать разные ActionListener для каждой кнопки. Поэтому вам нужны ActionListeners «Отправить», «Онлайн», «Навыки» и «Выход». Тогда «Отправить» ActionListener можно использовать как кнопкой отправки, так и текстовым полем.

Edit:

например: пользователь может нажать (VK_V) или нажать кнопку навыков, чтобы показать внутреннюю рамку навыков

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

Или, более простое решение - использовать JMenu с элементами меню для вызова ваших действий. Тогда вы можете просто установить ускоритель для пункта меню. Прочтите раздел из руководства по Swing по Как использовать меню для получения дополнительной информации.

Любая дополнительная помощь потребует, чтобы вы опубликовали свой SSCCE,

...