You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在discord.py中使带custom_id的按钮正常响应点击?

问题分析与修复方案

核心问题点

  • 你搞混了interaction.id和按钮的custom_id:interaction.id是每次点击生成的唯一交互ID,每次点都会变;要获取按钮设置的自定义ID,得用interaction.component.custom_id或者interaction.data["custom_id"]。
  • 所有按钮的custom_id都设成了同一个值"Filou",根本没法区分不同玩家的按钮。
  • 回调函数绑定位置错了:循环里创建的按钮只有最后一个会被绑定filou回调,前面的按钮都没关联上响应逻辑。
  • 自定义的Report_Buttons没继承discord.ui.View,这样的视图根本没法正常工作。

修正后的代码

from discord import ButtonStyle, Interaction
from discord.ui import View, Button

# 先定义正确的视图类
class Report_Buttons(View):
    def __init__(self, ctx):
        super().__init__(timeout=None)  # 设置timeout=None让视图持久化,按需调整超时时间
        self.ctx = ctx

# 举报命令部分
@bot.command()
async def Report(ctx):
    players = list(player_list.values())
    view = Report_Buttons(ctx)

    for player in players:
        # 给每个按钮生成唯一custom_id,比如用玩家ID做标识
        player_unique_id = str(player[0])  # 假设player[0]是玩家的唯一ID,也可以用名字
        button = Button(
            style=ButtonStyle.danger,
            label=str(player[1]),
            disabled=False,
            custom_id=f"report_player_{player_unique_id}"  # 每个按钮的ID唯一
        )

        # 给当前按钮绑定回调逻辑
        async def button_callback(interaction: Interaction):
            # 获取当前按钮的自定义ID
            current_btn_id = interaction.component.custom_id
            # 提取玩家ID,判断是哪个玩家的按钮被点了
            if current_btn_id.startswith("report_player_"):
                target_id = current_btn_id.split("_")[-1]
                target_player = next(p for p in players if str(p[0]) == target_id)
                await ctx.send(f"玩家「{target_player[1]}」的按钮被点击了!")

        button.callback = button_callback
        view.add_item(button)

    await ctx.send("请选择要举报的玩家:", view=view)

关键修改说明

  1. 正确获取按钮ID:用interaction.component.custom_id拿到你设置的自定义ID,再也不会被每次变化的交互ID搞混。
  2. 唯一标识按钮:每个按钮的custom_id带上玩家的唯一信息,确保能精准区分是谁的按钮被点击。
  3. 循环内绑定回调:在创建每个按钮的同时绑定回调,保证所有按钮都有响应逻辑。
  4. 规范视图类:让Report_Buttons继承discord.ui.View,这是Discord按钮视图的基础要求。

如果不想给每个按钮单独写回调,也可以用视图的装饰器批量处理,更简洁:

class Report_Buttons(View):
    def __init__(self, ctx, players):
        super().__init__(timeout=None)
        self.ctx = ctx
        self.players = players

    # 匹配所有以report_player_开头的按钮
    @discord.ui.button(custom_id="report_player_", style=ButtonStyle.danger)
    async def handle_player_click(self, interaction: Interaction, button: Button):
        target_id = button.custom_id.split("_")[-1]
        target_player = next(p for p in self.players if str(p[0]) == target_id)
        await self.ctx.send(f"玩家「{target_player[1]}」的按钮被点击了!")

@bot.command()
async def Report(ctx):
    players = list(player_list.values())
    view = Report_Buttons(ctx, players)

    for player in players:
        button = Button(
            style=ButtonStyle.danger,
            label=str(player[1]),
            disabled=False,
            custom_id=f"report_player_{str(player[0])}"
        )
        view.add_item(button)

    await ctx.send("请选择要举报的玩家:", view=view)

内容的提问来源于stack exchange,提问作者Miniveleur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:15:15