def __init__(self, startupDelay: float) -> None: threading.Thread.__init__(self) self.startupDelay = startupDelay self.finish = False if isMac and qtminor > 12: # trigger permission prompt from PyQt5.QtMultimedia import QAudioDeviceInfo QAudioDeviceInfo.defaultInputDevice()
def __init__(self, output_path: str, startup_delay: float) -> None: threading.Thread.__init__(self) self._output_path = output_path self._startup_delay = startup_delay self.finish = False # though we're using pyaudio here, we rely on Qt to trigger # the permission prompt on macOS if isMac and qtminor > 12: from PyQt5.QtMultimedia import QAudioDeviceInfo QAudioDeviceInfo.defaultInputDevice()
def __init__(self, output_path: str, mw: aqt.AnkiQt, parent: QWidget) -> None: super().__init__(output_path) self.mw = mw self._parent = parent from PyQt5.QtMultimedia import QAudioDeviceInfo, QAudioFormat, QAudioInput format = QAudioFormat() format.setChannelCount(1) format.setSampleRate(44100) format.setSampleSize(16) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) format.setSampleType(QAudioFormat.SignedInt) device = QAudioDeviceInfo.defaultInputDevice() if not device.isFormatSupported(format): format = device.nearestFormat(format) print("format changed") print("channels", format.channelCount()) print("rate", format.sampleRate()) print("size", format.sampleSize()) self._format = format self._audio_input = QAudioInput(device, format, parent)
def initAUD(self): # info = QAudioDeviceInfo.defaultInputDevice() if (~info.isFormatSupported(self.audio.format)): # print("警告,设置的默认音频格式并不支持,将尝试采用最相近的支持格式") # 不知道这里面有什么神改动? self.audio.format = info.nearestFormat(self.audio.format) # update_interval = 160 self.audioRecorder = QAudioInput(self.audio.format) self.audioRecorder.setNotifyInterval(update_interval) #按毫秒ms 类似于QTimer的作用 self.audioRecorder.notify.connect(self.processAudioData) self.audioRecorder_TD = QThread() self.audioRecorder.moveToThread(self.audioRecorder_TD) self.audioRecorder_TD.started.connect(self.startRecord) self.audioRecorder.stateChanged.connect(self.recordStopped) # 总结来说线程只是一个容器,里面执行的循环要是没法结束,强制退出也不好操作 # 所以还是好好写好任务流然后发送信号比较合理 self.audioPlayer = QAudioOutput(self.audio.format) self.audioPlayer.setNotifyInterval(update_interval) self.audioPlayer.notify.connect(self.processAudioData) self.audioPlayer_TD = QThread() self.audioPlayer.moveToThread(self.audioPlayer_TD) self.audioPlayer_TD.started.connect(self.startPlay) self.audioPlayer.stateChanged.connect(self.playStopped)
def __init__(self): super().__init__() self.m_chart = QChart() chart_view = QChartView(self.m_chart) chart_view.setMinimumSize(800, 600) self.m_series = QLineSeries() self.m_chart.addSeries(self.m_series) axis_x = QValueAxis() axis_x.setRange(0, 2000) axis_x.setLabelFormat("%g") axis_x.setTitleText("Samples") axis_y = QValueAxis() axis_y.setRange(-1, 1) axis_y.setTitleText("Audio level") self.m_chart.setAxisX(axis_x, self.m_series) self.m_chart.setAxisY(axis_y, self.m_series) self.m_chart.setTitle("Data from the microphone") main_layout = QVBoxLayout() main_layout.addWidget(chart_view) self.setLayout(main_layout) format_audio = QAudioFormat() format_audio.setSampleRate(48000) format_audio.setChannelCount(1) format_audio.setSampleSize(8) format_audio.setCodec("audio/pcm") format_audio.setByteOrder(QAudioFormat.LittleEndian) format_audio.setSampleType(QAudioFormat.UnSignedInt) input_devices = QAudioDeviceInfo.defaultInputDevice() self.m_audio_input = QAudioInput(input_devices, format_audio) self.m_device = XYSeriesIODevice(self.m_series) self.m_device.open(QIODevice.WriteOnly) self.m_audio_input.start(self.m_device) self.init_ui()
def _uic(self): """ set up our layout which consists of: Big Honkin' Label [input combobox] [output combobox] [volume slider] [x] Mute hooking put the signals to useful slots is the job of __init__. Here just make the layout. """ self.setMinimumWidth(400) # Create the big honkin' label and logo icon_pixmap = QPixmap(":/icon.png").scaledToWidth(64) icon_label = QLabel() icon_label.setPixmap(icon_pixmap) text_label = QLabel("Sidetone!") hb_label = QHBoxLayout() hb_label.addStretch(1) hb_label.addWidget(icon_label, 0) hb_label.addWidget(text_label, 0) hb_label.addStretch(1) # Create a list of QAudioInfo objects for inputs self.input_info_list = QAudioDeviceInfo.availableDevices(QAudio.AudioInput) if 0 == len(self.input_info_list): self.input_info_list = [QAudioDeviceInfo.defaultInputDevice()] # Create a combo box and populate it with names of inputs self.cb_inputs = QComboBox() self.cb_inputs.addItems([audio_info.deviceName() for audio_info in self.input_info_list]) # Create a list of QAudioInfo objects for outputs self.otput_info_list = QAudioDeviceInfo.availableDevices(QAudio.AudioOutput) if 0 == len(self.otput_info_list): self.otput_info_list = [QAudioDeviceInfo.defaultOutputDevice()] self.status_bar.showMessage( "{} inputs {} otputs".format(len(self.input_info_list), len(self.otput_info_list)), 2000 ) # Create a combo box and populate it with names of outputs self.cb_otputs = QComboBox() self.cb_otputs.addItems([audio_info.deviceName() for audio_info in self.otput_info_list]) # Lay those two out aligned to the outside hb_combos = QHBoxLayout() hb_combos.addWidget(self.cb_inputs, 1) hb_combos.addStretch(0) hb_combos.addWidget(self.cb_otputs, 1) # Create a volume slider from 0 to 100. self.volume = QSlider(Qt.Horizontal, self) self.volume.setMinimum(0) self.volume.setMaximum(100) self.volume.setTickInterval(10) self.volume.setTickPosition(QSlider.TicksBothSides) # Create a checkbox "Mute" self.mute = QCheckBox("Mute") # Put those together in a row squeezed in the center hb_volume = QHBoxLayout() hb_volume.addStretch(1) hb_volume.addWidget(self.volume, 1) hb_volume.addWidget(self.mute, 0) hb_volume.addStretch(1) # Stack all those up as this widget's layout vlayout = QVBoxLayout() vlayout.addLayout(hb_label) vlayout.addLayout(hb_combos) vlayout.addLayout(hb_volume) self.setLayout(vlayout)
def initUI(self): # main window/layout window = QWidget() layout = QVBoxLayout() # layout for audio device and sample rate selection deviceLayout = QHBoxLayout() # make audio device selection box and list of available devices self.deviceBox = QComboBox() defaultDeviceInfo = QAudioDeviceInfo.defaultInputDevice() self.availableDevices = [defaultDeviceInfo] self.availableDevices += QAudioDeviceInfo.availableDevices( QAudio.AudioInput) for device in self.availableDevices: self.deviceBox.addItem(device.deviceName()) # make sample rate label and combobox sRateLabel = QLabel("Sample rate:") sRateLabel.setAlignment(Qt.AlignRight) # user can choose between 44.1 and 48kHz (valid DetectorBank rates) self.sRateBox = QComboBox() self.sRateBox.addItem("44100") self.sRateBox.addItem("48000") self.sRateBox.setCurrentIndex(1) # add device and sr widgets to device layout deviceLayout.addWidget(self.deviceBox) deviceLayout.addWidget(sRateLabel) deviceLayout.addWidget(self.sRateBox) # add device layout to main layout layout.addLayout(deviceLayout) # DetectorBank parameters layout # two rows of three parameters # each param needs label and edit, # and a 'Start' button will be added at the bottom # so grid should be 3x6 detBankParamLayout = QGridLayout() # label and lineedit for each bandwidthLabel = QLabel("Bandwidth (cents):") dampingLabel = QLabel("Damping:") gainLabel = QLabel("Gain:") edoLabel = QLabel("EDO:") lwrLabel = QLabel("Lower note:") uprLabel = QLabel("Upper note:") self.bandwidthEdit = QLineEdit("0") self.dampingEdit = QLineEdit("0.0001") self.gainEdit = QLineEdit("25") self.edoEdit = QLineEdit("12") self.lwrEdit = QLineEdit("A1") self.uprEdit = QLineEdit("A7") # store all in lists detBankParamLabels = [bandwidthLabel, dampingLabel, gainLabel, edoLabel, lwrLabel, uprLabel] detBankParamEdits = [self.bandwidthEdit, self.dampingEdit, self.gainEdit, self.edoEdit, self.lwrEdit, self.uprEdit] # fill first two rows of grid with labels and edits row = 0 for row in range(2): widgetNum = 0 for i in range((row*3), (row*3)+3): detBankParamLayout.addWidget(detBankParamLabels[i], row, widgetNum) widgetNum += 1 detBankParamLayout.addWidget(detBankParamEdits[i], row, widgetNum) widgetNum += 1 # align labels to the right (next to the edit) for i in range(len(detBankParamLabels)): detBankParamLabels[i].setAlignment(Qt.AlignRight) # button to make DetectorBank and start visualisation row += 1 startButton = QPushButton("&Start!") detBankParamLayout.addWidget(startButton, row, 5) startButton.clicked.connect(self.start) # add grid of detbank params (and start button) to main layout layout.addLayout(detBankParamLayout) window.setLayout(layout) self.setCentralWidget(window) self.show()
def __init__(self): super().__init__() arguments = self.parseArguments() self.DEBUG = arguments.debug os.chdir(os.path.dirname(os.path.realpath(__file__))) self.MIN_WIDTH = 600 self.MIN_HEIGHT = 350 self.setMinimumWidth(self.MIN_WIDTH) self.setMinimumHeight(self.MIN_HEIGHT) self.ROOT_FOLDER = os.path.expanduser("~/.florodoro/") self.HISTORY_FILE_PATH = self.ROOT_FOLDER + "history" + ("" if not self.DEBUG else "-debug") + ".yaml" self.CONFIGURATION_FILE_PATH = self.ROOT_FOLDER + "config" + ("" if not self.DEBUG else "-debug") + ".yaml" self.history = History(self.HISTORY_FILE_PATH) self.SOUNDS_FOLDER = "sounds/" self.PLANTS_FOLDER = "plants/" self.IMAGE_FOLDER = "images/" self.TEXT_COLOR = self.palette().text().color() self.BREAK_COLOR = "#B37700" self.APP_NAME = "Florodoro" self.STUDY_ICON = qtawesome.icon('fa5s.book', color=self.TEXT_COLOR) self.BREAK_ICON = qtawesome.icon('fa5s.coffee', color=self.BREAK_COLOR) self.CONTINUE_ICON = qtawesome.icon('fa5s.play', color=self.TEXT_COLOR) self.PAUSE_ICON = qtawesome.icon('fa5s.pause', color=self.TEXT_COLOR) self.RESET_ICON = qtawesome.icon('fa5s.undo', color=self.TEXT_COLOR) self.PLANTS = [GreenTree, DoubleGreenTree, OrangeTree, CircularFlower] self.PLANT_NAMES = ["Spruce", "Double spruce", "Maple", "Flower"] self.WIDGET_SPACING = 10 self.MAX_TIME = 180 self.STEP = 5 self.INITIAL_TEXT = "Start!" self.menuBar = QMenuBar(self) self.presets_menu = self.menuBar.addMenu('&Presets') self.presets = { "Classic": (25, 5, 4), "Extended": (45, 12, 2), "Sitcomodoro": (65, 25, 1), } for name in self.presets: study_time, break_time, cycles = self.presets[name] self.presets_menu.addAction( QAction(f"{name} ({study_time} : {break_time} : {cycles})", self, triggered=partial(self.load_preset, study_time, break_time, cycles))) self.DEFAULT_PRESET = "Classic" self.options_menu = self.menuBar.addMenu('&Options') self.notify_menu = self.options_menu.addMenu("&Notify") self.sound_action = QAction("&Sound", self, checkable=True, checked=not self.DEBUG, triggered=lambda _: self.volume_slider.setDisabled( not self.sound_action.isChecked())) self.notify_menu.addAction(self.sound_action) # Default audio device self.audio_device = QAudioDeviceInfo.defaultInputDevice() # Create device menu self.audio_device_menu = self.notify_menu.addMenu("&Audio Devices") # For all sound devices, add a device check box to the device menu audio_devices = QAudioDeviceInfo.availableDevices(QAudio.AudioOutput) for device in audio_devices: device_name = device.deviceName() self.device_action = QAction(f"&{device_name}", self, checkable=True, checked=not self.DEBUG, triggered=partial(self.setAudioDevice, device)) # Create callback of some sort for clicking on the device in the menu self.audio_device_menu.addAction(self.device_action) self.volume_slider = QSlider(Qt.Horizontal, minimum=0, maximum=100, value=85) slider_action = QWidgetAction(self) slider_action.setDefaultWidget(SpacedQWidget(self.volume_slider)) self.notify_menu.addAction(slider_action) self.popup_action = QAction("&Pop-up", self, checkable=True, checked=True) self.notify_menu.addAction(self.popup_action) self.menuBar.addAction( QAction( "&Statistics", self, triggered=lambda: self.statistics.show() if self.statistics.isHidden() else self.statistics.hide() ) ) self.menuBar.addAction( QAction( "&About", self, triggered=lambda: QMessageBox.information( self, "About", "This application was created by Tomáš Sláma. It is heavily inspired by the Android app Forest, " "but with all of the plants generated procedurally. It's <a href='https://github.com/xiaoxiae/Florodoro'>open source</a> and licensed " "under MIT, so do as you please with the code and anything else related to the project.", ), ) ) self.plant_menu = self.options_menu.addMenu("&Plants") self.overstudy_action = QAction("Overstudy", self, checkable=True) self.options_menu.addAction(self.overstudy_action) self.plant_images = [] self.plant_checkboxes = [] # dynamically create widgets for each plant for plant, name in zip(self.PLANTS, self.PLANT_NAMES): self.plant_images.append(tempfile.NamedTemporaryFile(suffix=".svg")) tmp = plant() tmp.set_max_age(1) tmp.set_age(1) tmp.save(self.plant_images[-1].name, 200, 200) setattr(self.__class__, name, QAction(self, icon=QIcon(self.plant_images[-1].name), text=name, checkable=True, checked=True)) action = getattr(self.__class__, name) self.plant_menu.addAction(action) self.plant_checkboxes.append(action) # the current plant that we're growing # if set to none, no plant is growing self.plant = None self.menuBar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum) main_vertical_layout = QVBoxLayout(self) main_vertical_layout.setContentsMargins(0, 0, 0, 0) main_vertical_layout.setSpacing(0) main_vertical_layout.addWidget(self.menuBar) self.canvas = Canvas(self) self.statistics = Statistics(self.history) font = self.font() font.setPointSize(100) self.main_label = QLabel(self, alignment=Qt.AlignCenter) self.main_label.setFont(font) self.main_label.setText(self.INITIAL_TEXT) font.setPointSize(26) self.cycle_label = QLabel(self) self.cycle_label.setAlignment(Qt.AlignTop) self.cycle_label.setMargin(20) self.cycle_label.setFont(font) main_horizontal_layout = QHBoxLayout(self) self.study_time_spinbox = QSpinBox(self, prefix="Study for: ", suffix="min.", minimum=1, maximum=self.MAX_TIME, singleStep=self.STEP) self.break_time_spinbox = QSpinBox(self, prefix="Break for: ", suffix="min.", minimum=1, maximum=self.MAX_TIME, singleStep=self.STEP, styleSheet=f'color:{self.BREAK_COLOR};') self.cycles_spinbox = QSpinBox(self, prefix="Cycles: ", minimum=1, value=1) # keep track of remaining number of cycles and the starting number of cycles self.remaining_cycles = 0 self.total_cycles = 0 # whether we're currently studying self.is_study_ongoing = False # whether we notified the user already during overstudy self.already_notified_during_overstudy = False stacked_layout = QStackedLayout(self, stackingMode=QStackedLayout.StackAll) stacked_layout.addWidget(self.main_label) stacked_layout.addWidget(self.cycle_label) stacked_layout.addWidget(self.canvas) main_vertical_layout.addLayout(stacked_layout) self.setStyleSheet("") self.study_button = QPushButton(self, clicked=self.start, icon=self.STUDY_ICON) self.break_button = QPushButton(self, clicked=self.start_break, icon=self.BREAK_ICON) self.pause_button = QPushButton(self, clicked=self.toggle_pause, icon=self.PAUSE_ICON) self.reset_button = QPushButton(self, clicked=self.reset, icon=self.RESET_ICON) main_horizontal_layout.addWidget(self.study_time_spinbox) main_horizontal_layout.addWidget(self.break_time_spinbox) main_horizontal_layout.addWidget(self.cycles_spinbox) main_horizontal_layout.addWidget(self.study_button) main_horizontal_layout.addWidget(self.break_button) main_horizontal_layout.addWidget(self.pause_button) main_horizontal_layout.addWidget(self.reset_button) main_vertical_layout.addLayout(main_horizontal_layout) self.setLayout(main_vertical_layout) self.study_timer_frequency = 1 / 60 * 1000 self.study_timer = QTimer(self, interval=int(self.study_timer_frequency), timeout=self.decrease_remaining_time) self.player = QMediaPlayer(self) self.setWindowIcon(QIcon(self.IMAGE_FOLDER + "icon.svg")) self.setWindowTitle(self.APP_NAME) # set initial UI state self.reset() # a list of name, getter and setter things to load/save when the app opens/closes # also dynamically get settings for selecting/unselecting plants self.CONFIGURATION_ATTRIBUTES = [("study-time", self.study_time_spinbox.value, self.study_time_spinbox.setValue), ("break-time", self.break_time_spinbox.value, self.break_time_spinbox.setValue), ("cycles", self.cycles_spinbox.value, self.cycles_spinbox.setValue), ("sound", self.sound_action.isChecked, self.sound_action.setChecked), ("sound-volume", self.volume_slider.value, self.volume_slider.setValue), ("pop-ups", self.popup_action.isChecked, self.popup_action.setChecked), ("overstudy", self.overstudy_action.isChecked, self.overstudy_action.setChecked)] + \ [(name.lower(), getattr(self.__class__, name).isChecked, getattr(self.__class__, name).setChecked) for _, name in zip(self.PLANTS, self.PLANT_NAMES)] # load the default preset self.load_preset(*self.presets[self.DEFAULT_PRESET]) self.load_settings() self.show()
def _uic(self): ''' set up our layout which consists of: Big Honkin' Label [input combobox] [output combobox] [volume slider] [x] Mute hooking put the signals to useful slots is the job of __init__. Here just make the layout. ''' self.setMinimumWidth(400) # Create the big honkin' label and logo icon_pixmap = QPixmap(':/icon.png').scaledToWidth(64) icon_label = QLabel() icon_label.setPixmap(icon_pixmap) text_label = QLabel("Sidetone!") hb_label = QHBoxLayout() hb_label.addStretch(1) hb_label.addWidget(icon_label, 0) hb_label.addWidget(text_label, 0) hb_label.addStretch(1) # Create a list of QAudioInfo objects for inputs self.input_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioInput) if 0 == len(self.input_info_list): self.input_info_list = [QAudioDeviceInfo.defaultInputDevice()] # Create a combo box and populate it with names of inputs self.cb_inputs = QComboBox() self.cb_inputs.addItems( [audio_info.deviceName() for audio_info in self.input_info_list]) # Create a list of QAudioInfo objects for outputs self.otput_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioOutput) if 0 == len(self.otput_info_list): self.otput_info_list = [QAudioDeviceInfo.defaultOutputDevice()] self.status_bar.showMessage( '{} inputs {} otputs'.format(len(self.input_info_list), len(self.otput_info_list)), 2000) # Create a combo box and populate it with names of outputs self.cb_otputs = QComboBox() self.cb_otputs.addItems( [audio_info.deviceName() for audio_info in self.otput_info_list]) # Lay those two out aligned to the outside hb_combos = QHBoxLayout() hb_combos.addWidget(self.cb_inputs, 1) hb_combos.addStretch(0) hb_combos.addWidget(self.cb_otputs, 1) # Create a volume slider from 0 to 100. self.volume = QSlider(Qt.Horizontal, self) self.volume.setMinimum(0) self.volume.setMaximum(100) self.volume.setTickInterval(10) self.volume.setTickPosition(QSlider.TicksBothSides) # Create a checkbox "Mute" self.mute = QCheckBox('Mute') # Put those together in a row squeezed in the center hb_volume = QHBoxLayout() hb_volume.addStretch(1) hb_volume.addWidget(self.volume, 1) hb_volume.addWidget(self.mute, 0) hb_volume.addStretch(1) # Stack all those up as this widget's layout vlayout = QVBoxLayout() vlayout.addLayout(hb_label) vlayout.addLayout(hb_combos) vlayout.addLayout(hb_volume) self.setLayout(vlayout)
def _uic(self): ''' set up our layout which consists of: Big Honkin' Label [input combobox] [output combobox] [volume slider] [x] Mute Hooking the signals to useful slots is the job of __init__. Here just make the layout. ''' self.setMinimumWidth(400) # Create the big honkin' label and logo icon_pixmap = QPixmap(':/icon.png').scaledToWidth(64) icon_label = QLabel() icon_label.setPixmap(icon_pixmap) text_label = QLabel("Sidetone!") hb_label = QHBoxLayout() hb_label.addStretch(1) hb_label.addWidget(icon_label, 0) hb_label.addWidget(text_label, 0) hb_label.addStretch(1) # Create a list of QAudioInfo objects for inputs self.input_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioInput) if 0 == len(self.input_info_list): self.input_info_list = [QAudioDeviceInfo.defaultInputDevice()] # Make a list of the name-strings for those items. in_dev_names = [ audio_info.deviceName() for audio_info in self.input_info_list ] # Create a combo box and populate it with those names self.cb_inputs = QComboBox() self.cb_inputs.addItems(in_dev_names) # If the in_dev_name from the previous run is in the current list, # make it current, otherwise pick the first item. in_dev_name = self.settings.value('in_dev_name', 'unknown') if in_dev_name in in_dev_names: self.cb_inputs.setCurrentIndex(in_dev_names.index(in_dev_name)) else: self.cb_inputs.setCurrentIndex(0) # Create a list of QAudioInfo objects for outputs self.otput_info_list = QAudioDeviceInfo.availableDevices( QAudio.AudioOutput) if 0 == len(self.otput_info_list): self.otput_info_list = [QAudioDeviceInfo.defaultOutputDevice()] # Make a list of the name-strings of those things ot_dev_names = [ audio_info.deviceName() for audio_info in self.otput_info_list ] # Create a combo box and populate it with those names self.cb_otputs = QComboBox() self.cb_otputs.addItems(ot_dev_names) # If the ot_dev_name from the previous run is in the current list, # make it the current choice in the box. ot_dev_name = self.settings.value('ot_dev_name', 'unknown') if ot_dev_name in ot_dev_names: self.cb_otputs.setCurrentIndex(ot_dev_names.index(ot_dev_name)) else: self.cb_otputs.setCurrentIndex(0) #self.show_status( #'{} inputs {} otputs'.format(len(self.input_info_list),len(self.otput_info_list)) #) # Create a combo box and populate it with names of outputs # Lay those two out aligned to the outside hb_combos = QHBoxLayout() hb_combos.addWidget(self.cb_inputs, 1) hb_combos.addStretch(0) hb_combos.addWidget(self.cb_otputs, 1) # Create a volume slider from 0 to 100. self.volume = QSlider(Qt.Horizontal, self) self.volume.setMinimum(0) self.volume.setMaximum(100) self.volume.setTickInterval(10) self.volume.setTickPosition(QSlider.TicksBothSides) # set the volume slider to the value from the previous run, or zero. self.volume.setValue(self.settings.value('volume', 0)) # Create a checkbox "Mute" self.mute = QCheckBox('Mute') # Set it to the value at the end of the last run, or to True self.mute.setChecked(bool(self.settings.value('mute_status', 1))) # Put those together in a row squeezed in the center hb_volume = QHBoxLayout() hb_volume.addStretch(1) hb_volume.addWidget(self.volume, 1) hb_volume.addWidget(self.mute, 0) hb_volume.addStretch(1) # Stack all those up as this widget's layout vlayout = QVBoxLayout() vlayout.addLayout(hb_label) vlayout.addLayout(hb_combos) vlayout.addLayout(hb_volume) self.setLayout(vlayout)