You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5程序调用setTextCursor()后运行一段时间自动崩溃求助

问题分析与解决方案

崩溃原因

PyQt的GUI组件完全不是线程安全的,所有对QTextEdit这类控件的直接操作必须在主线程中执行。你的VoiceWorker是子线程,但在run()方法里直接调用txtbox.textCursor()、txtbox.setTextCursor(cursor)等GUI操作,会导致主线程和子线程同时修改控件的内部状态,引发内存数据损坏,最终出现段错误(Linux)或无预警崩溃(Windows)。

修复方案

将所有GUI相关操作移到主线程中,子线程只负责语音识别并发送识别结果,通过信号触发主线程处理文本插入和光标定位。

1. 修改VoiceWorker类(移除所有GUI操作)

class VoiceWorker(QtCore.QThread):
    textChanged = QtCore.pyqtSignal(str)
    sig_started = QtCore.pyqtSignal()

    def run(self) -> None:
        self.sig_started.emit()
        mic = PyAudio()

        stream = mic.open(format=FORMAT, channels=CHANNELS,
                          rate=RATE, input=True, frames_per_buffer=CHUNK)

        while not self.stopped:
            try:
                data = stream.read(4096, exception_on_overflow=False)
                if recognizer.AcceptWaveform(data):
                    text = recognizer.Result()
                    speech = text[14:-3] + " "
                    self.textChanged.emit(speech)
            except Exception as e:
                print(f"\n {e} \n")
                break

2. 主线程中定义槽函数处理GUI逻辑

def handle_speech_text(speech):
    # 保存当前光标位置
    cursor = txtbox.textCursor()
    current_pos = cursor.position()
    
    # 插入识别后的文本
    txtbox.insertPlainText(speech)
    
    # 恢复光标到原位置(如果需要保持用户编辑的位置)
    cursor.setPosition(current_pos)
    txtbox.setTextCursor(cursor)
    
    # 如果需求是插入文本后光标移到末尾,替换上面两行:
    # cursor.movePosition(cursor.End)
    # txtbox.setTextCursor(cursor)

# 重新连接信号与槽
voice_thread = VoiceWorker()
voice_thread.textChanged.connect(handle_speech_text)

额外注意事项

  • 确保stopped变量的线程安全性:如果是普通布尔值,建议改用QtCore.QAtomicInt或加锁保护,避免线程间的竞态条件。
  • 语音识别的异常捕获逻辑可以保留,但不要在子线程中处理GUI相关的错误提示,同样通过信号传递到主线程处理。

内容的提问来源于stack exchange,提问作者Ankit Tiwari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:01:21