Button Functionality (over, pressed and down)

I’m creating a simple button class, with Slick2D library.
However, I have a problem, on how to create a buttonReleased function.
So problem is, I click the button, and it already executes, with out releasing a mouse click.
What I want to achieve, is, I click the button, but execute only if a mouse click is released inside a button area.


    public boolean isActionPerformed(Input input, int mx, int my) throws SlickException {
        if (buttonContains(mx, my)) {
            if (buttonPressed(input)) {
                return true;
            }
            if (buttonDown(input)) {
            }
        }
        return false;
    }
    
    public boolean buttonContains(int mx, int my) throws SlickException {
        if ((mx > minX && mx < maxX) && (my > minY && my < maxY)) {
            buttonState = ButtonState.Over;
            return true;
        }
        buttonState = ButtonState.Normal;
        return false;
    }
    
    public boolean buttonPressed(Input input) throws SlickException {
        if (input.isMousePressed(Input.MOUSE_LEFT_BUTTON)) {
            return true;
        }
        return false;
    }

    public boolean buttonDown(Input input) throws SlickException {
        if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)) {
            buttonState = ButtonState.Down;
            return true;
        }
        return false;
    }

And? Whats the problem? No one is going to write your code for you. And if they do, thats not right because you aren’t learning.

I don’t need code, I need help, on how to create it… like pseudo code or explain how it works?

Well then, think about it logically. You have all the methods there to make it happen. You need to check if the mouse is pressed. Then check if the mouse press is within the bounds of a button. The, check if the mouse is still pressed, and when the user releases the mouse, perform your code.

Well, there is no isMouseReleased method inside Input class…

And? Seriously, just think about it. I know exactly how to do it with just those methods. If the mouse isn’t pressed, its released. How can you check if the mouse is not pressed using your code? You have a boolean method called buttonDown. How can you use that to check if the button is up?

    boolean buttonDown;
    public boolean isActionPerformed(Input input, int mx, int my) throws SlickException {
        if (buttonContains(mx, my)) {
            if (buttonPressed(input)) {
                buttonDown = true;
            }
            if (buttonDown(input)) {
                buttonDown = false;
            }
        }
        return false;
    }

And… ?

No. Check if !buttonDown. That’s how you know its released. You’re just checking to see if the button was pressed, which doesn’t allow you to check if it was down, and you’re also just checking if its down.


if(buttonContains(mx, my){
if(buttonDown(input){
if(!buttonDown(input){
//perform logic
buttonDown = false;
}
buttonDown = true;
}
}

Alright, but this is executing multiple times when mouse is down, what about mouse pressed?
I can’t figure out where to place, since both pressed & down methods have the same action… In which case, pressed does only 1 click, and down does like 5-6 clicks?? That’s what confuses me…

Right, that’s always been a pain in the ass. You’ll need to do something like this:


public boolean keyDown(int keycode) {
		if ((keycode == Keys.E) && Level.editMode == false) Level.editMode = true;
		else if((keycode == Keys.E) && Level.editMode) Level.editMode = false;
		return false;
	}

(This is taken from one of my other games)
What I’m basically showing you here is a skeleton of how to handle keys that are pressed. I check if the button is down, and then set a boolean to true. Then, I check if the key is down again, and if the boolean is true. If so, perform the logic. This should help you get started, just use your buttonDown boolean.

Why dont you just make that:


if (keycode == Keys.E) Level.editMode = !Level.editMode;

?

@OP Try this:


boolean buttonDown;
    public boolean isActionPerformed(Input input, int mx, int my) throws SlickException {
        if (buttonContains(mx, my)) {
            if (buttonPressed(input)) {
                buttonDown = true;
            }
            else if (buttonReleased(input) && buttonDown) {
                 buttonDown = false;
                 runActionOrDoWhateverHere();
            }
        }
        return false;
    }

Well, you need to check if the editMode is true or false. The only reason the logic isn’t fired off every frame when I’m holding down the edit key is because I check for the boolean. Without it, it would continually go off.

I dont understand? my modification does the same thing yours does, it just uses a boolean negation to toggle instead, save a cycle of cmpne :slight_smile:

@Dxu1994 He doesn’t have a keyReleased method. Change that to !buttonDown. Besides, that makes no sense, no offense. If the key is released, and the key is down, well that’s contradictory.
Edit: To your last post, no that’s not true. You are only checking if the key is down, which can be true or false multiple times a frame. Then you set the boolean to be the opposite, which is basically going to spam toggle it multiple times a frame.

This is a function that I created few days ago, what it does is, if is pressed once, execute… but after that press, if a button is not released, and is last for 1s, then execute down method, which spams… Tbh, I don’t like way of doing this… So that’s what I want now to short code into actionPerform


    public String getButtonExecutionInterval(GameContainer container, Input input, int delta, int mx, int my) throws SlickException {
        if (this.buttonContains(mx, my)) {
            if (this.buttonPressed(input)) {
                this.invoke = false;
                this.lastInvoke = container.getTime();

                return ONCE;
            }
            if (this.pressedTime < this.timeDuration && !this.buttonDown(input)) {
                this.pressedTime = this.timeDuration;
            }
            if (this.lastInvoke + 1000 < container.getTime()) {
                this.invoke = true;
            }
            if (this.buttonDown(input) && this.invoke) {
                this.pressedTime -= delta;
                if (this.pressedTime <= 0 && this.buttonDown(input)) {
                    this.pressedTime = this.timeDuration;

                    return REPEATEDLY;
                }
            }
        }
        return NEVER;
    }

It does make sense.

  1. User clicks in button, buttonDown is set to true.
  2. User releases mouse inside button rect, check if buttonDown is true, if so set it to false and fire event, if not, do nothing.

This prevents the user from clicking outside the button, dragging the mouse over the button and releasing to fire an event.

I don’t have buttonReleased method, what do you think it should contain ?

Right, I understand that. But considering the OP doesn’t have a released method, how would he check that? You can’t call the same method twice in one if statement and hope for different results!
Sorry OP I like being competitive :slight_smile:

Im not sure how Slick works, but that’s what I’d do if I had to implement a button. You need the released method, look up Slick docs or something.
The idea behind every button is the same.