def generate_labels(self): """ Generate the text labels for the slider. Called on init and on resizeEvent """ self.levels = np.linspace(self.minimum(), self.maximum(), 5) self.level_labels = [] painter = QtGui.QPainter(self) painter.setFont(mono_font()) style = self.style() opt = QtWidgets.QStyleOptionSlider() self.initStyleOption(opt) length = style.pixelMetric(QtWidgets.QStyle.PM_SliderLength, opt, self) available = style.pixelMetric(QtWidgets.QStyle.PM_SliderSpaceAvailable, opt, self) for v in self.levels: label_str = str(int(round(v))) # label_str = "{0:d}".format(v) rect = painter.drawText(QtCore.QRect(), QtCore.Qt.TextDontPrint, label_str) if self.orientation() == QtCore.Qt.Horizontal: x_loc = QtWidgets.QStyle.sliderPositionFromValue(self.minimum(), self.maximum(), v, available, opt.upsideDown) left = x_loc + length // 2 - rect.width() // 2 # there is a 3 px offset that I can't attribute to any metric # left = (self.width())-(rect.width())-10 bottom = (self.height() / 2) + rect.height() //2 + 3 else: y_loc= QtWidgets.QStyle.sliderPositionFromValue(self.minimum(), self.maximum(), v, available, opt.upsideDown) bottom=y_loc+length//2+rect.height()//2-3 # there is a 3 px offset that I can't attribute to any metric #left = (self.width())-(rect.width())-10 left = (self.width()/2)-(styles.INDICATOR_WIDTH/2)-rect.width()-3 pos=QtCore.QPoint(left, bottom) self.level_labels.append((pos, QtGui.QStaticText(label_str))) #painter.drawText(pos, label_str) self.setTickInterval(self.levels[1]-self.levels[0]) self.redraw_labels = False
def paintEvent(self, event): # based on http://qt.gitorious.org/qt/qt/blobs/master/src/gui/widgets/qslider.cpp painter = QtGui.QPainter(self) #style = QtWidgets.QApplication.style() style = self.style() for i, value in enumerate([self._high, self._low]): opt = QtWidgets.QStyleOptionSlider() self.initStyleOption(opt) # pdb.set_trace() # Only draw the groove for the first slider so it doesn't get drawn # on top of the existing ones every time if i == 0: opt.subControls = style.SC_SliderGroove | style.SC_SliderHandle else: # opt.subControls = QtWidgets.QStyle.SC_SliderHandle opt.subControls = style.SC_SliderHandle # # if self.tickPosition() != self.NoTicks: # opt.subControls |= QtWidgets.QStyle.SC_SliderTickmarks if self.pressed_control: opt.activeSubControls = self.pressed_control opt.state |= QtWidgets.QStyle.State_Sunken else: opt.activeSubControls = self.hover_control # opt.rect.setX(-self.width()/2) opt.sliderPosition = value opt.sliderValue = value style.drawComplexControl(QtWidgets.QStyle.CC_Slider, opt, painter, self) if not self.level_labels or self.redraw_labels: painter.end() self.generate_labels() painter = QtGui.QPainter(self) painter.setFont(mono_font()) for label in self.level_labels: painter.drawStaticText(label[0], label[1])
def init_ui(self): self.layout = QtWidgets.QGridLayout() self.timer_label = QtWidgets.QLabel() self.timer_label.setFont(mono_font()) self.indicator = QtWidgets.QRadioButton() self.set_indicator() self.layout.addWidget(QtWidgets.QLabel("Uptime"), 0, 0, alignment=QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight) self.layout.addWidget(self.timer_label, 1, 0) self.layout.addWidget(QtWidgets.QLabel("Status"), 0, 1) self.layout.addWidget(self.indicator, 1, 1) self.setFrameStyle(QtWidgets.QFrame.StyledPanel | QtWidgets.QFrame.Raised) self.setLayout(self.layout)
def init_ui(self): self.layout = QtWidgets.QHBoxLayout() self.setLayout(self.layout) ######### # create widgets # make range slider self.range_slider = RangeSlider(self.abs_range, self.safe_range) # make comboboxes to display numerical value self.max_safe = QtWidgets.QSpinBox() self.max_safe.setRange(self.abs_range[0], self.abs_range[1]) self.max_safe.setSingleStep(10**(self.decimals * -1)) self.max_safe.setValue(self.safe_range[1]) self.min_safe = QtWidgets.QSpinBox() self.min_safe.setRange(self.abs_range[0], self.abs_range[1]) self.min_safe.setSingleStep(10**(self.decimals * -1)) self.min_safe.setValue(self.safe_range[0]) # labels to display values self.value_label = QtWidgets.QLabel() self.value_label.setStyleSheet(styles.DISPLAY_VALUE) self.value_label.setFont(mono_font()) self.value_label.setAlignment(QtCore.Qt.AlignRight) self.value_label.setMargin(0) self.value_label.setContentsMargins(0, 0, 0, 0) self.name_label = QtWidgets.QLabel() self.name_label.setStyleSheet(styles.DISPLAY_NAME) self.name_label.setText(self.name) self.name_label.setAlignment(QtCore.Qt.AlignRight) self.units_label = QtWidgets.QLabel() self.units_label.setStyleSheet(styles.DISPLAY_UNITS) self.units_label.setText(self.units) self.units_label.setAlignment(QtCore.Qt.AlignRight) ######### # connect widgets # update boxes when slider changed self.range_slider.valueChanged.connect(self.update_boxes) # and vice versa self.min_safe.valueChanged.connect(self.range_slider.setLow) self.max_safe.valueChanged.connect(self.range_slider.setHigh) # and connect them all to a general limits_changed method # that also checks the alarm self.range_slider.valueChanged.connect(self._limits_changed) self.min_safe.valueChanged.connect(self._limits_changed) self.max_safe.valueChanged.connect(self._limits_changed) ######### # layout widgets self.layout.addWidget(self.range_slider, 2) box_layout = QtWidgets.QVBoxLayout() box_layout.addWidget(QtWidgets.QLabel('Max:')) box_layout.addWidget(self.max_safe) box_layout.addStretch() box_layout.addWidget(QtWidgets.QLabel('Min:')) box_layout.addWidget(self.min_safe) self.layout.addLayout(box_layout, 1) label_layout = QtWidgets.QVBoxLayout() label_layout.setContentsMargins(0, 0, 0, 0) label_layout.addWidget(self.value_label) label_layout.addWidget(self.name_label) label_layout.addWidget(self.units_label) label_layout.addStretch() self.layout.addLayout(label_layout, 5)
def init_ui(self): self.layout = QtWidgets.QGridLayout() # self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, # QtWidgets.QSizePolicy.Expanding) # Value, Controller # min, max # Name # Units self.value_label = EditableLabel() self.value_label.setStyleSheet(styles.CONTROL_VALUE) self.value_label.label.setFont(mono_font()) self.value_label.lineEdit.setFont(mono_font()) self.value_label.label.setAlignment(QtCore.Qt.AlignRight) #self.value_label.setMargin(0) self.value_label.setContentsMargins(0,0,0,0) # # set max size based on range # # FIXME: TEMPORARY HACK - get sizing to work intelligibly with the dial # #n_ints = len(str(self.abs_range[1])) # n_ints = 3 if self.decimals > 0: # don't just add decimals b/c we add another for the decimal itself # but don't want to +1 if decimals = 0! n_ints = int(len(str(self.abs_range[1]))+self.decimals+1) else: n_ints = int(len(str(self.abs_range[1]))) # to simplify things for now, if we're supposed to display _more_ # than the 5 we assume (eg. 100.0), then use the n_ints # otherwise just use 5 if n_ints <= 5: n_ints = 5 self.value_label.setFixedWidth(n_ints*styles.VALUE_SIZE*.6) # self.value_label.setSizePolicy(QtWidgets.QSizePolicy.Expanding, # QtWidgets.QSizePolicy.Maximum) self.name_label = QtWidgets.QLabel() self.name_label.setStyleSheet(styles.CONTROL_NAME) self.name_label.setText(self.name) self.name_label.setWordWrap(True) self.name_label.setAlignment(QtCore.Qt.AlignRight) # self.name_label.setSizePolicy(QtWidgets.QSizePolicy.Expanding, # QtWidgets.QSizePolicy.Expanding) self.units_label = QtWidgets.QLabel() self.units_label.setStyleSheet(styles.CONTROL_UNITS) self.units_label.setText(self.units) self.units_label.setAlignment(QtCore.Qt.AlignRight) self.units_label.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) # Expand drawer button self.toggle_button = QtWidgets.QToolButton(checkable=True, checked=False) self.toggle_button.setStyleSheet(styles.DISPLAY_NAME) self.toggle_button.toggled.connect(self.toggle_control) self.toggle_button.setToolButtonStyle( QtCore.Qt.ToolButtonIconOnly ) self.toggle_button.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding) self.toggle_button.setArrowType(QtCore.Qt.LeftArrow) ### # layout self.layout.addWidget(self.value_label, 0, 0, 2, 1, alignment=QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight) #self.layout.addWidget(self.dial, 0, 1, 2, 2, alignment=QtCore.Qt.AlignVCenter) #self.layout.addWidget(self.slider_min, 2, 1, 1, 1) #self.layout.addWidget(self.slider_max, 2, 2, 1, 1) self.layout.addWidget(self.name_label, 0, 1, 1, 1) self.layout.addWidget(self.units_label, 1, 1, 1, 1) self.layout.addWidget(self.toggle_button, 0, 2, 2, 1, alignment=QtCore.Qt.AlignRight) self.setLayout(self.layout) ################ # Create initially hidden widgets # Min value - slider - max value self.slider_layout = QtWidgets.QHBoxLayout() self.slider_min = QtWidgets.QLabel() self.slider_min.setText(str(np.round(self.abs_range[0], self.decimals))) self.slider_min.setAlignment(QtCore.Qt.AlignLeft) self.slider_min.setFont(mono_font()) self.slider_min.setStyleSheet(styles.CONTROL_LABEL) self.slider_min.setMargin(0) self.slider_min.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) self.slider_max = QtWidgets.QLabel() self.slider_max.setText(str(np.round(self.abs_range[1], self.decimals))) self.slider_max.setAlignment(QtCore.Qt.AlignRight) self.slider_max.setFont(mono_font()) self.slider_max.setStyleSheet(styles.CONTROL_LABEL) self.slider_max.setMargin(0) self.slider_max.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) self.slider = DoubleSlider(decimals=self.decimals, orientation=QtCore.Qt.Orientation.Horizontal) self.slider.setMinimum(self.abs_range[0]) self.slider.setMaximum(self.abs_range[1]) #self.slider.setContentsMargins(0,0,0,0) self.slider.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) self.slider_layout.addWidget(self.slider_min) self.slider_layout.addWidget(self.slider) self.slider_layout.addWidget(self.slider_max) self.slider_frame = QtWidgets.QFrame() self.slider_frame.setLayout(self.slider_layout) self.slider_frame.setVisible(False) ### # set signals self.value_label.textChanged.connect(self.update_value) self.slider.doubleValueChanged.connect(self.update_value) self.update_value(self.value)
def paintEvent(self, event): # based on http://qt.gitorious.org/qt/qt/blobs/master/src/gui/widgets/qslider.cpp painter = QtGui.QPainter(self) #style = QtWidgets.QApplication.style() style = self.style() ### Draw current value indicator if self._indicator != 0: opt = QtWidgets.QStyleOptionSlider() self.initStyleOption(opt) length = style.pixelMetric(QtWidgets.QStyle.PM_SliderLength, opt, self) available = style.pixelMetric(QtWidgets.QStyle.PM_SliderSpaceAvailable, opt, self) y_loc= QtWidgets.QStyle.sliderPositionFromValue(self.minimum(), self.maximum(), self._indicator, self.height(), opt.upsideDown) # draw indicator first, so underneath max and min indicator_color = QtGui.QColor(0,0,0) if not self.alarm: indicator_color.setNamedColor(styles.INDICATOR_COLOR) else: indicator_color.setNamedColor(styles.ALARM_COLOR) x_begin = (self.width()-styles.INDICATOR_WIDTH)/2 painter.setBrush(indicator_color) pen_bak = copy.copy(painter.pen()) painter.setPen(painter.pen().setWidth(0)) painter.drawRect(x_begin,y_loc,styles.INDICATOR_WIDTH,self.height()-y_loc) painter.setPen(pen_bak) for i, value in enumerate([self._high, self._low]): opt = QtWidgets.QStyleOptionSlider() self.initStyleOption(opt) # pdb.set_trace() # Only draw the groove for the first slider so it doesn't get drawn # on top of the existing ones every time if i == 0: opt.subControls = style.SC_SliderGroove | style.SC_SliderHandle else: #opt.subControls = QtWidgets.QStyle.SC_SliderHandle opt.subControls = style.SC_SliderHandle if self.tickPosition() != self.NoTicks: opt.subControls |= QtWidgets.QStyle.SC_SliderTickmarks if self.pressed_control: opt.activeSubControls = self.pressed_control opt.state |= QtWidgets.QStyle.State_Sunken else: opt.activeSubControls = self.hover_control # opt.rect.setX(-self.width()/2) opt.sliderPosition = value opt.sliderValue = value style.drawComplexControl(QtWidgets.QStyle.CC_Slider, opt, painter, self) # draw ticks opt = QtWidgets.QStyleOptionSlider() self.initStyleOption(opt) length = style.pixelMetric(QtWidgets.QStyle.PM_SliderLength, opt, self) available = style.pixelMetric(QtWidgets.QStyle.PM_SliderSpaceAvailable, opt, self) border_offset = 5 available -= border_offset painter.setFont(mono_font()) for v in self.levels: label_str = str(int(round(v))) # label_str = "{0:d}".format(v) rect = painter.drawText(QtCore.QRect(), QtCore.Qt.TextDontPrint, label_str) y_loc= QtWidgets.QStyle.sliderPositionFromValue(self.minimum(), self.maximum(), v, available, opt.upsideDown) bottom=y_loc+length//2+rect.height()//2+(border_offset/2)-3 # there is a 3 px offset that I can't attribute to any metric #left = (self.width())-(rect.width())-10 left = (self.width()/2)-(styles.INDICATOR_WIDTH/2)-rect.width()-3 pos=QtCore.QPoint(left, bottom) painter.drawText(pos, label_str) self.setTickInterval(self.levels[1]-self.levels[0])
def init_ui(self): self.layout = QtWidgets.QVBoxLayout() self.setLayout(self.layout) ######### # create widgets # make range slider self.range_slider = RangeSlider( self.abs_range, self.safe_range, decimals=self.decimals, orientation=QtCore.Qt.Orientation.Horizontal) # make comboboxes to display numerical value self.max_safe = QtWidgets.QDoubleSpinBox() self.max_safe.setDecimals(self.decimals) self.max_safe.setRange(self.abs_range[0], self.abs_range[1]) self.max_safe.setSingleStep(10**(self.decimals * -1)) self.max_safe.setValue(self.safe_range[1]) self.min_safe = QtWidgets.QDoubleSpinBox() self.min_safe.setDecimals(self.decimals) self.min_safe.setRange(self.abs_range[0], self.abs_range[1]) self.min_safe.setSingleStep(10**(self.decimals * -1)) self.min_safe.setValue(self.safe_range[0]) # labels to display values self.value_label = QtWidgets.QLabel() self.value_label.setStyleSheet(styles.DISPLAY_VALUE) self.value_label.setFont(mono_font()) self.value_label.setAlignment(QtCore.Qt.AlignRight) self.value_label.setMargin(0) self.value_label.setContentsMargins(0, 0, 0, 0) self.value_label.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.name_label = QtWidgets.QLabel() self.name_label.setStyleSheet(styles.DISPLAY_NAME) self.name_label.setText(self.name) self.name_label.setAlignment(QtCore.Qt.AlignRight) self.units_label = QtWidgets.QLabel() self.units_label.setStyleSheet(styles.DISPLAY_UNITS) self.units_label.setText(self.units) self.units_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTop) self.units_label.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) # toggle button to expand control self.toggle_button = QtWidgets.QToolButton(checkable=True, checked=False) self.toggle_button.setStyleSheet(styles.DISPLAY_NAME) self.toggle_button.toggled.connect(self.toggle_control) self.toggle_button.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) self.toggle_button.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding) self.toggle_button.setArrowType(QtCore.Qt.RightArrow) ######### # connect widgets # update boxes when slider changed self.range_slider.valueChanged.connect(self.update_boxes) # and vice versa self.min_safe.valueChanged.connect(self.range_slider.setLow) self.max_safe.valueChanged.connect(self.range_slider.setHigh) # and connect them all to a general limits_changed method # that also checks the alarm self.range_slider.valueChanged.connect(self._limits_changed) self.min_safe.valueChanged.connect(self._limits_changed) self.max_safe.valueChanged.connect(self._limits_changed) ######### # layout widgets # first make label layout label_layout = QtWidgets.QGridLayout() label_layout.setContentsMargins(0, 0, 0, 0) label_layout.addWidget(self.toggle_button, 0, 0, 2, 1) label_layout.addWidget(self.value_label, 0, 1, 2, 1) label_layout.addWidget(self.name_label, 0, 2, 1, 1) label_layout.addWidget(self.units_label, 1, 2, 1, 1) # label_layout.addStretch() self.layout.addLayout(label_layout, 5) # then combine sliders and boxes self.slider_layout = QtWidgets.QVBoxLayout() minmax_layout = QtWidgets.QHBoxLayout() minmax_layout.addWidget(QtWidgets.QLabel('Min:')) minmax_layout.addWidget(self.min_safe) minmax_layout.addStretch() minmax_layout.addWidget(QtWidgets.QLabel('Max:')) minmax_layout.addWidget(self.max_safe) self.slider_layout.addLayout(minmax_layout) self.slider_layout.addWidget(self.range_slider) # and wrap them in a widget so we can show/hide more robustly self.slider_frame = QtWidgets.QFrame() self.slider_frame.setLayout(self.slider_layout) self.slider_frame.setVisible(False)