Reputation: 13
I'm trying to make a game and this is what I use to draw the GUI on a JPanel.
g.drawImage(Assets.help, 950, 650, null);
if (mouseManager.getMouseX() >= 950 && mouseManager.getMouseX() <= 982) {
if (mouseManager.getMouseY() >= 650 && mouseManager.getMouseY() <= 682) {
g.drawImage(Assets.help_pushed, 950, 650, null);
if (mouseManager.isLeftPressed()) {
state = "credits";
}
}
}
It's full of if statements and clutters my code so I made a method to draw the buttons to clear up some space, but not all buttons change the state so I was wondering if there was a way to take a block of code as a parameter. Here's the method:
public void drawButton(Graphics g, BufferedImage button, BufferedImage buttonPushed, int x1, int x2, int y1, int y2, //CODE BLOCK) {
g.drawImage(button, x1, y1, null);
if (mouseManager.getMouseX() >= x1 && mouseManager.getMouseX() <= x2) {
if (mouseManager.getMouseY() >= y1 && mouseManager.getMouseY() <= y2) {
g.drawImage(buttonPushed, x1, y1, null);
if (mouseManager.isLeftPressed()) {
//CODE BLOCK
}
}
}
}
Upvotes: 0
Views: 664
Reputation: 96
There are multiple ways to achieve this. In classical Java, you can create your own Listener interface and pass an anonymous instance as a parameter. Example:
// Define your own listener once (you can add arbitrary parameters)
interface MyListener {
void runAction();
}
// Pass the listener instance
public void drawButton(Graphics g, BufferedImage button, BufferedImage buttonPushed, int x1, int x2, int y1, int y2, MyListener listener) {
g.drawImage(button, x1, y1, null);
if (mouseManager.getMouseX() >= x1 && mouseManager.getMouseX() <= x2) {
if (mouseManager.getMouseY() >= y1 && mouseManager.getMouseY() <= y2) {
g.drawImage(buttonPushed, x1, y1, null);
if (mouseManager.isLeftPressed()) {
listener.runAction(); // call the listener instance
}
}
}
}
// Invoking drawImage with a custom listener:
drawButton(g, button, image, x1, x2, y1, y2, new MyListener(){
@Override
public void runAction() {
// CODE BLOCK // put your code block here
}
});
Note that the MyListener interface is defined once and it can be instanciated when invoking the drawImage method with different code blocks.
In newer Java versions, you can also use functional interfaces. The concepts are similar, but these solutions require a bit less code, see https://www.baeldung.com/java-8-functional-interfaces
Upvotes: 0
Reputation: 814
You can use a lambda expression as Function, Supplier or Consumer depending if you need a return and/or input or not (of course you can skip the response and use Function in every case).
E.g.
public void drawButton(Graphics g, BufferedImage button, BufferedImage buttonPushed, int x1, int x2, int y1, int y2, //Function<String, String> myFunction / or Supplier<String> mySupplier / or Consumer<String> myConsumer) {
g.drawImage(button, x1, y1, null);
if (mouseManager.getMouseX() >= x1 && mouseManager.getMouseX() <= x2) {
if (mouseManager.getMouseY() >= y1 && mouseManager.getMouseY() <= y2) {
g.drawImage(buttonPushed, x1, y1, null);
if (mouseManager.isLeftPressed()) {
// CODE BLOCK
// state = myFunction.apply("credits");
// state = mySupplier.get();
// myConsumer.accept("credits");
}
}
}
}
The function, supplier and consumer look like this:
private Function<String, String> myFunction = input -> {
// I do the processing
return String.format("Input was: %s", input);
};
private Supplier<String> mySupplier = () -> {
// I do the processing
return "Hello World!";
};
private Consumer<String> myConsumer = input -> {
// I do the processing
System.out.println(String.format("Input was: %s", input));
};
You can also use the expression inline like for a Supplier:
drawButton(g,button, buttonPushed, x1, x2, y1, y2, input -> System.out.println(String.format("Input was: %s", input)));
or Consumer
drawButton(g,button, buttonPushed, x1, x2, y1, y2, input -> System.out.println(String.format("Input was: %s", input)));
or Function
drawButton(g,button, buttonPushed, x1, x2, y1, y2, input -> String.format("Input was: %s", input));
Upvotes: 1