我有一个 Qt 计时器,我想在录制时倒计时(使用声音设备包),我将附上下面的内容(我知道它离正确的东西还很远)。我一直在阅读有关多处理和线程的内容,我认为超时允许运行其他函数,但似乎记录函数在写入文件时保持不变,所以我有点困惑。任何建议都有帮助,谢谢!
class CountDown(QWidget):
def __init__(self, name, index):
super().__init__()
self.initUI(name, index)
def initUI(self, name, index):
self.setWindowTitle("Timer for "+name)
layout = QVBoxLayout()
self.setLayout(layout)
self.time_label = QLabel(self)
layout.addWidget(self.time_label)
self.setFixedWidth(500)
self.setFixedHeight(500)
# Create a QTimer that updates the time label every second
timer = QTimer(self)
self.current_time = 11
timer.timeout.connect(lambda: self.update_time())
timer.start(1000) # Update every 1000 milliseconds (1 second)
print("START RECORDING" + name)
self.record(index, name)
self.show()
#need to update time and record simultaneously
def update_time(self):
# Get the current time and set it on the label
if(self.current_time==0):
self.close()
self.current_time-=1
print(self.current_time)
self.time_label.setText(f"Current Time: {self.current_time}")
#Takes in name selected from GUI and finds its index to use for audio device-> records for 1 second
def record(self, index, name):
#1 Microphone (USB Lavalier Microp, MME (2 in, 0 out)
# Sample rate:
fs = 44100
# Duration of recording:
seconds = 5
myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=1, device=index)
# Wait until recording is finished:
sd.wait()
print("STOPPED RECORDING" + name)
# Save as WAV file:
write(name+".wav", fs, myrecording)
return name+".wav"
我会在这里找到
threading
。并非所有 Qt 都是线程安全的,但如果您的录制线程不直接与 GUI 交互,则几乎不需要任何工作:
...
print("START RECORDING" + name)
self.recording_thread = threading.Thread(target = self.record, args = (index, name))
self.recording_thread.start()
self.show()
...
可以从线程发出信号,因此您可以创建一个可由线程触发的槽(回调)。如果您开始尝试从线程中执行类似 label.setText()
之类的操作,那么您就会遇到麻烦。
from PyQt6.QtCore import pyqtSignal, pyqtSlot #custom signals and slots
from PyQt6.QtWidgets import ...
from PyQt6 ...
import threading
class CountDown(QWidget):
recording_done = pyqtSignal() #define a signal our thread will emit when done
def __init__(self, name, index):
super().__init__()
self.initUI(name, index)
def initUI(self, name, index):
self.setWindowTitle("Timer for "+name)
layout = QVBoxLayout()
self.setLayout(layout)
self.time_label = QLabel(self)
layout.addWidget(self.time_label)
self.setFixedWidth(500)
self.setFixedHeight(500)
self.setLayout(layout) #explicitly set the layout of the main widget rather than rely on parent-child relationship of label
# Create a QTimer that updates the time label every second
self.timer = QTimer(self)
self.current_time = 11
self.timer.timeout.connect(self.update_time) #you shouldn't need a lambda here, just pass the method
self.timer.start(1000) # Update every 1000 milliseconds (1 second)
print("START RECORDING" + name)
self.recording_thread = threading.Thread(target=self.record, args=(index, name))
self.recording_thread.start()
self.recording_done.connect(self.on_recording_done)
self.show()
#need to update time and record simultaneously
@pyqtSlot()
def update_time(self):
# Get the current time and set it on the label
if(self.current_time==0):
self.timer.stop()
self.current_time-=1
print(self.current_time)
self.time_label.setText(f"Current Time: {self.current_time}")
@pyqtSlot()
def on_recording_done(self):
if self.timer.isActive():
self.timer.stop()
self.time_label.setText("recording done")
#Takes in name selected from GUI and finds its index to use for audio device-> records for 1 second
def record(self, index, name):
#1 Microphone (USB Lavalier Microp, MME (2 in, 0 out)
fs = 44100
seconds = 5
myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=1, device=index)
sd.wait()
print("STOPPED RECORDING" + name)
write(name+".wav", fs, myrecording)
self.recording_done.emit() #signal the Qt event loop in the main process
#return name+".wav" #you can't get the return value from a thread. If you need to return some value, send it via signals and slots, or mutate a shared variable.
^注意:代码未经测试..阅读更改和理解。