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

2013/3/3

MouseInfo problem

Gevater_Tod4711 Gevater_Tod4711

2013/3/3

#
Hi all, I've got a problem using the MouseInfo class. Im trying to make my NumberField count up it's value if the mouse is pressed on the arrow button. If I click the button everything is working fine but if I try to count up the time any mousebutton is pressed it doesn't work. I want the numberfields to count up the value faster if the mouse is pressed on the object but the methods mouseDragged() (class Greenfoot), mousePressed() (class Greenfoot) and getButton() (class MouseInfo) seem to work only if the mouse button is pressed down AND the mouse is moved. Here's the code I use:
public class Arrow_Button extends Menu
{
    private String direction;
    
    private NumberField numberField;
    
    private long time;
    private long startingTime;
    
    public Arrow_Button(String direction, NumberField numberField) throws IllegalArgumentException {
        if (direction != "up" && direction != "down") {
            throw new IllegalArgumentException("String direction has to be \"up\" or \"down\"");
        }
        this.direction = direction;
        this.numberField = numberField;
        setImage(new GreenfootImage("arrow_" + direction + ".jpg"));
    }
    
    public Arrow_Button(String direction, NumberField numberField, int width, int height) {
        if (direction != "up" && direction != "down") {
            throw new IllegalArgumentException("String direction has to be \"up\" or \"down\"");
        }
        this.direction = direction;
        this.numberField = numberField;
        setImage(new GreenfootImage("arrow_" + direction + ".jpg"));
        getImage().scale(width, height);
    }
    
    public void act() {
        MouseInfo mouse = Greenfoot.getMouseInfo();
        if (Greenfoot.mouseClicked(this) && numberField != null) {
            if (!numberField.isActive()) {
                numberField.setActiveNumberField(numberField);
            }
            if (direction == "up") {
                numberField.incrementValue();
            }
            else {
                numberField.decrementValue();
            }
        }
        if (mouse.getButton() != 0 && mouseOnObject(this) && numberField != null) {
            if (!numberField.isActive()) {
                numberField.setActiveNumberField(numberField);
            }
            if (startingTime == 0) {
                startingTime = System.currentTimeMillis();
            }
            else {
                time = System.currentTimeMillis() - startingTime;
            }
            if (time > 500 && time % 5 == 0) {
                if (direction == "up") {
                    numberField.incrementValue();
                }
                else {
                    numberField.decrementValue();
                }
            }
        }
        else if (Greenfoot.mouseDragEnded(null)) {
            startingTime = 0;
        }
    }
    
    private boolean mouseOnObject(Actor actor) {
        MouseInfo mouse = Greenfoot.getMouseInfo();
        return mouse != null && mouse.getX() > actor.getX() - actor.getImage().getWidth()/2 && mouse.getX() < actor.getX() + actor.getImage().getWidth()/2 && 
            mouse.getY() > actor.getY() - actor.getImage().getHeight()/2 && mouse.getY() < actor.getY() + actor.getImage().getHeight()/2;
    }
}
Am I doing anything wrong or is this a bug in the Greenfoot API?
MatheMagician MatheMagician

2013/3/5

#
If you just want to know whether or not the mouse is being held down, the mousePressed() method will only tell you when the mouse is immediately pressed, but will only return true for one act cycle and then return to false. The mouseReleased() will similarly only notify you immediately after the mouse has been released again. You have to use a boollean that is turned to true when the mouse is pressed and then changed to false when the mouse is released. Kind of like this:
boolean mouseIsDown = false;
if(Greenfoot.mousePressed(this))
     mouseIsDown = true;
else if(Greenfoot.mouseReleased(this))
     mouseIsDown = false;
danpost danpost

2013/3/5

#
There is no 'mouseReleased' method in the Greenfoot class. 'mouseClicked' is what returns true when a mouse button is released. Unfortunately, there are two mouse buttons that can be pressed and clicked. This will cause problems with the working of the code. If one button is pressed, next the other, and finally one is released, then your boolean will be 'false', yet there is a mouse button still down.
davmac davmac

2013/3/5

#
Maybe I'm missing something, but this code doesn't look like it would work at all. On line 42 you call a method (getButton) on the MouseInfo reference without checking whether it's null. Also, calling getButton without checking for an event doesn't really make sense. The button will only be set to something if there's an event - mouse pressed, clicked, dragged, or drag ended.
Gevater_Tod4711 Gevater_Tod4711

2013/3/5

#
I think I'll try to use the boolean value. Thank you guys. @davemac Yes I also saw this problem. I corrected it in my code but didn't update the code here. I just wanted to check whether the getButton method could check whether there is a button pressed.
MatheMagician MatheMagician

2013/3/5

#
Sorry, I think I was refering to the mouseDragged(java.lang.Object obj) method. Anyway, I think mouseClicked() will work just as well.
Upupzealot Upupzealot

2013/3/5

#
@davmac clicked actually means released, would you Greenfoot team consider adding something as "button down" or "button up" things. Also what's more, what about "mouse enter" and "mouse leave", I know that could be down by ourselves, but I think it would be clearer to let it added into Greenfoot API directly.
danpost danpost

2013/3/6

#
I think you can find what you are looking for in the code of my 'MseActBar' class of my Bar Subclasses demo.
davmac davmac

2013/3/6

#
Upupzealot, you can detect a mouse button down using 'mousePressed' and a mouse button up using 'mouseClicked' and 'mouseDragEnded' (one of them will return true for a button release). I agree the API could be improved a bit, maybe in a future release this will happen.
danpost danpost

2013/3/6

#
Below is a more generic and simplified version of the mouse action code in my 'MseActBar' class. Hope it helps.
// fields
private int value; // current value of numberfield
private boolean buttonDown; // flag signifying within value-changing process
private int timer; // the delay counter

// the basic act method
public void act()
{
    // check for initial mouse button pressing
    if (!buttonDown && Greenfoot.mousePressed(this))
    { // a mouse button was pressed down on the object; bump value and set both flag and timer
        value++;
        buttonDown = true;
        timer = 50; // the initial delay amount
    }
    if (buttonDown)
    { // mouse button was previously found to be pressed down; check if the button is still down
        if (!Greenfoot.mouseClicked(null))
        { // mouse button still being held down; check if time to adjust value again
            timer--;
            if (timer == 0)
            { // time to adjust value again; bump value and reset timer
                value++;
                timer = 4; // the non-initial delay amount             }
        }
        // mouse button clicked (released), action over
        else buttonDown = false;
    }
}
You need to login to post a reply.