问题
I know many questions have been asked to solve similar problem but i could not find an answer to it.
Problem : I have made a screen for my libgdx game which looks like the following screenshot.
I want the input through touch only.When i press and hold the button labeled 'lower' it decrements the number in the middle once. I want it to keep decrementing until i release the 'lower' button. I have placed the button in a table, which in turn is added on a stage. To achieve what i want i used the following approach :
TextButton less; //for the button labeled 'lower'
....
***constructor start****
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
table = new Table();
table.setFillParent(true);
stage.addActor(table);
......
......
style = new TextButton.TextButtonStyle();
style.up = new TextureRegionDrawable(upRegion);
style.down = new TextureRegionDrawable(downRegion);
style.font = buttonFont;
less = new TextButton("lower", style);
table.add(less).expand().fill();
....
....
less.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
while(less.isPressed()) {
Gdx.app.log("ispressed ","yes");
curLevel--;
level.setText("" + curLevel);
Gdx.app.log("curLevel: ",curLevel+"");
try{
Thread.sleep(1000);
}catch (Exception e){
}
}
}
}
....
....
***constructor ends****
But the while loop in changed() goes infinite even if i release the "less/lower" button. I have also tried the solution to this question but this also results in infinite loop.
Also my project details are : (if they matter) :
ext {
appName = 'kombat'
gdxVersion = '1.5.2'
roboVMVersion = '1.0.0-beta-01'
box2DLightsVersion = '1.3'
ashleyVersion = '1.3.1'
aiVersion = '1.4.0'
}
I tried solution from gaRos but as a result the number in the label goes on decreasing infinitely even after a single touch and release. Here is what i did to follow gaRos's instructions :
Overrode the act method
package com.zeher.kombat; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.zeher.kombat.Screens.LevelChooser; /** * Created by zucky on 10/4/2015. */ public class LessButton extends TextButton { LevelChooser lc; public LessButton(String text,TextButton.TextButtonStyle skin,Kombat game) { super(text, skin); this.lc=game.introScreen.lc; } @Override public void act(float delta){ if(lc.lowerFlag ) { lc.curLevel--; lc.level.setText("" + lc.curLevel); } }
}
Used the inputListener.
less.addListener(new InputListener() { public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { lowerFlag = true; return false; } public void touchUp(InputEvent event, float x, float y, int pointer, int button) { lowerFlag = false; Gdx.app.log("occured: ","touchUp on less"); } });
But the problem is that the touchUp event does not get fired and lowerFlag never switches to false.
Kindly tell me what is causing this unexpected behaviour and how to handle the press and hold gesture the way i want.
回答1:
TextButton is an Actor, so you can set an InputListener for it.
That interface has two methods to implement:
less.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
lowerFlag = true;
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
lowerFlag = false;
}
});
And you override the act
method of the button and lower the value if the flag is true. Use the delta as a parameter how fast you want to decrease curLevel
.
(if the delta is bigger decrease more, if is lower decrease less)
回答2:
First of all, i want to thank gaRos for giving a hint.
The listener we should be using with actors for this purpose is ActorGestureListener . It should be like this :
less.addListener(new ActorGestureListener() { public void touchDown(InputEvent event, float x, float y, int pointer, int button) { lowerFlag = true; Gdx.app.log("occured: ","touchDown on less"); //to test whether it works or not } public void touchUp(InputEvent event, float x, float y, int pointer, int button) { lowerFlag = false; Gdx.app.log("occured: ","touchUp on less"); } });
Now override the act method for that 'less' button by making a new class which extends TextButton such that it lowers the value if the flag is true. Use the delta as a parameter how fast you want to decrease curLevel.
(if the delta is bigger decrease more, if is lower decrease less). For example i created the class LessButton.java.
public class LessButton extends TextButton {
LevelChooser lc;
public LessButton(String text, TextButton.TextButtonStyle skin,Kombat game) {
super(text, skin);
this.lc=game.introScreen.lc;
}
@Override
public void act(float delta){
wait+=delta;
if(lc.lowerFlag && lc.curLevel>0 && wait>delta*8) {
lc.curLevel--;
lc.level.setText("" + lc.curLevel);
wait=0f;
}
}
}
3. Now use it like this:
LessButton less;
....
less = new LessButton("lower", style,game);
来源:https://stackoverflow.com/questions/32818163/why-doesnt-my-approach-work-to-continuously-repeat-an-action-till-a-libgdx-scen