如何在Discord Python选择菜单中实现二级嵌套选择功能?
实现Discord选择菜单的二级嵌套交互
要实现选择首个选项后弹出二级选择的效果,核心思路是在一级菜单的回调中动态更新消息的View,替换成二级选择菜单。以下是修改后的完整代码:
import discord from discord.ext import commands # 一级选择菜单 class FirstDropdown(discord.ui.Select): def __init__(self): options = [ discord.SelectOption(label='Акрополь', description='Выберите вариант баннера "Акрополь"', emoji='🏛️'), discord.SelectOption(label='Год Кролика', description='Будет отправлен баннер "Год Кролика"', emoji='🐇'), discord.SelectOption(label='Зевс', description='Будет отправлен баннер "Зевс"', emoji='⚡'), ] super().__init__(placeholder='Выберите нужный баннер:', min_values=1, max_values=1, options=options) async def callback(self, interaction: discord.Interaction): if self.values[0] == 'Акрополь': # 清空当前View的所有组件,添加二级选择菜单 self.view.clear_items() self.view.add_item(SecondDropdown()) # 更新消息内容和View,引导用户选择子选项 await interaction.response.edit_message(content='Выберите вариант баннера "Акрополь":', view=self.view) elif self.values[0] == 'Год Кролика': await interaction.response.send_message('Баннер "Год Кролика"', file=discord.File(r'C:\Users\Timir\AppData\Local\Discord\Kroll.png')) elif self.values[0] == 'Зевс': await interaction.response.send_message('Баннер "Зевс"', file=discord.File(r'C:\Users\Timir\AppData\Local\Discord\Zevs.png')) # 二级选择菜单(仅针对"Акрополь"选项) class SecondDropdown(discord.ui.Select): def __init__(self): # 自定义二级选项,可根据需求修改 options = [ discord.SelectOption(label='Акрополь - Дневной', description='Дневная версия баннера', emoji='☀️'), discord.SelectOption(label='Акрополь - Ночной', description='Ночная версия баннера', emoji='🌙'), ] super().__init__(placeholder='Выберите вариант:', min_values=1, max_values=1, options=options) async def callback(self, interaction: discord.Interaction): # 根据二级选择发送对应文件 if self.values[0] == 'Акрополь - Дневной': await interaction.response.send_message('Баннер "Акрополь - Дневной"', file=discord.File(r'C:\Users\Timir\AppData\Local\Discord\Akropol_day.png')) elif self.values[0] == 'Акрополь - Ночной': await interaction.response.send_message('Баннер "Акрополь - Ночной"', file=discord.File(r'C:\Users\Timir\AppData\Local\Discord\Akropol_night.png')) # 视图类,用于承载选择菜单 class DropdownView(discord.ui.View): def __init__(self): super().__init__(timeout=180) # 设置3分钟超时,可调整 self.add_item(FirstDropdown()) # 初始化机器人 intents = discord.Intents.all() intents.message_content = True bot = commands.Bot(command_prefix='+', intents=intents) @bot.event async def on_ready(): print(f'Logged in as {bot.user} (ID: {bot.user.id})') print('------') @bot.command() async def banner(ctx): """Отправляет сообщение с выбором баннера""" view = DropdownView() await ctx.send('Выберите нужный баннер:', view=view) @bot.command() async def Молодец(ctx): await ctx.send(f"{ctx.author.mention} молодец") bot.run('bottoken')
关键改动说明
- 拆分选择菜单类:将原来的单一
Dropdown拆分为FirstDropdown(一级菜单)和SecondDropdown(二级菜单),分别处理不同层级的选择逻辑。 - 动态更新View:在一级菜单的
callback中,当用户选择"Акрополь"时,调用self.view.clear_items()清空当前视图组件,再添加二级菜单,最后用interaction.response.edit_message()更新原消息的内容和视图。 - 修复重复初始化问题:删除冗余的
Bot类定义,统一使用bot = commands.Bot()初始化,并通过@bot.event定义on_ready事件。 - 设置超时时间:给
DropdownView设置180秒超时,避免视图长时间无效占用资源。
注意事项
- 请确保二级菜单对应的图片文件路径正确,否则会抛出文件不存在的错误。
- 如果需要扩展更多层级嵌套,可按照相同逻辑继续添加新的选择菜单类,并在对应回调中更新视图。
内容的提问来源于stack exchange,提问作者Oskar Voralberg
相关产品推荐
相关产品推荐

