分类: Discord 机器人开发
Discord 机器人开发#6实现下拉菜单(Select Menu)!
本文译自韩语原文。
目录8 项
大家好!我是 Mojangcam 😎
在上一篇 #5中,我们学习了如何用按钮(Button)和机器人交互,对吧?这次再进一步,来做一个下拉菜单(Select Menu)!
按钮适合只有 2~3 个选项的场景,可一旦选项超过 5 个,屏幕就会被按钮塞满。这时候用下拉菜单,就能把最多 25 个选项整整齐齐地放进一个菜单里。身份组选择、问卷调查、游戏服务器选择菜单等场景都非常常用!

📌 准备工作
- Python 3.8 及以上
- discord.py 2.x(Select Menu 从 2.0 开始支持!)
- 机器人 Token + 已把机器人邀请进服务器(参考本系列第 1 篇!)
pip install -U discord.py可以用 pip show discord.py 查看版本。2.x 及以上就 OK!1.x 版本无法运行。
📌 第 1 步 - 创建 Select(下拉菜单)类
下拉菜单的核心是 discord.ui.Select 类。继承这个类,然后定义选项(SelectOption)和选择后的行为(callback)。
import discord
from discord.ext import commands
class GameSelect(discord.ui.Select):
def __init__(self):
options = [
discord.SelectOption(label="我的世界", value="minecraft", description="用方块搭建的世界", emoji="⛏️"),
discord.SelectOption(label="方舟:生存进化", value="ark", description="和恐龙一起求生!", emoji="🦖"),
discord.SelectOption(label="无畏契约", value="valorant", description="5v5 战术 FPS", emoji="🔫"),
]
super().__init__(
placeholder="请选择你喜欢的游戏!",
min_values=1,
max_values=1,
options=options,
)
async def callback(self, interaction: discord.Interaction):
await interaction.response.send_message(
f"🎮 {interaction.user.mention} 选择了 **{self.values[0]}**!"
)逐个拆解来看 💡
SelectOption:下拉菜单里显示的每一个选项。label是屏幕上显示的名称,value是代码中接收到的值,description是灰色的说明文字,emoji是显示在前面的表情。placeholder:还没有选择任何内容时显示的提示文字。min_values/max_values:最少·最多可选数量。设置成max_values=3就变成多选菜单了!(最多 25)callback:用户完成选择后执行的函数。选中的值会放进self.values列表里。
📌 第 2 步 - 放进 View 里
就像在按钮篇中学到的那样,所有 UI 组件都要装进一个叫 View 的容器里再发送。
class GameSelectView(discord.ui.View):
def __init__(self):
super().__init__(timeout=60) # 60 秒后失效
self.add_item(GameSelect())顺便一提,一个下拉菜单会独占 View 的一整行(row)。View 最多只有 5 行,所以一个 View 里最多只能放 5 个下拉菜单。
📌 第 3 步 - 用斜杠命令发送
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.event
async def on_ready():
await bot.tree.sync()
print(f"✅ {bot.user} 机器人已准备就绪!")
@bot.tree.command(name="게임선택", description="来选一个你喜欢的游戏吧!")
async def game_select(interaction: discord.Interaction):
await interaction.response.send_message("请在下方选择!👇", view=GameSelectView())
bot.run("Token")📌 完整代码(可直接复制)
# discord.py 2.x / Python 3.8+
import discord
from discord.ext import commands
class GameSelect(discord.ui.Select):
def __init__(self):
options = [
discord.SelectOption(label="我的世界", value="我的世界", description="用方块搭建的世界", emoji="⛏️"),
discord.SelectOption(label="方舟:生存进化", value="方舟:生存进化", description="和恐龙一起求生!", emoji="🦖"),
discord.SelectOption(label="无畏契约", value="无畏契约", description="5v5 战术 FPS", emoji="🔫"),
]
super().__init__(placeholder="请选择你喜欢的游戏!", min_values=1, max_values=1, options=options)
async def callback(self, interaction: discord.Interaction):
await interaction.response.send_message(
f"🎮 {interaction.user.mention} 选择了 **{self.values[0]}**!"
)
class GameSelectView(discord.ui.View):
def __init__(self):
super().__init__(timeout=60)
self.add_item(GameSelect())
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.event
async def on_ready():
await bot.tree.sync()
print(f"✅ {bot.user} 机器人已准备就绪!")
@bot.tree.command(name="게임선택", description="来选一个你喜欢的游戏吧!")
async def game_select(interaction: discord.Interaction):
await interaction.response.send_message("请在下方选择!👇", view=GameSelectView())
bot.run("Token")📌 运行结果
输入 /게임선택(即"选择游戏")后,机器人会发送一条带下拉菜单的消息;在菜单里选好游戏,就会收到"🎮 OO 选择了 我的世界!"这样的回复。
💡 附加内容:还有专门用来选择用户·身份组·频道的下拉菜单!使用 discord.ui.UserSelect、discord.ui.RoleSelect、discord.ui.ChannelSelect,就不用自己定义选项,服务器的用户/身份组/频道列表会自动显示出来。以后有机会再详细讲讲!
📌 常见错误
1. This interaction failed(交互失败)
callback 没有在 3 秒内响应时就会出现这个错误。如果处理需要较长时间,请先调用 await interaction.response.defer(),再用 interaction.followup.send() 回复即可。
2. 下拉菜单变成灰色、无法使用
超过 View(timeout=60) 设定的时间后,组件就会过期。如果菜单需要一直可用,请设置为 timeout=None。(如果想在机器人重启后也保留,需要使用 persistent view 并指定 custom_id,这部分会在进阶篇里讲!)
3. TypeError: __init__() got an unexpected keyword argument 'options'
把 options 传给 UserSelect 这类专用下拉菜单,而不是 discord.ui.Select 时,就会出现这个错误。自己定义选项时,一定要使用基础的 discord.ui.Select。
📌 总结
今天我们学习了如何用下拉菜单(Select Menu)整齐地放下最多 25 个选项。从按钮一路走到下拉菜单,下一篇我们来讲讲如何用模态框(Modal)让用户直接输入文本!敬请期待 🙌
📚 Discord 机器人开发系列
- Slash Command 完全攻略
- 为 Slash Command 添加选项(Arguments)
- 在 Slash Command 中添加子命令
- 用 Slash Command 发送 Embed
- 实现按钮(Button)交互
- 实现下拉菜单(Select Menu) ← 就是这篇!
连载 · 共 32 篇中的第 6 篇
Discord 机器人开发
- #1Discord 机器人开发 - Slash Command 完全攻略!
- #2为 Slash Command 添加选项(Arguments)!
- #3在 Slash Command 中添加子命令(Subcommand)!
- #4用 Slash Command 发送 Embed 嵌入消息!
- #5实现按钮(Button)交互!
- #6实现下拉菜单(Select Menu)!当前文章
- #7用模态框(Modal)接收用户输入(Python 示例)
- #8用嵌入消息(Embed)的图片和字段美化消息(Python 示例)
- #9接入 AI(Claude·ChatGPT API)!(Python 示例)
- #10支持多语言(i18n)!(Python 示例)
- #11用 Flask 制作网页仪表盘!(Python 示例)
- #12管理命令冷却时间(Cooldown)与权限(Permission)!(Python 示例)
- #13用身份组·频道自动化管理服务器!(Python 示例)
- #14保存数据!JSON vs SQLite(Python 示例)
- #15슬래시 명령어 그룹(Group)으로 명령어 정리하기! (파이썬 예제) (韩语)
- #16리마인더·알림 기능 만들기! 봇이 먼저 말 걸게 하기 (파이썬 예제) (韩语)
- #17RAG로 문서 기반 답변봇 만들기! 우리 서버 전용 FAQ 봇 (파이썬 예제) (韩语)
- #18투표(Poll) 기능 만들기! 다수결로 정하는 서버 규칙 (파이썬 예제) (韩语)
- #19Cog로 코드 쪼개기! 1000줄 봇도 안 더러워지는 구조 (파이썬 예제) (韩语)
- #20자동 환영 메시지·온보딩 만들기! 규칙 동의 버튼으로 자동 역할 부여 (파이썬 예제) (韩语)
- #21키워드 자동응답·금지어 필터 만들기! 경고 누적으로 자동 제재까지 (파이썬 예제) (韩语)
- #22슬래시 명령어 자동완성(Autocomplete) 만들기! 금지어를 골라서 추가·삭제 (파이썬 예제) (韩语)
- #23aiosqlite로 비동기 DB 제대로 설계하기! JSON 탈출 (파이썬 예제) (韩语)
- #24채널 난독화(Channel Obfuscation) 대응하기! 11/16부터 안 보이는 채널이 생겨요 (파이썬 예제) (韩语)
- #25봇이 죽지 않게! 에러 핸들링·로깅 체계 잡기 (파이썬 예제) (韩语)
- #26티켓(Ticket) 문의 시스템 만들기! 버튼 하나로 1:1 상담 채널 자동 생성 (파이썬 예제) (韩语)
- #27티켓 담당자 배정·우선순위 만들기! 스태프가 여러 명이어도 안 꼬이게 (파이썬 예제) (韩语)
- #28레벨·경험치(XP) 시스템 만들기! 채팅할수록 레벨업, 랭킹판까지 (파이썬 예제) (韩语)
- #29화폐·상점(Economy) 시스템 만들기! 코인 벌어서 아이템 사기 (파이썬 예제) (韩语)
- #30打造投票·问卷(Poll)机器人!原生投票 + 按钮实时统计(Python 示例)🗳️
- #32打造服务器日志·审核日志(Audit Log)频道!自动记录消息删除、编辑、成员进出和踢出(Python 示例)🕵️
- #33임시 음성방 확장, 파티방 만들기! 방장 위임·강퇴·초대 전용(비공개) 방 + 전용 채팅방 자동 생성 (파이썬 예제) 🎉 (韩语)
