This site requires JavaScript, please enable it in your browser!
Greenfoot back
Unicus
Unicus wrote ...

2015/6/14

Responsiveness problem with getKey()

Unicus Unicus

2015/6/14

#
Hello, I am having a strange problem which I don't seem to be able to get around. Say I have this:
1
2
3
4
5
6
private String text = "";
 
public void act(){
String input = Greenfoot.getKey();
if(input != null) text += input;
}
This one works. But this...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void act(){
    String input = Greenfoot.getKey();
    if(initialized && !ready){
        if(Greenfoot.mouseClicked(trueButton)){
            addSecondImage();
            ready = true;
        }
    }
    if(ready){
        //if(Greenfoot.isKeyDown("left")){
        if(input != null && input.equals("left")){
            //while(Greenfoot.isKeyDown("left")){}
            userAnswer = true;
            getNextImage();
        }
        //if(Greenfoot.isKeyDown("right")){
        if(input != null && input.equals("right")){
            //while(Greenfoot.isKeyDown("right")){}
            userAnswer = false;
            getNextImage();
        }
    }
}
The problem is that sometimes, when I compile or reset the game/program, nothing happens when I press left or right (after clicking "ready"), unless I pause the game and resume, or I alt-tab to another window, and back. Other times, it works normally. And it works correctly 100% of the time, when I check with Greenfoot.isKeyDown() (commented part of the above code). It's not a question for a solution (since the solution for this is obviously to use the other way, which works, rather I need to know why this happens, so I avoid it happening in another, more complex code, that uses this same method, with the same symptoms.
danpost danpost

2015/6/14

#
I will say this (although I cannot be certain this has anything to do with your issue or not) -- you cannot concurrently use 'getKey' more than once in any act cycle. The operative word here is 'cycle'; therefore it should only be used for one active object instance at a time. So, there can be no more than one active instance of any and all classes you use it in at any time. Therefore, the best place to use it is in your world class (which you only have one active instance of) and it must be saved to a string variable if compared to more than one string (you can compare it directly to a single string by putting the string to compare it to first -- i.e. 'if ("space".equals(Greenfoot.getKey()))' ).
Unicus Unicus

2015/6/14

#
The above act method is used in my world class, and there is no other instance of 'getKey' that is working concurrently in any other actor.
danpost danpost

2015/6/14

#
What do 'addSecondImage' and 'getNextImage' do? what controls do you have for the 'initialized' field? and what codes are used for the declaration, initialization and adding to the world of the 'trueButton' object?
Unicus Unicus

2015/6/14

#
Neither of them contains getKey, and since it sometimes works correctly, and when it doesn't alt-tabbing temporarily fixes this... Here are the codes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void addFirstImage(){
    // Get a random image as first image
    imageIDs[0] = getRandomImage();
    // Add ready button
    trueButton = new ImageActor("big_green_ball2.png");
    addObject(trueButton, getWidth()/2, getHeight()/2+300);
    initialized = true;
}
 
