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
相关产品推荐
相关产品推荐

