如何在discord.py中根据用户输入自动创建动态按钮?
动态创建Discord按钮的优雅实现方案
原代码问题分析
你当前的代码只生成单个按钮,核心原因有两个:
- 类定义阶段使用for循环加装饰器时,每次生成的回调方法都重名(
first_button_callback),后续迭代会覆盖之前的方法,最终仅保留最后一个按钮的绑定。 - 闭包变量
bnum未被正确捕获,所有回调会共享循环结束后的bnum值,导致逻辑错误。
优雅解决方案:手动创建按钮并绑定回调
直接绕过类装饰器的限制,通过手动创建discord.ui.Button实例并绑定带参数的回调,既避免方法名冲突,也能正确传递每个按钮对应的选项。这里用functools.partial来绑定回调参数:
from functools import partial import discord class ButtonView(discord.ui.View): def __init__(self, guild_id, options): super().__init__() # 限制最多5个选项 limited_options = options[:5] for option in limited_options: # 绑定当前选项到回调函数 bound_callback = partial(self._button_callback, option=option) # 创建按钮实例 button = discord.ui.Button(label=option, style=discord.ButtonStyle.green) # 绑定回调 button.callback = bound_callback # 添加到View self.add_item(button) async def _button_callback(self, interaction, option): await interaction.response.send_message(f"You voted for {option}", ephemeral=True)
使用方式
从模态框获取用户输入的参数列表后,直接实例化View即可:
# 假设从模态框得到的参数是user_input_options(列表类型) view = ButtonView(guild_id=your_guild_id, options=user_input_options) # 发送带按钮的消息 await interaction.response.send_message("请选择:", view=view)
另一种可选方案:动态生成回调方法名
如果偏好使用装饰器风格,可以通过动态生成唯一的方法名来避免覆盖,不过代码复杂度稍高:
import discord class ButtonView(discord.ui.View): def __init__(self, guild_id, options): super().__init__() limited_options = options[:5] for idx, option in enumerate(limited_options): # 生成唯一的方法名 callback_name = f"_button_callback_{idx}" # 定义回调函数 async def callback(self, interaction, option=option): await interaction.response.send_message(f"You voted for {option}", ephemeral=True) # 绑定方法到类实例 setattr(self, callback_name, callback) # 创建按钮并绑定回调 button = discord.ui.Button(label=option, style=discord.ButtonStyle.green) button.callback = getattr(self, callback_name) self.add_item(button)
内容的提问来源于stack exchange,提问作者Liam McMillen-Meyers
相关产品推荐
相关产品推荐

