KDE Plasma菜单(EQMenu分支)集成TTS服务错误排查求助
我来帮你梳理下代码里的几个关键问题,这些应该就是导致TTS功能异常的核心原因:
1. QML中TTS调用时机完全错误
你在Label组件的顶层直接写了Tools.tospeak(model.display.toString());,这会导致每个菜单项在初始化渲染的时候就自动触发朗读——也就是说,菜单加载完成后会一口气把所有菜单项的名称都读一遍,完全不是你预期的“交互时朗读”的效果。
修复方案:
删掉Label里的这句调用,把TTS触发逻辑移到MouseArea的交互事件里,比如鼠标悬停或者点击时触发:
MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true // 鼠标悬停到菜单项时朗读名称 onEntered: { Tools.tospeak(label.text.toString()); } // 可选:点击菜单项时再次朗读 onClicked: { Tools.tospeak(label.text.toString()); } }
2. 拖拽事件中的TTS调用存在空值崩溃与频繁触发问题
在onDragMove事件里,你直接调用Tools.tospeak(item.itemIndex.toString()),这里有两个严重问题:
- 当拖拽到没有菜单项的空白区域时,
item会是null,此时访问item.itemIndex会直接抛出错误,导致整个菜单的拖拽功能崩溃; onDragMove事件会在拖拽过程中高频触发(每帧都可能触发),这会导致TTS快速连续朗读索引数字,体验极差。
修复方案:
先判断item是否存在,同时改用朗读目标项的名称而非索引,再加个定时器限制触发频率:
// 先在ItemGridView.qml里定义一个定时器,用于限制TTS触发频率 Timer { id: ttsTimer interval: 1000 // 1秒内只允许触发一次 running: false repeat: false } // 修改onDragMove逻辑 onDragMove: { if (!dragEnabled || gridView.animating) { return; } var cPos = mapToItem(gridView.contentItem, event.x, event.y); var item = gridView.itemAt(cPos.x, cPos.y); if (item && item != kicker.dragSource && kicker.dragSource && kicker.dragSource.parent == gridView.contentItem) { item.GridView.view.model.moveRow(dragSource.itemIndex, item.itemIndex); // 先判断item和对应的Label存在,再触发朗读 if (item && item.label && !ttsTimer.running) { Tools.tospeak(item.label.text.toString()); ttsTimer.start(); } } }
3. Node.js exec命令的参数格式错误
在tools.js的tospeak函数里,你直接把文本拼接到命令后面:process.exec('/etc/alternatives/tts'+TextToSpeech,...)。如果要朗读的文本包含空格(比如"Firefox Browser"),这条命令会被解析成/etc/alternatives/tts Firefox Browser——TTS软件会把Firefox和Browser当成两个独立参数,而不是一个完整的朗读文本,自然无法正常工作。
修复方案:
用单引号包裹朗读文本,同时转义文本里的单引号避免破坏命令结构:
function tospeak(TextToSpeech) { var process = require('child_process'); // 转义文本中的单引号,并用单引号包裹整个文本 var safeText = TextToSpeech.replace(/'/g, "\\'"); var cmd = `/etc/alternatives/tts '${safeText}'`; process.exec(cmd, function (err, stdout, stderr) { if (err) { console.log("\n" + stderr); } else { console.log(stdout); } }); }
把以上三个修复点都应用后,你的TTS朗读功能应该就能按照预期工作了:鼠标悬停菜单项时朗读名称,拖拽时也能稳定朗读目标项的名称,不会出现崩溃或混乱朗读的情况。
内容的提问来源于stack exchange,提问作者Paul WOISARD

