Hi guys I want the user to choose the motor speed before going into step. So, in the first class, I made the first window which asked for the motor speed and another one is the recording and predicting process. In the recording process, I want to collect the WAV file as future data and use the motor speed as a file name. But I cannot pass the self.RPM value from one class to another. This is some part of the code.
class Ui_Form(object):
def setupUi(self, Form):
#The rest of the code
def retranslateUi(self, Form):
#The rest of the code
def start_click(self):
print('Start button click')
_translate = QtCore.QCoreApplication.translate
self.label.setText(_translate("Form", "<html><head/><body><p align=\"center\"><span style=\" color:#000000;\">Recording</span></p></body></html>"))
app.processEvents()
time.sleep(1)
count = 0
round = 0
for i in range(3):
round = i + 1
text = "Round " + str(round) + "/3"
self.label.setText(text)
app.processEvents()
print(text)
#Recording
now = datetime.now()
day = now.strftime("%d")
month = now.strftime("%m")
year = now.strftime("%y")
hour = now.strftime("%H")
minute = now.strftime("%M")
second = now.strftime("%S")
print(day,"/",month,"/",year,hour,":",minute,":",second)
CHUNK = 1024 #The number of frames in the buffer
FORMAT = pyaudio.paInt16
CHANNELS = 1 #Each frame will have 2 samples
RATE = 44100 #The number of samples collected per second or we can called sample rate
RECORD_SECONDS = 2 #Duration of recording
WAVE_OUTPUT_FILENAME = f"Data2/Test/{day}{month}{year}_{hour}{minute}{second}.wav" <--- I want to add RPM value here
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK) #read audio data from the stream
frames.append(data)
print("* done recording")
self.label.setText(_translate("Form", "<html><head/><body><p align=\"center\"><span style=\" color:#000000;\">Done Recording</span></p></body></html>"))
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') # 'rb' read only, 'wb' write only
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames)) #
wf.close()
#The rest of the code
class Ui_Form2(object):
def openWindow(self):
self.window = QtWidgets.QWidget()
self.ui = Ui_Form()
self.ui.setupUi(self.window)
self.window.show()
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(422, 202)
Form.setFixedSize(422, 202)
self.pushButton = QtWidgets.QPushButton(Form, clicked = lambda: self.openWindow())
self.pushButton.setGeometry(QtCore.QRect(10, 120, 121, 71))
font = QtGui.QFont()
font.setPointSize(15)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(Form, clicked = lambda: self.openWindow())
self.pushButton_2.setGeometry(QtCore.QRect(150, 120, 121, 71))
font = QtGui.QFont()
font.setPointSize(15)
self.pushButton_2.setFont(font)
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_3 = QtWidgets.QPushButton(Form, clicked = lambda: self.openWindow())
self.pushButton_3.setGeometry(QtCore.QRect(290, 120, 121, 71))
font = QtGui.QFont()
font.setPointSize(15)
self.pushButton_3.setFont(font)
self.pushButton_3.setObjectName("pushButton_3")
self.label = QtWidgets.QLabel(Form)
self.label.setGeometry(QtCore.QRect(70, 20, 281, 81))
self.label.setFrameShape(QtWidgets.QFrame.WinPanel)
self.label.setFrameShadow(QtWidgets.QFrame.Sunken)
self.label.setObjectName("label")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.pushButton.setText(_translate("Form", "1300 RPM"))
self.pushButton.clicked.connect(lambda: self.rpm_button_clicked(self.pushButton.text()))
self.pushButton_2.setText(_translate("Form", "1500 RPM"))
self.pushButton_2.clicked.connect(lambda: self.rpm_button_clicked(self.pushButton_2.text()))
self.pushButton_3.setText(_translate("Form", "1800 RPM"))
self.pushButton_3.clicked.connect(lambda: self.rpm_button_clicked(self.pushButton_3.text()))
self.label.setText(_translate("Form", "<html><head/><body><p align=\"center\"><span style=\" font-size:18pt; font-weight:600;\">RPM Selection</span></p></body></html>"))
def rpm_button_clicked(self, button_text):
rpm_values = {'1300 RPM': 1300, '1500 RPM': 1500, '1800 RPM': 1800}
self.RPM = rpm_values[button_text]
print(self.RPM)
if __name__ == "__main__":
Form = QtWidgets.QWidget()
ui = Ui_Form2()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
I want to use the value from one class on another or anyone got a better idea than this can suggest
Either you use signal/slots (a Qt mechanism for observer/observable), or do it the Python object way.
In the first case, you need to declare a signal in the class (A) where you select the motor speed, then in your other class (B) you connect
the signal for your instance of A to a slot in your B instance.
When doing Qt graphical applications, I prefer to use toy examples to better understand how it works.
Here is what I mean :
import sys
from typing import Optional
from PyQt5 import QtWidgets, QtCore
class WindowA(QtWidgets.QMainWindow):
def __init__(self):
super().__init__(parent=None)
self.setWindowTitle("A")
central_widget = QtWidgets.QPushButton("Choose")
central_widget.clicked.connect(self.on_button_Choose_pushed)
self.setCentralWidget(central_widget)
def on_button_Choose_pushed(self, checked: bool) -> None:
print("'choose' button clicked")
file_dialog = QtWidgets.QFileDialog(parent=self)
if file_dialog.exec():
print("a file was selected")
filenames = file_dialog.selectedFiles()
print(filenames)
assert len(filenames) == 1
print("emitting the signal")
self.file_selected.emit(filenames[0])
else:
print("no file selected")
file_selected = QtCore.pyqtSignal(str)
class WindowB(QtWidgets.QMainWindow):
def __init__(self, window_a: WindowA):
super().__init__(parent=None)
self.setWindowTitle("B")
self.filename: Optional[str] = None
central_widget = QtWidgets.QPushButton("Do something")
central_widget.clicked.connect(self.on_button_Do_Something_pushed)
self.setCentralWidget(central_widget)
window_a.file_selected.connect(self.on_file_selected)
def on_button_Do_Something_pushed(self, checked: bool) -> None:
print("'do something' button clicked")
print("filename is :", repr(self.filename))
# do something
@QtCore.pyqtSlot(str)
def on_file_selected(self, filename: str) -> None:
print("'file selected' slot received a signal, filename =", repr(filename))
self.filename = filename
def main() -> int:
app = QtWidgets.QApplication([])
window_a = WindowA()
window_a.setVisible(True)
window_b = WindowB(window_a) # passing A to B
window_b.setVisible(True)
return app.exec()
if __name__ == "__main__":
sys.exit(main())
(the 2 windows may appear one on top of the other)
Click the button B "do something" button, then the A button "choose" and select a file, then click B again. You will get :
'do something' button clicked
filename is : None
'choose' button clicked
a file was selected
['/home/stack_overflow/log.log']
emitting the signal
'file selected' slot received a signal, filename = '/home/stack_overflow/log.log'
'do something' button clicked
filename is : '/home/stack_overflow/log.log'
This is the over way around. You need your A to know of B, so that when a file is selected from A, it sets the variable for B.
import sys
from typing import Optional
from PyQt5 import QtWidgets, QtCore
class WindowA(QtWidgets.QMainWindow):
def __init__(self, window_b: "WindowB"):
super().__init__(parent=None)
self.setWindowTitle("A")
self._window_b = window_b # save it for later
central_widget = QtWidgets.QPushButton("Choose")
central_widget.clicked.connect(self.on_button_Choose_pushed)
self.setCentralWidget(central_widget)
def on_button_Choose_pushed(self, checked: bool) -> None:
print("'choose' button clicked")
file_dialog = QtWidgets.QFileDialog(parent=self)
if file_dialog.exec():
print("a file was selected")
filenames = file_dialog.selectedFiles()
print(filenames)
assert len(filenames) == 1
print("setting the variable of B")
self._window_b.filename = filenames[0]
else:
print("no file selected")
class WindowB(QtWidgets.QMainWindow):
def __init__(self):
super().__init__(parent=None)
self.setWindowTitle("B")
self.filename: Optional[str] = None
central_widget = QtWidgets.QPushButton("Do something")
central_widget.clicked.connect(self.on_button_Do_Something_pushed)
self.setCentralWidget(central_widget)
def on_button_Do_Something_pushed(self, checked: bool) -> None:
print("'do something' button clicked")
print("filename is :", self.filename)
# do something
def main() -> int:
app = QtWidgets.QApplication([])
window_b = WindowB()
window_b.setVisible(True)
window_a = WindowA(window_b) # passing B to A
window_a.setVisible(True)
return app.exec()
if __name__ == "__main__":
sys.exit(main())
This way, A sets the variable of B.
If you understand these 2 techniques, you can change the structure. You can have a class containing the data, and the other being given a reference to the first class.
Or you could make the code that instantiate both of them (here is is the main()
function) connect the signal from the first to the slot of the second.