public void addSecondImage(){
    List objects = getObjects(null);
    removeObjects(objects);
     
    imageIDs[1] = getRandomImage();
    //Add buttons
    falseButton = new ImageActor("big_red_ball2.png");
     
    addObject(trueButton, getWidth()/2-150, getHeight()/2+300);
    addObject(falseButton, getWidth()/2+150, getHeight()/2+300);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public int getRandomImage(){
    Random rand = new Random();
    int ID = rand.nextInt(5);
    String imagePath = "SameAsPrevious\\";
    switch(ID) {
        case 0: imagePath += "zero.png";
                break;
        case 1: imagePath += "one.png";
                break;
        case 2: imagePath += "two.png";
                break;
        case 3: imagePath += "three.png";
                break;
        case 4: imagePath += "four.png";
                break;
        case 5: imagePath += "five.png";
                break;
    }
     
    currentImage = new ImageActor(imagePath);
    addObject(currentImage, getWidth()/2, getHeight()/2);
    return ID;
}
The true and false buttons are objects of this:
1
2
3
4
5
6
7
8
9
10
public class ImageActor extends Actor
{   
    public ImageActor(String image){
        this.setImage(image);
    }
     
    public void resize(int width, int height){
        getImage().scale(width, height);
    }
}
Basically, I add an initial image, wait for mouse click on the trueButton, and then add the second image, where the true and false buttons will be working by pressing left/right keys.
danpost danpost

2015/6/14

#
Still, the 'getNextImage' method is not given. It could be in it or possibly in your world constructor (or some code it executes).
Unicus Unicus

2015/6/14

#
I have literally taken each class, and searched for getKey() It only shows up in the two places that it should. Anyway, here is the getNextImage method.
1
2
3
4
5
6
public void getNextImage(){
    currentImage.changeOut();
    if(checkIDs() == userAnswer) score += 5;
    else score -= 10;
    updateIDs(getRandomImage());
}
All these methods are in my current world.
Unicus Unicus

2015/6/14

#
The other place where getKey is used is here in this actor (not world, in this case). This is a text box, which if clicked upon, will delete the initial text, and let the user add input. As with the previous case, after clicking the text box to enter the text, nothing is entered, until I alt-tab and come back, or if I pause-resume. In this case, I have also noticed that sometimes, input will be equal to "right", even though I never press that button.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import greenfoot.*;
import java.awt.Color;
import java.awt.Font;
 
public class TextBoxField extends Text
{
    private boolean boxActive = false;
    private boolean cursorActive = false;
    private boolean writeEnable = false;
     
    private int textBoxActive;
     
    private int textFieldNumber;
    private int textFontSize;
    private int cursorPosition = 0;
     
    private long cursorTime;
     
    private String text = "";
    private String temp = "";
     
    private Color invisible = Color.white;
    private Color textColor = Color.white;
     
    public void act()
    {
        if(Greenfoot.mouseClicked(this) && getText() == "Introduza aqui o seu nome" ){
            textBoxActive = 1;
            textBoxActive = textFieldNumber;
            cursorTime = System.currentTimeMillis();
            setText("");
            writeEnable = true;
            cursorActive = true;
        }else if(Greenfoot.mouseClicked(this)){
            textBoxActive = textFieldNumber;
        }
         
        if(boxActive){
            if(textBoxActive != textFieldNumber){
                boxActive = false;
                cursorActive = false;
                displayText();
                return;
            }
             
            if((System.currentTimeMillis() - cursorTime > 500)){
                cursorTime = System.currentTimeMillis();
                cursorActive = !cursorActive;
            }
             
            String input = Greenfoot.getKey();
             
            if(writeEnable){
                if(input == "backspace" && text.length() != 0 && cursorPosition != 0){
                    if(cursorPosition == text.length()){
                        text = text.substring(0,text.length() - 1);
                    }else{
                        temp = text.substring(0,cursorPosition - 1);
                        temp += text.substring(cursorPosition,text.length()-1);
                        text = temp;
                        temp = "";
                    }
                    cursorPosition--;
                }else if(input == "enter"){
                    setTextBoxActive();
                }else if(input == "space"){
                    if(cursorPosition == text.length()){
                        text += " ";
                    }else{
                        temp = text.substring(0,cursorPosition);
                        temp += " ";
                        temp += text.substring(cursorPosition,text.length()-1);
                        text = temp;
                        temp = "";
                    }
                    cursorPosition++;
                }else if(input == "left"){
                    if(cursorPosition > 0){
                        cursorPosition--;
                        cursorTime = System.currentTimeMillis();
                        cursorActive = true;
                    }
                }else if(input == "right"){
                    cursorPosition++;
                    cursorTime = System.currentTimeMillis();
                    cursorActive = true;
                }else if(input != null && input.length() == 1){
                    if(cursorPosition == text.length()){
                        text += input;
                    }else{
                        temp = text.substring(0,cursorPosition);
                        temp += input;
                        temp += text.substring(cursorPosition, text.length() - 1);
                        text = temp;
                        temp = "";
                    }
                    cursorPosition++;
                }
            }
            displayText();
        }else{
            if(textBoxActive == textFieldNumber){
                boxActive = true;
            }
        }
    }
     
    public TextBoxField(){
        this(310,40,Color.white,Color.black,"");
    }
     
    public TextBoxField(int width, int height, String text){
        this(width, height, true, Color.white, Color.black, text);
    }
     
    public TextBoxField(int width, int height, Color invisible, Color textColor){
        this(width, height, true, invisible, textColor, "");
    }
     
    public TextBoxField(int width, int height, Color invisible, Color textColor, String text){
        this(width, height, true, invisible, textColor, text);
    }
     
    public TextBoxField(int width, int height, boolean writeEnable, Color invisible, Color textColor, String text){
        this.invisible = invisible;
        this.textColor = textColor;
        this.text = text;
        this.writeEnable = writeEnable;
        cursorPosition = text.length();
        getImage().clear();
        getImage().scale(width, height);
        textFontSize = height - 10;
        resetImage();
        displayText();
    }
     
    public void addedToWorld(World world){
        textFieldNumber = getWorld().getObjects(TextBoxField.class).size();
    }
     
    public void displayText(){
        GreenfootImage textImage = new GreenfootImage(text, textFontSize, textColor, new Color(0,0,0,0));
        GreenfootImage textBeforeCursor = new GreenfootImage(text.substring(0, cursorPosition), textFontSize, new Color(0,0,0,0), new Color(0,0,0,0));
        resetImage();
        getImage().drawImage(textImage, (textImage.getWidth() > getImage().getWidth() - 10 ? -(textImage.getWidth() - getImage().getWidth()) - 10 : 5), (getImage().getHeight() / 2 - textImage.getHeight() / 2));
        getImage().setColor(textColor);
         
        if(cursorActive){
            getImage().fillRect((textBeforeCursor.getWidth() > getImage().getWidth() - 10 ? getImage().getWidth() - 8 : textBeforeCursor.getWidth() + 4), getImage().getHeight() / 2 - textFontSize / 2, 2, textFontSize);
        }
    }
     
    public void resetImage(){
        getImage().clear();
    }
     
    public void setTextBoxActive(int textBoxActive){
        this.textBoxActive = textBoxActive;
    }
     
    public void setTextBoxActive(){
        textBoxActive++;
         
        if(textBoxActive > getWorld().getObjects(TextBoxField.class).size()){
            textBoxActive = 1;
        }
    }
     
    public boolean isEnabled(){
        return writeEnable;
    }
     
    public void setWriteEnable(boolean writeEnable){
        this.writeEnable = writeEnable;
    }
     
    public String getText(){
        return text;
    }
     
    public void setText(String text){
        this.text = text;
        cursorPosition = text.length();
    }
     
    public Color getBackGroundColor(){
        return invisible;
    }
     
    public void setBackGroundColor(){
        this.invisible = invisible;
    }
     
    public Color getTextColor(){
        return textColor;
    }
     
    public void setTextColor(Color textColor){
        this.textColor = textColor;
    }
}
danpost danpost

2015/6/14

#
(1) what is the most number of TextBoxField objects that are in your world at any time? (2) is 'boxActive' true for any TextBoxField object while 'ready' in your world class is true?
Unicus Unicus

2015/6/14

#
This is the world class where TextBox class is called:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import greenfoot.*;
import java.awt.Font;
import java.awt.Color;
 
public class NameInput extends World
{
    Button continueButton = new Button("continueButton.png","continueButtonClicked.png");
    TextBox textBox = new TextBox();
    displayInfo bigText = new displayInfo("", 700,155,30);
    displayInfo inform = new displayInfo("*Campo obrigatório");
    TextBoxField textBoxField = new TextBoxField(310,40,false, Color.white, Color.white, "Introduza aqui o seu nome");
    String text;
    String name;
     
    public NameInput()
    {   
        super(1015,766,1);
        addObject(continueButton, getWidth() - 250, getHeight()/2 + 250);
        addObject(bigText,getWidth()/2,getHeight()/2 - 100);
        addObject(textBox, getWidth() / 2, (getHeight() / 2) + 70);
        addObject(textBoxField, getWidth() / 2, (getHeight() / 2) + 70);
        text =  "         \nAntes de iniciar este teste, introduza o seu nome\n";
        text += "de modo a que todos os dados estatísticos se encontrem\n";
        text += "                             devidamente identificados!\n";
        bigText.setText(text);
    }
     
    public void act(){
        if(Greenfoot.mouseClicked(continueButton)){
            String name = textBoxField.getText();
            if(name.length() > 15){
                 
            }
            else {
                Greenfoot.setWorld(new GameSelection(name));//MemoryGame(name));
                manageUsers.addUser(name); //Caso nao existir ja o utilizador, cria um novo
            }
        }
    }
     
    public String getText(){
        return text;
    }
     
    public String getName(){
        return textBoxField.getText();
    }
}
danpost danpost

2015/6/14

#
I would presume that this NameInput world works okay and that a GameSelection world is activated properly when the continue button is clicked. Correct? And also, I would presume that the GameSelection world is not the world you are having the 'getKey' issue in; but, in a MemoryGame world. Correct? (maybe you should show its code since that is where you are having the issue)
Unicus Unicus

2015/6/14

#
Yes, the GameSelection world is activated properly. The getKey issue happens in NameInput world.
danpost danpost

2015/6/14

#
Where are you setting the textBoxField object active?
Unicus Unicus

2015/6/14

#
Not sure which variable you mean. Is it this? 'writeEnable' I set it active right at the beginning of the act method, inside the if condition, which checks if I mouse clicked TextBoxField.
danpost danpost

2015/6/14

#
From what I can tell, your TextBoxField class appears to accept keystrokes normally. However, I do not have the Text class to test it with; nor, the scenario as a whole. In other words, I tested the class to the limits of what was given and the only thing I found as a potential issue is that the 'enter' key does not take focus off the field (I am not saying that it should do more than it does; just that it does not behave in the manner that I would have expected).
You need to login to post a reply.