Python Qt5 同时运行两个方法
我有一个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"
相关问题:
1 个回答
0
在这里,我建议使用 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): #main process will execute this in the main thread when it gets the signal from the recording thread.
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.
^注意:代码未经测试,请阅读以了解变化和理解。