Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Keyboard question
Index -> Programming, Java -> Java Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
Flikerator




PostPosted: Thu Aug 09, 2007 7:59 pm   Post subject: Keyboard question

I just started learning Java (I'm not asking for a lecture on why I shouldn't use Java either), and I've been stuck on getting input from the keyboard to work for a few hours. Its probably not that difficult, but I can't get it to work at all. I've looked up a ton of examples. They each do it differently as well. In terms of Turing I want something that works relative to this;

Turing:
var x, y : int := 50
var chars : array char of boolean
loop
    Input.Flush
    Input.KeyDown (chars)
    if chars ('w') then
        y += 1
    end if
    if chars ('s') then
        y -= 1
    end if
    if chars ('d') then
        x += 1
    end if
    if chars ('a') then
        x -= 1
    end if
    Draw.FillBox (x, y, x + 50, y + 50, red)
    Time.DelaySinceLast (10)
    cls
end loop


And what I have in Java (The latest most cutdown version);

Java:
import java.lang.Math;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.Color;
import java.util.Random;

public class test extends JFrame{       
    public static void main(String[] args) {
        new mainFrame();
    }
}

class mainFrame extends JFrame {
        Graphics g;
        Random r = new Random();
        private int x=50,y=50;
               
        public mainFrame() {
                setTitle("The Main Frame");
                setVisible(true);
                setSize(800,600);
                setResizable(false);
                setLocationRelativeTo(null);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
       
    public void keyDown(Event e, int key) {
        if (key == Event.LEFT) {
            x=x-1;
        }
                if (key == Event.RIGHT) {
                        x=x+1;
                }
                if (key == Event.UP) {
                        y=y-1;
                }
                if (key == Event.DOWN) {
                        y=y+1;
                }
    }
       
        public void paint(Graphics g) {
                g.setColor(new Color( r.nextInt(256), r.nextInt(256), r.nextInt(256)));
                keyDown();
                g.fillRect(x,y,x+50,y+50);
                repaint();
        }
}


Don't worry too much about the imports. I know some of them aren't being used right now. The reason I have java.awt.* is because if I don't, then it claims it can't find the 'Event' methods, even when I had java.awp.Event.*.

I'm still learning how Java works, and I have the basic idea but not completely, obviously. Having the program continue without loops is still bugging me (The Woes of Turing).

With this good I'm basically grasping for straws. Experimenting until I find something that works, gain some understanding on how it all comes together as I go along.

Any assistance?
Sponsor
Sponsor
Sponsor
sponsor
Flikerator




PostPosted: Fri Aug 10, 2007 2:11 am   Post subject: Re: Keyboard question

I feel I'm so close, but I keep getting this error: events.Test is not abstract and does not override abstract method keyReleased(java.awt.event.KeyEvent) in java.awt.event.KeyListener



Java:
package events;

import java.lang.Math;
import java.awt.Graphics;
//import javax.swing.JFrame;
import java.awt.*;
//import java.awt.event.*;
//import javax.swing.*;
import java.awt.Color;
import java.util.Random;

//import java.awt.event.KeyListener;
//import java.awt.event.KeyEvent;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JFrame
        implements KeyListener,
        ActionListener {
    public static void main(String[] args) {
        new mainFrame();
    }
}

class mainFrame extends JFrame {
        Graphics g;
        Random r = new Random();
        private int x=50,y=50;
        char opt;
               
        public mainFrame() {
                setTitle("The Main Frame");
                setVisible(true);
                setSize(800,600);
                setResizable(false);
                setLocationRelativeTo(null);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
               
                public boolean keyDown(Event e, int key) {
                opt = (char) key;
                if (opt == 'a') {
                        x=x-1;
                }
                if (opt == 'd') {
                        x=x+1;
                }
                if (opt == 'w') {
                        y=y-1;
                }
                if (opt == 's') {
                        y=y+1;
                }
                return true;
    }
       
        public void paint(Graphics g) {
                g.setColor(new Color( r.nextInt(256), r.nextInt(256), r.nextInt(256)));
                g.fillRect(x,y,x+50,y+50);
                repaint();
        }
}



Aziz




PostPosted: Fri Aug 10, 2007 9:19 am   Post subject: RE:Keyboard question

There are a few things:

1) Each class should be in a separate file, ClassName.java

2) test class should not extend JFrame. It's not actually a JFrame, is it? All it does is create an instance of mainFrame().

3) Classes should be named in FirstLetterCase, notLikeThis.

4) test should not implement KeyListener. Let me explain about EventListeners

all Swing components can add certain EventListeners. When something happens on that component (such as a key being typed, or a button being pressed), the internal mechanisms "fire" an Event. If that component has an appropriate listener added to it, it will call a specific method of that selected listener. All listeners inherit from EventListener, and each (almost) Listener has an associated Event.

