Search code examples
javadiscord-jda

How to use JDA's setComponents() method with custom buttons?


I'm working on a Discord bot using the JDA (Java Discord API) library, and I'm trying to create an interactive message with custom buttons. However, I'm having trouble understanding how to correctly use the setComponents() method with my buttons when I have more than 5 buttons.

Here's a simplified version of my code:

List<Button> buttons = new ArrayList<>();
// Code to create and populate buttons...

Collection<LayoutComponent> buttonCollection = buttons.stream()
    .map(button -> {
        // How to properly convert Button objects to LayoutComponent objects?
    })
    .collect(Collectors.toList());

event.getHook().editOriginalEmbeds(eb.build()).setComponents(buttonCollection).queue();

My goal with this code is to create a collection of LayoutComponent objects from a list of Button objects and pass it to the setComponents() method to update the message with the new buttons.

However, I'm unsure about how to correctly convert Button objects to LayoutComponent objects. The JDA documentation doesn't seem to provide clear guidance on this.

Additionally, I'm aware that setActionRow(buttons) theoretically works, but it's not an option for me since I have more than 5 buttons.

Could someone please provide an example or explanation of how to achieve this? Any help would be greatly appreciated!

Additional Details:

  • JDA version: 5.0.0-beta.23
  • Java version: OpenJDK 22.0.1

Solution

  • You cannot put more than 5 buttons in a single action row but you can create multiple action rows each containing up to 5 buttons.

    You can create an ActionRow from buttons using ActionRow.of and then pass that to setComponents.

    event.getHook().editOriginalEmbeds(eb.build()).setComponents(
            ActionRow.of(
                    Button.of(ButtonStyle.SECONDARY, "b00", "0/0"),
                    Button.of(ButtonStyle.SECONDARY, "b01", "0/1"),
                    Button.of(ButtonStyle.SECONDARY, "b02", "0/2"),
                    Button.of(ButtonStyle.SECONDARY, "b03", "0/3"),
                    Button.of(ButtonStyle.SECONDARY, "b04", "0/4")
            ),
            ActionRow.of(
                    Button.of(ButtonStyle.SECONDARY, "b10", "1/0"),
                    Button.of(ButtonStyle.SECONDARY, "b11", "1/1"),
                    Button.of(ButtonStyle.SECONDARY, "b12", "1/2"),
                    Button.of(ButtonStyle.SECONDARY, "b13", "1/3"),
                    Button.of(ButtonStyle.SECONDARY, "b14", "1/4")
            )
        ).queue();
    

    With that, the first action row will be displayed in one row followed by the second action row.

    buttons in multiple rows

    If you want to automatically split it, you can do it with a simple loop:

    List<ActionRow> split = new ArrayList<>();
    List<Button> current = new ArrayList<>();
    for(Button button : buttons){
        current.add(button);
        if(current.size() >= 5){
            split.add(ActionRow.of(current));
            current = new ArrayList<>();
        }
    }
    event.getHook().editOriginalEmbeds(eb.build()).setComponents(split).queue();