8

My question is straightforward.

I have some ClickListeners added to an Actor. I want to execute a click event on them programmatically.

Something like myActor.performClick();

Cœur
  • 37,241
  • 25
  • 195
  • 267
Rahul Verma
  • 2,140
  • 3
  • 21
  • 31

4 Answers4

13

You can also use:

InputEvent event1 = new InputEvent();
event1.setType(InputEvent.Type.touchDown);
button.fire(event1);

InputEvent event2 = new InputEvent();
event2.setType(InputEvent.Type.touchUp);
button.fire(event2);

This will also show any pressed image change which can be helpful.

Winter
  • 3,894
  • 7
  • 24
  • 56
user2299004
  • 131
  • 1
  • 2
8

I figured out a solution :

public static void performClick(Actor actor) {
    Array<EventListener> listeners = actor.getListeners();
    for(int i=0;i<listeners.size;i++)
    {
        if(listeners.get(i) instanceof ClickListener){
            ((ClickListener)listeners.get(i)).clicked(null, 0, 0);
        }
    }
}

This method can be called passing the actor on whom click needs to be performed

Rahul Verma
  • 2,140
  • 3
  • 21
  • 31
2

I do it like this (seems nicer to me):

public void triggerButtonClicked(Button button) {
    InputEvent inputEvent = Pools.obtain(InputEvent.class);
    inputEvent.reset();
    inputEvent.setButton(0);
    inputEvent.setRelatedActor(button);

    try {
        inputEvent.setType(InputEvent.Type.touchDown);
        button.fire(inputEvent);

        inputEvent.setType(InputEvent.Type.touchUp);
        button.fire(inputEvent);
    } finally {
        Pools.free(inputEvent);
    }
}
Betalord
  • 109
  • 7
  • If there's an exception during a real touch down the touch up will still be called right? But I don't see actual use case where perfect simulation is needed. – Winter Jan 11 '18 at 16:20
0

If you want to simulate user clicking on a visible actor, then you can find a point inside actor and tell InputProcessor to send touch events there.

// a point in the middle of the actor
val middle = actor.localToScreenCoordinates(Vector2(
    this.width / 2,
    this.height / 2
))

// simulate left mouse button press and release
Gdx.input.inputProcessor.touchDown(
    middle.x.toInt(), 
    middle.y.toInt(), 
    0,
    Input.Buttons.LEFT
)
Gdx.input.inputProcessor.touchUp(
    middle.x.toInt(),
    middle.y.toInt(),
    0,
    Input.Buttons.LEFT
)

Depending on actor style, touch down event can issue a change in actor's appearance which require being on the LibGDX's main thread. So if you are not on that thread (for example, simulating a click from a JUnit test case) then Gdx.input.inputProcessor.touchDown and touchUp have to be inside Gdx.app.postRunnable block.

Emperor Orionii
  • 703
  • 10
  • 22