Qt 鼠标形状 19 种 CursorShape 分不清?TaoToken 通道下让 Codex 逐个对照

发布时间:2026/9/18 23:23:09
Qt 鼠标形状 19 种 CursorShape 分不清?TaoToken 通道下让 Codex 逐个对照 Qt 鼠标形状 19 种 CursorShape 分不清是自定义控件里最容易绊住人的一个细节。TaoToken 在这篇里只做两件事给你一把能调模型的 Key给 Codex 一条稳定的兼容通道。先去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册并创建 API Key把 Base URL 填 https://taotoken.net/api 接到 Codex 上再把原文 Cursor 类里对不上的那段贴进对话让模型对着 enum Qt::CursorShape 逐条比对。光标形状本身仍然由 Qt 的 setCursor 决定通道不参与任何光标逻辑它只负责让你问得上、问得快。原始那篇《QT 鼠标形状》的写法很朴素一个 Cursor 类十九个槽函数每个槽函数里一行 setCursor。slotArrow() 调 setCursor(Qt::ArrowCursor)slotWait() 调 setCursor(Qt::WaitCursor)slotSizeB() 调 setCursor(Qt::SizeBDiagCursor)slotSplitV() 调 setCursor(Qt::SplitVCursor)一路排到 slotClosedHand()。单看代码挑不出毛病编译也过可一旦把鼠标挨个移到按钮上试心里就会冒出一串问号SplitHCursor 和 SizeHorCursor 到底谁管左右分栏WhatsThisCursor 长什么样UpArrowCursor 在这台机器上是不是根本看不出区别。这类问题的尴尬之处在于答案全写在 Qt 头文件里但没人能只靠读名字记住形状。人脑对「一个竖直条两边带左右小箭头」的记忆远不如对像素的记忆。所以下面的排障路线不是让你背枚举而是搭一张能跑起来的对照表本地起一个窗口鼠标扫过哪一行整窗光标就切成哪一行的形状十九个槽函数在同一屏里全触发一遍标不出来或者和你预期相反的那几行把代码段原样丢给 Codex让它指出槽函数名、枚举名、真实形状三者的偏差。1. 十九个槽函数里对不上的通常是这几个1.1 原文那套 setCursor 写法卡点不在语法原文的组织方式是把每个形状都封成一个槽按钮 clicked 连过去点了才换光标。这个结构本身没问题甚至比直接在 paintEvent 里乱设 cursor 干净得多。真正让人反复回头查的是「槽函数名」和「枚举语义」之间那层不透明slotSizeB 里的 B 是 Bottom 还是 BothslotSplitV 的 V 指分割条本身竖直还是指上下被分开。名字起得越短回头越容易忘。更麻烦的是原文只给了逐行的 setCursor没有给出「现在这个形状到底长什么样」的即时反馈。你在两个枚举之间犹豫时只能改代码、重编译、再点一次按钮一轮下来三十秒就没了。十九个形状挨个怀疑一遍一个下午就交代进去了。1.2 SplitH、SizeH、WhatsThis三个最容易翻车的枚举把十九个形状按槽函数排开日常被问最多的就是下面三个。它们的共同点是名字里的方向词指向的是「被操作的容器」而不是「箭头指向哪里」。槽函数CursorShape实际形状多数桌面主题下用在哪slotSplitHQt::SplitHCursor竖直细条两侧带左右小箭头左右分栏的分割条slotSplitVQt::SplitVCursor水平细条上下带小箭头上下分栏的分割条slotSizeHQt::SizeHorCursor普通的左右双箭头拖窗口、拖列宽slotSizeVQt::SizeVerCursor普通的上下双箭头拖行高slotWhatsThisQt::WhatsThisCursor箭头旁边挂一个问号「这是什么」帮助模式slotBlankQt::BlankCursor什么都没有光标消失全屏播放、隐藏指针SplitHCursor 的 H 说的是「Horizontal 方向上的分割」也就是把窗口切成左右两块所以分割条本身是竖的。SizeHorCursor 的 Hor 说的是「箭头沿水平方向动」所以箭头是左右向的。两条都带左右但一条是细条加小箭头一条是纯双箭头肉眼差别不大语义差得很远——分割条上挂错用户拖两下就会觉得别扭。WhatsThisCursor 是另一个典型。很多人以为它是个纯问号实际上多数主题里是箭头加问号而且在 Qt Fusion、Windows Vista 这类风格下还会再变一次样子。BlankCursor 更狠它本来就该看不见你如果拿它当「默认形状」测会以为是配置没生效。1.3 为什么「读文档」解不了这个惑Qt 文档对每个枚举都有一句英文描述比如 SplitHCursor 写的是「a horizontal splitter」你读完还是不知道它长得像不像 SizeHorCursor。文档解决的是「这个枚举存在的意义」不解决「我眼睛看到的这个是不是它」。这两件事之间的桥只有把形状真正渲染到屏幕上才能搭起来。这也是为什么后面要拉 Codex 进来它擅长的是把枚举列表、命名规律、平台差异一次性摊平让你在改代码之前就知道该怀疑哪几个而验证形状还得靠你本地跑起来的那几十秒。2. 让 Codex 当活体对照表config.toml 与 auth.json 怎么填2.1 先去模型广场确认模型 ID再创建 Key别急着翻配置文件先确认两件事一个能用的模型 ID一把能用的 Key。打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 登录在模型广场里挑一个适合读代码的模型把它的 ID 原样记下来——这个 ID 后面要写进 config.toml不要凭印象拼也不要自己加日期后缀以列表里当时显示的那串为准。Key 在同一站点的控制台里创建创建出来的字符串只在弹窗里完整显示一次先粘到密码管理器里再关页面。整篇出现的 Key 都用 YOUR_API_KEY 代替你实际填的是自己那串。2.2 ~/.codex/config.toml 里的 model_provider 和 base_urlCodex 的配置走 TOML文件在用户目录下的 ~/.codex/config.toml。要接 TaoToken 的兼容通道核心是自定义一个 model_provider把 base_url 指到 https://taotoken.net/api注意末尾不带 /v1也不要带任何查询串。模型 ID 换成你刚从模型广场抄下来的那一串。# ~/.codex/config.toml model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chatwire_api 这一行按你所选模型的接口类型来模型广场和 TaoToken 的文档里会写清楚是 chat 还是 responses拿不准就先按上面写报错再对照文档改。注意这一段是给 Codex 用的不要把 ANTHROPIC_BASE_URL 之类的变量套过来那套是 Claude Code 的两边混填只会得到一堆看不懂的 404。2.3 Key 的两种放法env_key 还是 auth.json上面 config.toml 里写了 env_key TAOTOKEN_API_KEY那就得让这个环境变量真的存在。在启动 Codex 的同一个 shell 里导一次export TAOTOKEN_API_KEYYOUR_API_KEY codex喜欢写死配置的话把 env_key 换成你系统里已有的变量名也一样改哪儿就在哪儿 export两处必须一致。另一条路是把凭据交给 Codex 自己的凭据文件 ~/.codex/auth.json字段名跟着你当前 Codex 版本走写完记得回头确认 config.toml 里没有留着指向另一个变量名的 env_key——两个来源同时存在时哪个生效取决于版本排查起来很费劲。不管走哪条路base_url 都保持 https://taotoken.net/api 这一个值。落地页那个地址是给人点的用来注册、看模型广场、看用量填进工具里只会让请求打到网页上。2.4 启动后先问一条只涉及枚举的问题配置改完别直接上业务代码先发一条极短的问题试水比如让它列出 Qt::CursorShape 里所有以 Size 开头的枚举并说明各自含义。能正常返回说明 Key、base_url、模型 ID 三件套都对了返回 401 或 404先回 4.3 那节看是不是地址写歪了。这一步花不了半分钟却能把「配置问题」和「代码问题」提前分开后面调试形状时就不会疑神疑鬼。3. 把 Cursor 类贴给 Codex让它对着 enum Qt::CursorShape 逐条核3.1 贴代码的粒度整段类比单行更有效只贴一行 setCursor(Qt::SplitHCursor) 去问「这个对不对」模型只能给你教科书答案。把整个 Cursor 类连同槽函数名一起贴过去它才能看出命名和语义之间的错位哪个槽名字里的方向词和枚举的方向词打架哪个槽干脆用错了系列比如本该用 Split 却写了 Size。贴的时候顺手带上你的 Qt 版本5.15 和 6.x 的枚举集合不一样6 里多了 DragCopy、DragMove、DragLink 这几个拖拽专用形状版本说清楚回答才不会跑偏。3.2 提问模板要四列表不要散文散文化的回答读起来舒服但没法拿去改代码。直接用下面这套要求逼它输出可对照的结构下面是我项目里 Cursor 类的全部槽函数Qt 版本是 6.x。 请对照 enum Qt::CursorShape 输出一张四列表 槽函数名 | 我写的枚举 | 这个枚举的真实形状 | 建议用在什么交互上。 另外单独列一节指出所有「槽函数名暗示的方向与枚举实际含义不一致」的条目 每条给出修正建议但不要改动我的函数名只指出 setCursor 参数是否有误。 如果有枚举在你的知识里存在平台差异也在那一行备注出来。这一问下来SplitHCursor 和 SizeHorCursor 谁管左右分栏会当场写清楚WhatsThisCursor 的样子也会被描述成「箭头加问号」而不是一个孤零零的问号。把它给的表格和原文那十九个槽函数并排放在编辑器两栏改起来就是纯粹的对照工作。3.3 再让它生成一个本地可跑的光标自检窗口文字对照只能解决命名解决不了「我眼睛看到的到底是不是它」。可以让 Codex 生成一个极小的自检窗口列表里列出十九个槽函数鼠标滑到哪一行整个窗口的光标就切成那一行的形状。这样名字和形状出现在同一条视线里错位一眼就能看出来。#include QApplication #include QListWidget #include QVBoxLayout int main(int argc, char **argv) { QApplication app(argc, argv); struct Row { const char *slot; Qt::CursorShape shape; }; const Row rows[] { {slotArrow, Qt::ArrowCursor}, {slotUpArrow, Qt::UpArrowCursor}, {slotCross, Qt::CrossCursor}, {slotWait, Qt::WaitCursor}, {slotIBeam, Qt::IBeamCursor}, {slotSizeV, Qt::SizeVerCursor}, {slotSizeH, Qt::SizeHorCursor}, {slotSizeBDiag, Qt::SizeBDiagCursor}, {slotSizeFDiag, Qt::SizeFDiagCursor}, {slotSizeAll, Qt::SizeAllCursor}, {slotBlank, Qt::BlankCursor}, {slotSplitV, Qt::SplitVCursor}, {slotSplitH, Qt::SplitHCursor}, {slotPointingHand, Qt::PointingHandCursor}, {slotForbidden, Qt::ForbiddenCursor}, {slotWhatsThis, Qt::WhatsThisCursor}, {slotBusy, Qt::BusyCursor}, {slotOpenHand, Qt::OpenHandCursor}, {slotClosedHand, Qt::ClosedHandCursor}, }; QWidget w; auto *layout new QVBoxLayout(w); auto *list new QListWidget(w); for (const Row r : rows) { auto *item new QListWidgetItem( QString(%1 - %2).arg(r.slot).arg(int(r.shape)), list); item-setData(Qt::UserRole, int(r.shape)); } // 鼠标进入哪一行就整窗切换成那一行的形状 // 名字和形状同屏出现对不上的那几行会非常显眼。 QObject::connect(list, QListWidget::currentItemChanged, [](QListWidgetItem *cur, QListWidgetItem *) { if (!cur) return; w.setCursor(static_castQt::CursorShape( cur-data(Qt::UserRole).toInt())); }); layout-addWidget(list); w.resize(420, 560); w.show(); return app.exec(); }上面这段是骨架具体样式、字体、是否加「恢复正常光标」按钮都可以让 Codex 在你贴过去的原文 Cursor 类基础上补。它负责写你负责跑。3.4 编译与运行放在你本地结果贴回对话Codex 生成的是代码不是执行结果。编译、运行、把鼠标滑过十九行、看哪一行显示成箭头——这些动作全部在你自己的开发机上完成。模型看不到你的屏幕也连不上你的 Qt 环境它只能根据你贴回去的信息继续判断。所以流程是闭合的Codex 生成自检窗口 → 你本地用 qmake 或 CMake 编译运行 → 发现 slotSplitH 那一行显示的是上下箭头 → 把这一行截图描述或把行号贴回对话 → 它再告诉你这里应该换成 SplitVCursor 还是核对主题。一轮下来十九个槽函数里有疑问的那两三个基本就定位完了。4. 形状还是不对时的排查顺序4.1 光标回落成箭头先查 overrideCursor 栈自检窗口里明明写了 BlankCursor鼠标却还在或者整窗始终是普通箭头八成不是枚举写错而是有东西盖在上面。QApplication::setOverrideCursor 是压栈的某个地方压进去没配对 restore后面所有 setCursor 都会被它盖掉。先在代码里全局搜一遍 setOverrideCursor 和 restoreOverrideCursor确认压栈次数能对上。如果项目用了自定义样式表也顺手看一下控件自身的 cursor 属性。父控件 setCursor 之后子控件如果又被样式表设过 cursor最终生效的是子控件那一份这跟枚举对不对没关系。4.2 同一枚举在不同平台长得不一样Qt 只是把形状编号交给平台去画真正画出来的是系统主题或 Qt 的内置风格。结果就是UpArrowCursor 在不少现代主题里和 ArrowCursor 几乎没区别WhatsThisCursor 有的画成带问号的箭头有的画成纯问号SplitHCursor 的细条粗细也各不一样。你在这台机器上排好的对照表换到同事的 Linux 桌面上可能有两条对不上。做验证时以你实际交付的目标平台为准。跨平台项目里别用形状本身做逻辑判断形状只影响观感真正的交互判定能不能分栏、能不能拖拽还是靠控件自己的状态和事件处理。4.3 base_url 写成 /v1 或把落地页地址填进工具如果 Codex 连对话都发不出去先看两个地址有没有混。填进工具的一律是 https://taotoken.net/api末尾不加 /v1带 /v1 或者多带一截路径通常会得到 404 或者模型找不到。另一种错是把浏览器里那个落地页地址复制进 base_url那是给页面用的请求打到网页上自然也不通。还有一个更隐蔽的坑base_url 和 env_key 之间多写了个空格或者 TOML 里该加引号的字符串没加Codex 启动时会直接说配置解析失败而不是给你一个网络错误。看到解析类报错先看语法再过地址。4.4 回控制台确认这次对话记上了账排到这一步如果你已经能正常问问题只是不确定请求有没有真的走通就回 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 看一眼控制台。刚才那几轮让它核枚举的对话如果都出现在记录里说明 Key、模型 ID、base_url 三段全都对上了剩下的就纯粹是 Qt 那边形状的事不用再回头怀疑通道。记录里没有对应条目通常是 Key 用错了项目、或者导出环境变量的 shell 和启动 Codex 的 shell 不是同一个——后者特别常见新开一个终端窗口就忘了再 export 一次。5. 对照表做完之后留在项目里的东西5.1 把核对结果写进注释和常量表十九个槽函数挨个核完之后别让这份结果只留在聊天记录里。最省事的做法是把它变成项目里的一张常量表每个槽函数旁边加一行注释写清这个枚举真实长什么样、用在什么交互上、在哪个平台可能退化成箭头。下一次有人问「SplitHCursor 是左右还是上下」答案就在代码里不用再翻文档。顺手也可以把自检窗口留成项目里的一个 debug 小程序加个 CMake 的 target 就行。换 Qt 版本、换主题、上新平台的时候跑一次五分钟内能确认十九个形状有没有悄悄变样。5.2 下一步模型对话、Coding Plan 与 Key 管理如果你只是偶尔核一次枚举用 TaoToken 模型对话 直接发那段 Cursor 类过去就够了不用配任何文件。要是打算让 Codex 长期待在编辑器旁边帮你读 Qt 代码、翻文档、写自检小程序可以看看 Coding Plan 的额度是否够用再决定要不要把这次的 Key 单独归类。Key 本身建议按用途分开建Qt 项目一把、其他实验一把出问题时好定位是谁在调用也能随时单独停掉。控制台 API Keys 页面里能看到每把 Key 的状态创建和停用都在同一个地方。最后留一句提醒SplitHCursor 那个坑不是记性问题是命名问题。槽函数名按「槽函数名 | 枚举 | 形状 | 场景」当成表来维护之后换谁来接手都不用重新猜一遍——光标由 Qt 的 setCursor 决定你的表只负责说清楚哪个枚举对应屏幕上的哪个样子配好的通道只负责让你随时能把这段代码贴过去问。