0

First, I know that the way I'm trying to read the input is really bad, but I've tried to use Keylistener, and it doesn't work no matter what I try. I don't know what I'm doing wrong, so this is what I'm trying at the moment. I'm trying to call a thread in Controller.java from PreControls.java. If you could help me implement a working keylistener, it would me much appreciated, but I think fixing this thread problem will work too. I have tried debugging it, and the thread doesn't seem to start.

Code in PreControls.java:

Controller C = new Controller();
C.start();
System.out.print("Thread Should be started ");

Code in Controller.java:

package Game;

public class Controller extends Thread {
    public void MyShipController(){
        System.out.print("Thread Is started ");
        String CharIn = "";
        while(SpaceInvaders.GameOn = true){
            CharIn = PreControls.ReadKeyPressed.getText();
            if(CharIn.equalsIgnoreCase("a")){
                SpaceInvaders.MyPos[0]--;
                System.out.print("Move Left ");
            }else if(CharIn.equalsIgnoreCase("d")){
                SpaceInvaders.MyPos[0]++;
                System.out.print("Move Right");
            }else if(CharIn.equalsIgnoreCase(" ")){
                //Fire Bullet   
            }
        PreControls.ReadKeyPressed.setText("");
        SpaceInvaders.MyShip.setLocation(SpaceInvaders.MyPos[0], SpaceInvaders.MyPos[1]);
        jp1.repaint();
        }
    }
}

Sorry for not providing an SSCCEE. I'd need to send my whole project, and that defeats the point of doing a project.

ReadKeyPressed is the JTextArea that I'm having the letters inputted into. jp1 is the JFrame

I'm working in the Eclipse IDE.

EDIT: forgot to add: After I start the applet, the Console reads "Thread Should be started" only, so it is a problem with the how I made the thread, or how I'm trying to create it.

Edit 2: My End goal is to detect when a (or left arrow) is pressed and move MyShip (a JLabel) to the left by 1 position and more it to the right by 1 position if d (or right arrow) is pressed.

Alright, I've accepted Williams answer as it made my thread run. And as suggested, I'm going to look into key bindings to detect when the keys are pressed. Thanks for all the help.

Shivam Amin
  • 75
  • 1
  • 1
  • 7
  • 2
    You haven't overriden the `run()` method. You've only added an unrelated `MyShipController()` method. – Sotirios Delimanolis Jan 11 '14 at 20:00
  • 1
    No, you're not clear on the concept of [sscce](http://sscce.org), or now here for this site, [MCVE](http://stackoverflow.com/help/mcve). We don't want to see your whole code or snippets of code. Instead we want a **completely new program** that is small, that extracts your problem, that runs, and that demonstrates your problem. Please re-read the link. – Hovercraft Full Of Eels Jan 11 '14 at 20:05
  • 3
    Try extending Runnable rather than thread and implement the single run() method. – takendarkk Jan 11 '14 at 20:06
  • Also, why are you using a KeyListener at all? This question smells of an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Rather than tell us the code problem you're having, better to tell us the overall goal you're trying to achieve. There's likely a better way. – Hovercraft Full Of Eels Jan 11 '14 at 20:06
  • 2
    It looks like you should be using KeyBinding, and a Swing Timer instead. – Hovercraft Full Of Eels Jan 11 '14 at 20:07
  • @csmckelvey: that should read, "Try ***implementing*** Runnable rather than extending Thread". Yes, I'm being overly picky, but so is the Java compiler. – Hovercraft Full Of Eels Jan 11 '14 at 20:12
  • @HovercraftFullOfEels I've edited my End goal to the into the original question. – Shivam Amin Jan 11 '14 at 20:27
  • You got me, thanks for the correction – takendarkk Jan 11 '14 at 20:56
  • _I'd need to send my whole project_ if you think so, you missed the point of a SSCCE (or MCVE, as it is named nowadays). Also, please learn java naming conventions and stick to them. – kleopatra Jan 12 '14 at 10:12

2 Answers2

3

This = is an assinment operator.

while(SpaceInvaders.GameOn = true)

I think you wanted this ==

while(SpaceInvaders.GameOn == true)

Or better yet, and much cleaner, just

while(SpaceInvaders.GameOn)

Also, you should use key bindings instead of KeyListener, which my give you focus problems. See this answer for an example of using key bindings. Also see the tutorial

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Didn't notice that, thanks. But the thread still doesn't start. And the console doesn't output "Thread Is started " which doesn't depend on the while statement. But thanks for catching the mistake in the while statement. – Shivam Amin Jan 11 '14 at 20:07
  • @ShivamAmin the first comment in your question answers your question. My reply gives more details as to **why** this is. Please read both. This answer corrects a logic error within `MyShipController`, but the code within `MyShipController` is still never executed. – William Morrison Jan 11 '14 at 20:09
  • @peeskillet I'm reading your suggestion now, hopefully it will help me understand how to add key bindings into my program. – Shivam Amin Jan 11 '14 at 20:29
1

The code you've written in method MyShipController should be placed inside the run method of your thread. The run method is what the thread actually executes within.

As you've written it now, calling start on your Controller class will start your thread, and that thread will end immediately as its run method is empty.

public class Controller extends Thread {

@Override
public void run()
//public void MyShipController(){
    System.out.print("Thread Is started ");
    String CharIn = "";
    while(SpaceInvaders.GameOn = true){
        CharIn = PreControls.ReadKeyPressed.getText();
        if(CharIn.equalsIgnoreCase("a")){
            SpaceInvaders.MyPos[0]--;
                System.out.print("Move Left ");
            }else if(CharIn.equalsIgnoreCase("d")){
                SpaceInvaders.MyPos[0]++;
                System.out.print("Move Right");
            }else if(CharIn.equalsIgnoreCase(" ")){
                //Fire Bullet   
            }
    PreControls.ReadKeyPressed.setText("");
    SpaceInvaders.MyShip.setLocation(SpaceInvaders.MyPos[0], SpaceInvaders.MyPos[1]);
    jp1.repaint();
    }
    }
}

However, I suggest your controller class extend Runnable rather than Thread.

William Morrison
  • 10,953
  • 2
  • 31
  • 48
  • 1
    Calling Swing commands (except for repaint) from within a background thread == dangerous code. – Hovercraft Full Of Eels Jan 11 '14 at 20:10
  • Ok, that fixed the problem of the thread not starting, but I've run into another problem. When I enter "a" into the JTextArea, I get a message saying "Your computer has run out of memory." Then my computer lags, and Eclipse closes. The program freezes too.Will adding Thread.sleep(500); or something fix this? – Shivam Amin Jan 11 '14 at 20:10
  • That's because your thread is continuously pooling the textfield relentlessly. GUIs are event driven environments, that is, you attack some kind of listener or call back to the component your interested and it tells you when something happens. This is known as the observer pattern... – MadProgrammer Jan 11 '14 at 20:12
  • @MadProgrammer Ok, so should I find another way to make my image move around the applet? Or is there a way I can get this to work too? – Shivam Amin Jan 11 '14 at 20:14
  • 2
    I would investigate [Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) and understand [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) - for [example](http://stackoverflow.com/questions/19374866/yet-another-keylistener-keybinding-issue/19375052#19375052) – MadProgrammer Jan 11 '14 at 20:33