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

2020/4/14

Help with multi-key macro

1
2
3
444Jam444 444Jam444

2020/4/18

#
Sorry, that post might be quite confusing, my mind has kind of melted... let me know if further detail is needed.
Super_Hippo Super_Hippo

2020/4/18

#
Greenfoot API wrote...
getKey() also returns uppercase characters when appropriate.
However, I don’t see this when testing. The following code only returns a key which I just released (!). So pressing a key doesn’t matter. When I for example press and hold shift and then press ‘g’, nothing happens so far. If I then release one of them, that one is printed out, so either ‘shift’ or ‘g’ (not ‘G’). Releasing the other one then prints that one out. If I release both at the time time, one of them is printed.
String key = Greenfoot.getKey();
if (key != null) System.out.println(key);
The method will also never return a * or many other special characters as it is limited to what is given here: https://www.greenfoot.org/files/javadoc/greenfoot/Greenfoot.html.
danpost danpost

2020/4/18

#
444Jam444 wrote...
Issue #1: 'currentIndex' not increasing problem #2: Text not updating (remaining '0' despite the string changing)
public void updateDisplay(){
    Calculate calculate = new Calculate();
    String displayCalculation = calculate.getCurrentCalculation();
    String cursor = ":";
    int index = calculate.getCurrentIndex();
    if (!displayCalculation.equals("")){
        displayCalculation = calculate.insert(displayCalculation, index, cursor);
    }
    else{
        displayCalculation = "0";
    }
    System.out.println(displayCalculation);
    showText(displayCalculation, xCoord4, yCoord4);
}
Line 2 is the cause of both issues. Your output (later in the method) is based on the new unused Calculate object created here. It needs to based on the one currently being used in your world. Please post the Caclulate class insert method for review on another possible issue.
444Jam444 444Jam444

2020/4/20