For example,

A button being clicked. When you make a button, you do like so:

code:
JButton button = new JButton("Click me");
frame.add(button);


When you click that button, it's internal code takes care of certain things, including drawing the clicking animation and "firing" and event. In this case, the button's click would fire an ActionEvent. But our code doesn't add an ActionListener to the button. Let's do that.

An ActionListener is another class. Or rather, it is an interface. It has a single method:

code:
public void actionPerformed(ActionEvent e)


We can't instantiate an object of an interface. We have to create a class that implements ActionListener. We can have our main class do this:

code:
public class MainFrame extends JFrame, implements ActionListener
{
    public MainFrame()
    {
        // we'll set up components here, later
    }
   
    // Overrides void actionPerformed(ActionEvent) in ActionListener
    public void actionPerformed(ActionEvent e)
    {
        // do something
    }
}


Now, in the constructor, when we set up components, we will make a JButton, and use the JButton's addActionListener(ActionListener) method to add the current MainClass object ("this") as an ActionListener (because MainClass implements ActionListener, it "is an" ActionListener, and you could pass it to any method that calls for an ActionListener). When an ActionEvent is fire by a JButton (like clicking it), it will call the associated ActionListener's actionPerformed() method, and pass an ActionEvent object (which can tell you certain information, such as the source of the event). Watch:

code:
JButton button = new JButton("Click me");
button.addActionListener(this); // <----
frame.add(button);


Test it out, when the button is clicked, actionPerformed() in MainClass is run. Of course, you need to import JFrame, ActionEvent, ActionListener, and JButton.

However, this is often hackish, especially if you have many buttons, etc. You'll have to use the "getSource" or "getActionText" to figure out which button fired the event, and act on there. That's how the Swing Tutorial does it, and I don't like it (neither do others around here...) (I'm writing this all off the top of my head, so forgive me if I get any method names wrong or wrong)

What we should do is create a separate ActionListener object for each button. Which would mean we'd have to create a separate class. But then, it'd be a lot of work to make those classes access the features of MainFrame, and we don't want that. Hold on. We can use Java's inner classes:

code:
    private class Button1ActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            // do something for button1
        }
    }
   
    private class Button2ActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            // do something for button2
        }
    }


Then we can make an object of each:

code:
Button1ActionListener b1AListener = new Button1ActionListener();
button1.addActionListener(b1AListener);
// similar for button2


When we click button1, the button fire an ActionEvent, recognizes that it has an associated ActionListener, and calls that ActionListener's actionPerformed. This ActionListener happens to be b1AListener, an object of Button1ActionListener. So the actionPerformed() method of Button1ActionListener gets called.

That's a lot of clutter at class-level. We don't need those class outside of the place where we create them. Of course, we can strip the "private" modifier of the classes, and declare them inside the methods, but it's not much better.

We'll never need the classes more than once, will we? Java offers another structure to make our life easier: anonymous inner classes. We don't even have to give the class a name! We'll go back to our one-button example. Watch:

code:
ActionListener listener = new ActionListener()
    {
        public void actionPerformed(ActionEvent e)
        {
            // do something
        }
    }

JButton button = new JButton("Click me!");
button.addActionListener(listener);


(See bottom of post for links).

In this way of doing this, we've defined the class as soon as we've instantiated it. When you compile, you'll see a file called "MainClass$1.class". This is the class definition for that class. A note, these classes can only affect local variables that are declared "final". The best way to deal with events that do something is to call a method to handle the event, such as button1ActionPerformed.

We can make it better. We only need to use "listener" once. We don't need to store it in a variable. We can do it write in the argument list for addActionListener:

code:
JButton button = new JButton("Click me!");
button.addActionListener(new ActionListener()
    {
        public void actionPerformed(ActionEvent e)
        {
            // do something
        }
    });


The same can be said for KeyListeners.

You'll have to add a KeyListener to MainClass. So:

code:
public MainClass()
{
    addKeyListener(new KeyListener()
    {
        public void keyPressed(KeyEvent e)
        {
            // deal with key pressed
        }
        public void keyReleased(KeyEvent e)
        {
            // deal with key releases
        }
        public void keyTyped(KeyEvent e)
        {
            // deal with key type (pressed and released)
        }
    }
}


But we only need the one method, probably keyPressed. However, we have to define all 3 methods, because KeyListener is an interface, and by default all methods are abstract: they have no implementation, and thus calling them (which might happen, the compiler doesn't know) would not work. Luckily, we can use the KeyAdapter class. It is simply a class that implements KeyListener (so it is-a KeyListener and can go where a KeyListener can). All it's methods are defined with empty implementation (there's no code in the method body, but it does exist).

So we can override only the methods we want:

Anonymous classes can extend classes as well, not just interfaces. So we can do:

code:
public MainClass()
{
    addKeyListener(new KeyAdapter()
    {
        public void keyPressed(KeyEvent e)
        {
            // deal with key pressed
        }
    }
}


Here's a complete working example:

MainFrame.java
code:
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class MainFrame extends JFrame
{
    private JLabel label;
   
    public MainFrame()
    {
        label = new JLabel("No key pressed");
        add(label);
       
        addKeyListener(new KeyAdapter()
        {
            public void keyPressed(KeyEvent e)
            {
                aKeyWasPressed(e);
            }
        });
       
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setSize(300, 300);
        setVisible(true);
    }
   
    private void aKeyWasPressed(KeyEvent e)
    {
        String keyName = KeyEvent.getKeyText(e.getKeyCode());
       
        int keycode = e.getKeyCode();
       
        String direction = "holding position.";
        if (keycode == KeyEvent.VK_UP)
            direction = "going up!";
        else if (keycode == KeyEvent.VK_DOWN)
            direction = "falling down!";
       
        label.setText("Key pressed: " + keyName + "     "
            + "Status: " + direction);
    }
   
    public static void main(String[] args)
    {
        new MainFrame();
    }
}


Refer to these links for for help

Swing Tutorial - http://java.sun.com/docs/books/tutorial/uiswing/index.html
Writing Event Listeners - http://java.sun.com/docs/books/tutorial/uiswing/events/index.html

Swing Basics tutorial by rizzix - http://compsci.ca/v3/viewtopic.php?t=1975
Use Swing, for crying outloud, tip by wtd http://compsci.ca/v3/viewtopic.php?t=14235

Now, I just got paid for writing all that (Help desk jobs can be pretty liesurely), and I've got better things to do (like read Wookiepedia!), so I suggest you read all the tuts and what not, and experiment. And just post if you have more issues. Don't forget the Jave API Documentation is the an amazing resource... http://java.sun.com/javase/6/docs/api/
Flikerator




PostPosted: Wed Aug 15, 2007 2:30 am   Post subject: Re: Keyboard question

Thanks for all the help, and especially the links. I've been reading through the tutorials. It makes a lot more sense actually reading how Java works instead of downloading an IDE and just messing around. Who could have guessed =) Thanks again.
Nick




PostPosted: Wed Aug 15, 2007 5:06 am   Post subject: Re: RE:Keyboard question

Aziz @ Fri Aug 10, 2007 9:19 am wrote:
Now, I just got paid for writing all that (Help desk jobs can be pretty liesurely)


dude could ya hook me up with a turing help desk job... i have absoultly nothing to do with my time and although im no expert in turing i still know A LOT!... well mroe than the average programmer

i read some problems ppl have in turing and although most are already answered (becuase im new to this site) i knew excatly the problem and how to fix...

so could you get back to me on this... please?
Aziz




PostPosted: Wed Aug 15, 2007 7:52 am   Post subject: RE:Keyboard question

Hehe. I don't work for a Turing helpdesk (he was asking a Java question, anyways Razz). My summer co-op job placement for school is working at a help desk for a company (well, a Municipality).
Nick




PostPosted: Wed Aug 15, 2007 8:17 am   Post subject: RE:Keyboard question

lol awwww i thought u worked for compsci and they paid u to help ppl Sad cause i can do that and to be paid for it is just a bonus Razz
Aziz




PostPosted: Wed Aug 15, 2007 8:26 am   Post subject: RE:Keyboard question

Heh . . . Dan wouldn't pay anyone to answer questions on this site. There's enough people willing to do it for free (wtd, rizzix...). Though, they do get to expel radiation in the form of [corrupted] moral wisdom while doing so.
Sponsor
Sponsor
Sponsor
sponsor
Nick




PostPosted: Wed Aug 15, 2007 8:27 am   Post subject: RE:Keyboard question

lmao well in a way u do get paid... bits and enough bits and i can get that web hosting, c'mon c'mon c'mon!!!
Aziz




PostPosted: Wed Aug 15, 2007 8:31 am   Post subject: RE:Keyboard question

I wish. It'd probably more cost-effective to just buy hosting. It's not that expensive, is it? I've been here for nearly three years... and I've only got 720 bits! But, I would visit in laps Razz
Nick




PostPosted: Wed Aug 15, 2007 8:34 am   Post subject: RE:Keyboard question

lmao yea and for contests most top prizes are only around 200 bits like how anyone ever supposed to save up with that? :S
Display posts from previous:   
   Index -> Programming, Java -> Java Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 11 Posts ]
Jump to:   


Style:  
Search: