#!/usr/bin/env python import os import sys from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import uic from qrangeslider import QRangeSlider app = QtGui.QApplication(sys.argv) # Example 1 rs1 = QRangeSlider() rs1.show() rs1.setWindowTitle('example 1') rs1.setRange(15, 35) rs1.setBackgroundStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);') rs1.setSpanStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);') # Example 2 rs2 = QRangeSlider() rs2.show() rs2.setWindowTitle('example 2') rs2.setFixedWidth(400) rs2.setFixedHeight(36) rs2.setMin(0) rs2.setMax(100) rs2.setRange(30, 80) rs2.setDrawValues(False)
#!/usr/bin/env python import os import sys from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import uic from qrangeslider import QRangeSlider app = QtGui.QApplication(sys.argv) # Example 1 rs1 = QRangeSlider() rs1.show() rs1.setWindowTitle('example 1') rs1.setRange(15, 35) rs1.setBackgroundStyle( 'background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);' ) rs1.setSpanStyle( 'background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);' ) # Example 2 rs2 = QRangeSlider() rs2.show() rs2.setWindowTitle('example 2') rs2.setFixedWidth(400) rs2.setFixedHeight(36)
def initUI(self): # ==================================== Set up window and wrapping layout self.setWindowTitle("Visualization") wrapper = QVBoxLayout() # ========================================== Set up FPS and error labels labels_layout = QHBoxLayout() self.label_error = QLabel("") self.label_fps = QLabel("") self.label_fps.setAlignment(Qt.AlignRight | Qt.AlignVCenter) labels_layout.addWidget(self.label_error) labels_layout.addStretch() labels_layout.addWidget(self.label_fps) # ================================================== Set up graph layout graph_view = pg.GraphicsView() graph_layout = pg.GraphicsLayout(border=(100,100,100)) graph_view.setCentralItem(graph_layout) # Mel filterbank plot fft_plot = graph_layout.addPlot(title='Filterbank Output', colspan=3) fft_plot.setRange(yRange=[-0.1, 1.2]) fft_plot.disableAutoRange(axis=pg.ViewBox.YAxis) x_data = np.array(range(1, config.N_FFT_BINS + 1)) self.mel_curve = pg.PlotCurveItem() self.mel_curve.setData(x=x_data, y=x_data*0) fft_plot.addItem(self.mel_curve) # Visualization plot graph_layout.nextRow() led_plot = graph_layout.addPlot(title='Visualization Output', colspan=3) led_plot.setRange(yRange=[-5, 260]) led_plot.disableAutoRange(axis=pg.ViewBox.YAxis) # Pen for each of the color channel curves r_pen = pg.mkPen((255, 30, 30, 200), width=4) g_pen = pg.mkPen((30, 255, 30, 200), width=4) b_pen = pg.mkPen((30, 30, 255, 200), width=4) # Color channel curves self.r_curve = pg.PlotCurveItem(pen=r_pen) self.g_curve = pg.PlotCurveItem(pen=g_pen) self.b_curve = pg.PlotCurveItem(pen=b_pen) # Define x data x_data = np.array(range(1, config.N_PIXELS + 1)) self.r_curve.setData(x=x_data, y=x_data*0) self.g_curve.setData(x=x_data, y=x_data*0) self.b_curve.setData(x=x_data, y=x_data*0) # Add curves to plot led_plot.addItem(self.r_curve) led_plot.addItem(self.g_curve) led_plot.addItem(self.b_curve) # ================================================= Set up button layout label_active = QLabel("Active Effect") button_grid = QGridLayout() buttons = {} connecting_funcs = {} grid_width = 4 i = 0 j = 0 # Dynamically layout buttons and connect them to the visualisation effects def connect_generator(effect): def func(): visualizer.current_effect = effect func.__name__ = effect return func # Where the magic happens for effect in visualizer.effects: connecting_funcs[effect] = connect_generator(effect) buttons[effect] = QPushButton(effect) buttons[effect].clicked.connect(connecting_funcs[effect]) button_grid.addWidget(buttons[effect], j, i) i += 1 if i % grid_width == 0: i = 0 j += 1 # ============================================== Set up frequency slider # Frequency range label label_slider = QLabel("Frequency Range") # Frequency slider def freq_slider_change(tick): minf = freq_slider.tickValue(0)**2.0 * (config.MIC_RATE / 2.0) maxf = freq_slider.tickValue(1)**2.0 * (config.MIC_RATE / 2.0) t = 'Frequency range: {:.0f} - {:.0f} Hz'.format(minf, maxf) freq_label.setText(t) config.MIN_FREQUENCY = minf config.MAX_FREQUENCY = maxf dsp.create_mel_bank() def set_freq_min(): config.MIN_FREQUENCY = freq_slider.start() dsp.create_mel_bank() def set_freq_max(): config.MAX_FREQUENCY = freq_slider.end() dsp.create_mel_bank() freq_slider = QRangeSlider() freq_slider.show() freq_slider.setMin(0) freq_slider.setMax(20000) freq_slider.setRange(config.MIN_FREQUENCY, config.MAX_FREQUENCY) freq_slider.setBackgroundStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);') freq_slider.setSpanStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #393);') freq_slider.setDrawValues(True) freq_slider.endValueChanged.connect(set_freq_max) freq_slider.startValueChanged.connect(set_freq_min) freq_slider.setStyleSheet(""" QRangeSlider * { border: 0px; padding: 0px; } QRangeSlider > QSplitter::handle { background: #fff; } QRangeSlider > QSplitter::handle:vertical { height: 3px; } QRangeSlider > QSplitter::handle:pressed { background: #ca5; } """) # ============================================ Set up option tabs layout label_options = QLabel("Effect Options") opts_tabs = QTabWidget() # Dynamically set up tabs tabs = {} grid_layouts = {} self.grid_layout_widgets = {} options = visualizer.effect_opts.keys() for effect in visualizer.effects: # Make the tab self.grid_layout_widgets[effect] = {} tabs[effect] = QWidget() grid_layouts[effect] = QGridLayout() tabs[effect].setLayout(grid_layouts[effect]) opts_tabs.addTab(tabs[effect],effect) # These functions make functions for the dynamic ui generation # YOU WANT-A DYNAMIC I GIVE-A YOU DYNAMIC! def gen_slider_valuechanger(effect, key): def func(): visualizer.effect_opts[effect][key] = self.grid_layout_widgets[effect][key].value() return func def gen_float_slider_valuechanger(effect, key): def func(): visualizer.effect_opts[effect][key] = self.grid_layout_widgets[effect][key].slider_value return func def gen_combobox_valuechanger(effect, key): def func(): visualizer.effect_opts[effect][key] = self.grid_layout_widgets[effect][key].currentText() visualizer._wavelength_set_color_mode(visualizer.effect_opts[effect][key]) return func def gen_checkbox_valuechanger(effect, key): def func(): visualizer.effect_opts[effect][key] = self.grid_layout_widgets[effect][key].isChecked() return func # Dynamically generate ui for settings if effect in visualizer.dynamic_effects_config: i = 0 connecting_funcs[effect] = {} for key, label, ui_element, opts in visualizer.dynamic_effects_config[effect][:]: if ui_element == "slider": connecting_funcs[effect][key] = gen_slider_valuechanger(effect, key) self.grid_layout_widgets[effect][key] = QSlider(Qt.Horizontal) self.grid_layout_widgets[effect][key].setMinimum(opts[0]) self.grid_layout_widgets[effect][key].setMaximum(opts[1]) self.grid_layout_widgets[effect][key].setValue(opts[2]) self.grid_layout_widgets[effect][key].valueChanged.connect( connecting_funcs[effect][key]) grid_layouts[effect].addWidget(QLabel(label),i,0) grid_layouts[effect].addWidget(self.grid_layout_widgets[effect][key],i,1) elif ui_element == "float_slider": connecting_funcs[effect][key] = gen_float_slider_valuechanger(effect, key) self.grid_layout_widgets[effect][key] = QFloatSlider(*opts) self.grid_layout_widgets[effect][key].valueChanged.connect( connecting_funcs[effect][key]) grid_layouts[effect].addWidget(QLabel(label),i,0) grid_layouts[effect].addWidget(self.grid_layout_widgets[effect][key],i,1) elif ui_element == "dropdown": connecting_funcs[effect][key] = gen_combobox_valuechanger(effect, key) self.grid_layout_widgets[effect][key] = QComboBox() self.grid_layout_widgets[effect][key].addItems(opts.keys()) self.grid_layout_widgets[effect][key].currentIndexChanged.connect( connecting_funcs[effect][key]) grid_layouts[effect].addWidget(QLabel(label),i,0) grid_layouts[effect].addWidget(self.grid_layout_widgets[effect][key],i,1) elif ui_element == "checkbox": connecting_funcs[effect][key] = gen_checkbox_valuechanger(effect, key) self.grid_layout_widgets[effect][key] = QCheckBox() #self.grid_layout_widgets[effect][key].addItems(opts.keys()) self.grid_layout_widgets[effect][key].stateChanged.connect( connecting_funcs[effect][key]) grid_layouts[effect].addWidget(QLabel(label),i,0) grid_layouts[effect].addWidget(self.grid_layout_widgets[effect][key],i,1) i += 1 #visualizer.effect_settings[effect] else: grid_layouts[effect].addWidget(QLabel("No customisable options for this effect :("),0,0) # ============================================= Add layouts into wrapper self.setLayout(wrapper) wrapper.addLayout(labels_layout) wrapper.addWidget(graph_view) wrapper.addWidget(label_active) wrapper.addLayout(button_grid) wrapper.addWidget(label_slider) wrapper.addWidget(freq_slider) wrapper.addWidget(label_options) wrapper.addWidget(opts_tabs) self.show()
class RangesliderZmq(QtGui.QWidget): def __init__(self): #app = QtGui.QApplication(sys.argv) super().__init__() self.gesture_dict = GestureDict() self.port = 5556 logging.basicConfig(level=logging.DEBUG, format='%(message)s') self.initUI() #sys.exit(app.exec_()) def initUI(self): port = self.port self.create_socket(port) range_label = QtGui.QLabel('events') self.range_events = QRangeSlider() self.range_events.show() self.range_events.setFixedWidth(300) self.range_events.setFixedHeight(36) self.range_events.setMin(0) self.range_events.setMax(4) self.range_events.setRange(0, 1) self.range_events.startValueChanged.connect( lambda: self.keep_slider_min(self.range_events)) hbox_events = QtGui.QHBoxLayout() hbox_events.addWidget(range_label) hbox_events.addWidget(self.range_events) self.textbox = QtGui.QLineEdit() self.update_btn = QtGui.QPushButton("update") self.update_btn.clicked.connect(lambda: self.button_click(port)) self.update_btn.setFixedWidth(100) hbox = QtGui.QHBoxLayout() hbox.addWidget(self.update_btn) magnitude_label = QtGui.QLabel('magnitude in g/10') self.range_magnitude = QRangeSlider() self.range_magnitude.show() self.range_magnitude.setFixedWidth(300) self.range_magnitude.setFixedHeight(36) self.range_magnitude.setMin(20) self.range_magnitude.setMax(80) self.range_magnitude.setRange(20, 30) hbox_magnitude = QtGui.QHBoxLayout() hbox_magnitude.addWidget(magnitude_label) hbox_magnitude.addWidget(self.range_magnitude) self.filter_length = QRangeSlider() self.filter_length.show() self.filter_length.setFixedWidth(300) self.filter_length.setFixedHeight(36) self.filter_length.setMin(0) self.filter_length.setMax(250) self.filter_length.setRange(0, 100) self.filter_length.startValueChanged.connect( lambda: self.keep_slider_min(self.filter_length)) filter_length_label = QtGui.QLabel('filter length in samples') hbox_length = QtGui.QHBoxLayout() hbox_length.addWidget(filter_length_label) hbox_length.addWidget(self.filter_length) self.message_label = QtGui.QLabel("messages will be here") self.exit_btn = QtGui.QPushButton('exit') self.exit_btn.clicked.connect( lambda: self.exit_click(self.socket, self.context, port)) vbox = QtGui.QVBoxLayout() vbox.addStretch(1) vbox.addLayout(hbox_events) vbox.addLayout(hbox_magnitude) vbox.addLayout(hbox_length) vbox.addWidget(self.message_label) vbox.addWidget(self.update_btn) vbox.addLayout(hbox) vbox.addWidget(self.exit_btn) self.setLayout(vbox) self.setGeometry(300, 300, 300, 150) self.setWindowTitle('rangesliders') self.show() @QtCore.pyqtSlot() def button_click(self, port): ''' handle button click event ''' try: self.update_gesture_dict() message = self.gesture_dict.make_json() logging.info('rangeslider sending message {}'.format(message)) self.socket.send_json(message, flags=zmq.NOBLOCK) except zmq.error.Again as e: logging.info('no receiver for the message: {}'.format(e)) # restart the socket if nothing to receive the message # if receiver closed, the socket needs to be restarted self.close_socket() self.create_socket(port) def close_socket(self): ''' close the socket and context ''' self.socket.close() self.context.term() def create_socket(self, port): ''' create a socket using pyzmq with PAIR context ''' self.context = zmq.Context() self.socket = self.context.socket(zmq.PAIR) self.socket.setsockopt(zmq.LINGER, 0) self.socket.bind("tcp://*:%s" % port) stream_pair = zmqstream.ZMQStream(self.socket) stream_pair.on_recv(self.process_message) def exit_click(self, socket, context, port): ''' handle exit button click ''' socket.close() context.term() sys.exit() def filter_length_change(self): ''' filter length slider has changed ''' length = self.filter_length.value() self.set_message_label('filter_length: {}'.format(length)) def keep_slider_min(self, slider): ''' keep the slider length minimum as one ''' try: slider.setStart(0) except RuntimeError as e: pass self.set_message_label('cannot change this') def process_message(self, msg): time = datetime.now() time = time.strftime('%H:%M:%S') text = ('{}: {}'.format(time, msg)) self.message_label.setText(text) def set_message_label(self, text): self.message_label.setText(text) def timer_timeout(self): ''' handle the QTimer timeout ''' try: msg = self.socket.recv(flags=zmq.NOBLOCK).decode() self.process_message(msg) except zmq.error.Again as e: return def update_gesture_dict(self): ''' get status of all the rangesliders into GestureDict object ''' magnitude_min, magnitude_max = self.range_magnitude.getRange() filter_length = self.filter_length.end() events = self.range_events.end() self.gesture_dict.update_dict(magnitude_min=magnitude_min, \ magnitude_max=magnitude_max/10, events=events, \ filter_length=filter_length)