#
Ok I see my mistake.
danpost wrote...
Please post the Caclulate class insert method for review on another possible issue.
I have thoroughly tested the code on an external site, it works as intended (albeit quite a confusing concept, as the way the user's cursor works different to what one would expect), but I will still post the code for you. You may need to go over the concept sheet I improvised a couple days ago. (Is there a way to upload image files without having to upload them to an external site and linking them here?)
   public static String delete(String aString, int index){
        String placeholderString1 = "";
        String placeholderString2 = "";
        if (index != 0){
            placeholderString1 = aString.substring(0, index-1);
        }
        if (index != aString.length()){
            placeholderString2 = aString.substring(index, aString.length());
        }
        aString = placeholderString1 + placeholderString2;
        return aString;
    }
    
    public static String insert(String aString, int index, String character){
        String placeholderString1 = "";
        String placeholderString2 = "";
        if (index != 0){
            placeholderString1 = aString.substring(0, index);
        }
        if (index != aString.length()){
            placeholderString2 = aString.substring(index, aString.length());
        }
        aString = placeholderString1 + character + placeholderString2;
        return aString;
    }
(The user's cursor is actually between currentIndex and currentIndex-1, the displayed string is the same as the calculation string but with the cursor ':' inserted after currentIndex-1. Again, uploading the image of the hard-copy reference sheet I made a couple days ago would help)
Super_Hippo wrote...
Greenfoot API wrote...
getKey() also returns uppercase characters when appropriate.
However, I don’t see this when testing. The following code only returns a key which I just released (!). So pressing a key doesn’t matter. When I for example press and hold shift and then press ‘g’, nothing happens so far. If I then release one of them, that one is printed out, so either ‘shift’ or ‘g’ (not ‘G’). Releasing the other one then prints that one out. If I release both at the time time, one of them is printed.
String key = Greenfoot.getKey();
if (key != null) System.out.println(key);
The method will also never return a * or many other special characters as it is limited to what is given here: https://www.greenfoot.org/files/javadoc/greenfoot/Greenfoot.html.
Thanks for this explanation. So in that case, I can just do; IF shift held THEN do stuff related to entering 1-4 character strings and returning the related macros ELSE IF shift is not held THEN do basic macros like 0-9, etc ENDIF
danpost wrote...
Line 2 is the cause of both issues. Your output (later in the method) is based on the new unused Calculate object created here. It needs to based on the one currently being used in your world.
Thanks, I will try removing/moving that line, see how that goes.
444Jam444 444Jam444

2020/4/20

#
Also apologies for the delayed replies, I'm working on this during 5 days of the week (I choose which 2 days of the week I have off). I should probably still check and respond to replies, but I honestly forget when I'm on break, sorry about that.
444Jam444 444Jam444

2020/4/20

#
The only problem with the 'insert' method is that it relies on currentIndex (which doesn't seem to increase when calling the getCurrentIndex method in the world, likely fixed by what danpost suggested; removing 'Calculate calculate = new Calculate();' from the updateDisplay() method) Edit: The 2nd part of this message was incorrect. I was still experiencing the same problem with currentIndex after making the change. I have found that the source of the problem is that currentIndex is not increasing in the Calculate class. I do not know the cause of this. For some reason, currentIndex in Calculate starts at 1 (despite being initialised at zero) and permanently stays at 1 while the program is running, and stays at 0 in the world class despite no changes to currentIndex being made. My guess is that this is causing part of the problem:
//Button class
public void buttonPress(){ /**override this in subclasses*/
        if(getWorld() instanceof Calculator){//if world is 'Calculator'
            /**possible source of issue*/
            Calculate calculate = new Calculate();
            calculate.add(button);//call add method in calculate
            if (!button.equals("=")){
                /**possible source of issue*/
                Calculator world = new Calculator();
                world.updateDisplay();
            }
            else{
                Calculator world = new Calculator();
                /**world.showAnswer*/
            }
            /**call method from world that updates the display.
             * the method must call on getcurrentcalculation method of calculate
             * and assign that string to a string called displayCalculation
             * the method must call on getcurrentindex method of calculate
             * and then insert ":" at index+1 of displayCalculation
             * (possibly using calculate's insert method)
             * and showText(displaycalculation) etc
             */
        }
        /**delete*/
        System.out.println(button);
    }

//Calculate class
public void add(String chars){
        /**check if chars == mode alpha store. if so, then 'return;'*/
        if (processingCalculation == false){
            holder = chars;
            //check to see if input is a number
            if (checkIfNumber(holder)){
                currentCalculation = insert(currentCalculation, currentIndex, holder);
            }
            else if (holder.equals("Clear")){
                currentCalculation = "";
                currentIndex = -1; //+1 is added at end of method
                System.out.println("CLEARED");
                System.out.println("_______");
            }
            else if (holder.equals("Delete")){
                if (! currentCalculation.equals("")){
                    currentCalculation = delete(currentCalculation, currentIndex);
                }
                if (currentIndex > 0){
                    currentIndex = currentIndex - 2;
                    //currentIndex - 2 + 1 = intended currentIndex
                    //will not matter if currentIndex results as -1...
                    //...because +1 is added at the end of the method
                }
            }
        }
        /**make sure subclasses of button arent registered!*/
        /**starts at zero each time a button is pressed then increases by 1, to equal 1?*/
        currentIndex = currentIndex + 1;
        System.out.println("a" + currentIndex); //error checking
    }
I will try fixing this and get back with results. Edit 2: I made a big mistake that almost destroyed Greenfoot... caused an infinite loop of error messages in terminal. Lesson learned; if you have numerous amounts of a single actor created by using a loop in the world, do NOT do something like 'MyWorld world = new MyWorld' in the first few lines of that actors code... causes an infinite loop of errors that increases in size exponentially per iteration... (that issue has been fixed now, but I accidentally cleared the terminal without thinking of copy-pasting the output here.) I realise that I should be using getWorld() instead of instantiating a new Calculator, but 'World world = getWorld()' doesn't work (there is no 'updateDisplay' method in World) and 'Calculator world = (Calculator) getWorld()' causes a NullPointerException: java.lang.NullPointerException at greenfoot.core.SetWorldHelper.<init>(SetWorldHelper.java:15) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) at bluej.runtime.ExecServer$3.lambda$run$2(ExecServer.java:859) at bluej.runtime.ExecServer.runOnTargetThread(ExecServer.java:930) at bluej.runtime.ExecServer$3.run(ExecServer.java:857)
444Jam444 444Jam444

2020/4/20

#
in button class:
    public void buttonPress(){ /**override this in subclasses*/
        if(getWorld() instanceof Calculator){//if world is 'Calculator'
            Calculator world = (Calculator) getWorld();
            calculate.add(button);//call add method in calculate
            if (!button.equals("=")){
                world.updateDisplay();
            }
Line 2 is fine. Line 3 is not.
danpost danpost

2020/4/20

#
Seems to me that you are or have been excessively using the new keyword. You should limit yourself to as few new objects as needed. I am placing a large bet that your Calculator world has some unneeded uses of it.
444Jam444 444Jam444

2020/4/20

#
Possibly, but I have cut back on that in Calculator today, so it shouldn't be as much of an issue... some are necessary (as far as I know).
public Calculator()
    {    
        super(420, 600, 1);
        makeNumButtons();
        makeOpButtons();
        makeAdvOpButtons();
        makeActionButtons();
        makeArrowButtons();
        prepare();
        updateDisplay();
    }

public void makeNumButtons(){
        for(int i = 0; i < 15; i++) { /**change 17 to length of array*/
            if(!numButton[i].equals("")){
                Button myButton = new Button(numButton[i]);
                addObject(myButton, xCoord1, yCoord1);
            }
            xCoord1 += buttonSpacingXVal;
            if((i+1)%4 == 0){
                xCoord1 = xCoordStart;
                yCoord1 = (yCoordStart - buttonSpacingYVal) - buttonSpacingYVal * ((i-3)/4);
            }
        }
    }

    public void makeOpButtons(){
        for(int i = 0; i < 16; i++) { /**change 17 to length of array*/
            if(!operationButton[i].equals("")){
                Button myButton = new Button(operationButton[i]);
                addObject(myButton, xCoord2, yCoord2);
            }
            xCoord2 += buttonSpacingXVal;
            if((i+1)%4 == 0){
                xCoord2 = xCoordStart;
                yCoord2 = (yCoordStart - buttonSpacingYVal) - buttonSpacingYVal * ((i-3)/4);
            }
        }
    }
    
    public void makeAdvOpButtons(){ /**change 17 to length of array*/
        for(int i = 0; i < 28; i++) {
            if(!advOperationButton[i].equals("")){
                Button myButton = new Button(advOperationButton[i], advOperationButtonName[i]);
                addObject(myButton, xCoord3, yCoord3);
            }
            xCoord3 += buttonSpacingXVal;
            if((i+1)%4 == 0){
                xCoord3 = xCoordStart;
                yCoord3 = (yCoordStart - buttonSpacingYVal) - buttonSpacingYVal * ((i-3)/4);
            }
        }
        
        //Clear and Delete buttons
        Button clear = new Button("Clear", " AC");
        addObject(clear, xCoordStart + (buttonSpacingXVal * 3), yCoordStart - (buttonSpacingYVal * 8));
        Button delete = new Button("Delete", "Del");
        addObject(delete, xCoordStart + (buttonSpacingXVal * 5 / 2), yCoordStart - (buttonSpacingYVal * 7));
    }
    
    public void makeActionButtons(){
        StoreButton store = new StoreButton();
        ModeButton mode = new ModeButton();
        AlphaButton alpha = new AlphaButton();
        addObject(store, xCoordStart, yCoordStart - (buttonSpacingYVal * 5));
        addObject(mode, xCoordStart, yCoordStart - (buttonSpacingYVal * 8));
        addObject(alpha, xCoordStart + (buttonSpacingXVal/2), yCoordStart - (buttonSpacingYVal * 7));
    }
    
    public void makeArrowButtons(){ /**change 17 to length of array*/
        //make the area that the buttons will occupy
        Arrows arrowCircle = new Arrows();
        addObject(arrowCircle, (getWidth() / 2 + 5), (getHeight() / 2 - 60));
        
        DownArrow down = new DownArrow();
        addObject(down, (getWidth() / 2 + 5), (getHeight() / 2 - 27));
        
        UpArrow up = new UpArrow();
        addObject(up, (getWidth() / 2 + 5), (getHeight() / 2 - 97));
        
        LeftArrow left = new LeftArrow();
        addObject(left, (getWidth() / 2 - 30), (getHeight() / 2 - 62));
        
        RightArrow right = new RightArrow();
        addObject(right, (getWidth() / 2 + 39), (getHeight() / 2 - 62));
    }
    
    public void prepare(){
        CheckKeyPress keypress = new CheckKeyPress();
        addObject(keypress, 0, 0);
    }
Again, is there a way to upload an image to post here from my files? Just want to know in case someone is confused about how the index works, so I can send the reference sheet I made.
danpost danpost

2020/4/20

#
444Jam444 wrote...
Again, is there a way to upload an image to post here from my files? Just want to know in case someone is confused about how the index works, so I can send the reference sheet I made.
You could include the image in your scenario folder and share the project here, being sure to check the Publish source code box. That would also allow for me, and possibly others, to test out what you got, making for easier and more accurate help.
444Jam444 444Jam444

2020/4/21

#
Sure. It's not close to finished though. I have used a library of code sourced from someone else's calculator project (as it was a project requirement to use a library of code) which I have modified. I don't remember the name or link of the project, but it was something along the lines of 'simple calculator', it had a wooden background aesthetic and it could only add/multiply/subtract/divide 2 numbers at a time (I do have it downloaded though). You may see that I have put some of the source code into comments and rewritten it to suit my program better.
444Jam444 444Jam444

2020/4/21

#
https://www.greenfoot.org/scenarios/25669
444Jam444 444Jam444

2020/4/21

#
The reference guide is under a separate folder within the scenario called Guides for Developer(s) (let me know if it's hard to read -- I can edit it in photoshop (change the contrast etc) to make it more readable)
danpost danpost

2020/4/21

#
444Jam444 wrote...
https://www.greenfoot.org/scenarios/25669
In Button class, use the following to access the Calculate object:
Calculate calculate = ((Calculator)getWorld()).myCalculator;
Remove the following line from top of class:
Calculate calculate = new Calculate();
444Jam444 444Jam444

2020/4/21

#
That change threw an error. java.lang.NullPointerException at Button.<init>(Button.java:19) Calculate calculate = ((Calculator)getWorld()).myCalculator; at Calculator.makeNumButtons(Calculator.java:74) Button myButton = new Button(numButton); at Calculator.<init>(Calculator.java:62) (World constructor) makeNumButtons(); I replaced Calculate calculate = new Calculate(); with Calculate calculate = ((Calculator)getWorld()).myCalculator; Was I supposed to replace? Or just delete and use Calculate calculate = ((Calculator)getWorld()).myCalculator; within methods?
There are more replies on the next page.
1
2
3