def create_widget(self): self.check_param(self.param, assert_error=True) self.default = self.param['range'][0] if 'default' in self.param.keys(): if self.param['default']: self.default = self.param['default'] self.widget_group = QWidget() slider = QSlider(Qt.Horizontal) slider.setValue(self.default) slider.setRange(self.param['range'][0], self.param['range'][1]) self.widget = QSpinBox() self.widget.setValue(self.default) self.widget.setRange(self.param['range'][0], self.param['range'][1]) self.widget.valueChanged.connect(slider.setValue) slider.valueChanged.connect(self.widget.setValue) h_box = QHBoxLayout() h_box.addWidget(slider) h_box.addWidget(self.widget) h_box.addStretch(1) self.widget_group.setLayout(h_box)
def __init__(self, layer): super().__init__() self.layer = layer layer.events.blending.connect(self._on_blending_change) layer.events.opacity.connect(self._on_opacity_change) self.setObjectName('layer') self.setMouseTracking(True) self.grid_layout = QGridLayout() self.grid_layout.setContentsMargins(0, 0, 0, 0) self.grid_layout.setSpacing(2) self.setLayout(self.grid_layout) sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(0) sld.setMaximum(100) sld.setSingleStep(1) sld.setValue(self.layer.opacity * 100) sld.valueChanged[int].connect( lambda value=sld: self.changeOpacity(value)) self.opacitySilder = sld blend_comboBox = QComboBox() for blend in Blending: blend_comboBox.addItem(str(blend)) index = blend_comboBox.findText(self.layer.blending, Qt.MatchFixedString) blend_comboBox.setCurrentIndex(index) blend_comboBox.activated[str].connect( lambda text=blend_comboBox: self.changeBlending(text)) self.blendComboBox = blend_comboBox
def createBottomRightGroupBox(self): self.bottomRightGroupBox = QGroupBox("Group 3") self.bottomRightGroupBox.setCheckable(True) self.bottomRightGroupBox.setChecked(True) lineEdit = QLineEdit('s3cRe7') lineEdit.setEchoMode(QLineEdit.Password) spinBox = QSpinBox(self.bottomRightGroupBox) spinBox.setValue(50) dateTimeEdit = QDateTimeEdit(self.bottomRightGroupBox) dateTimeEdit.setDateTime(QDateTime.currentDateTime()) slider = QSlider(Qt.Horizontal, self.bottomRightGroupBox) slider.setValue(40) scrollBar = QScrollBar(Qt.Horizontal, self.bottomRightGroupBox) scrollBar.setValue(60) dial = QDial(self.bottomRightGroupBox) dial.setValue(30) dial.setNotchesVisible(True) layout = QGridLayout() layout.addWidget(lineEdit, 0, 0, 1, 2) layout.addWidget(spinBox, 1, 0, 1, 2) layout.addWidget(dateTimeEdit, 2, 0, 1, 2) layout.addWidget(slider, 3, 0) layout.addWidget(scrollBar, 4, 0) layout.addWidget(dial, 3, 1, 2, 1) layout.setRowStretch(5, 1) self.bottomRightGroupBox.setLayout(layout)
class IntelligentSlider(QWidget): ''' A slider that adds a 'name' attribute and calls a callback with 'name' as an argument to the registerd callback. This allows you to create large groups of sliders in a loop, but still keep track of the individual events It also prints a label below the slider. The range of the slider is hardcoded from zero - 1000, but it supports a conversion factor so you can scale the results''' def __init__(self, name, a, b, callback): QWidget.__init__(self) self.name = name self.callback = callback self.a = a self.b = b self.manually_triggered = False self.slider = QSlider() self.slider.setRange(0, 1000) self.slider.setValue(500) self.slider.valueChanged.connect(self.slider_changed) self.name_label = QLabel() self.name_label.setText(self.name) self.name_label.setAlignment(QtCore.Qt.AlignCenter) self.value_label = QLabel() self.value_label.setText('%2.2f' % (self.slider.value() * self.a + self.b)) self.value_label.setAlignment(QtCore.Qt.AlignCenter) self.layout = QGridLayout(self) self.layout.addWidget(self.name_label, 0, 0) self.layout.addWidget(self.slider, 1, 0, QtCore.Qt.AlignHCenter) self.layout.addWidget(self.value_label, 2, 0) # bind this to the valueChanged signal of the slider def slider_changed(self, val): val = self.val() self.value_label.setText(str(val)[:4]) if not self.manually_triggered: self.callback(self.name, val) def set_conv_fac(self, a, b): self.a = a self.b = b def set_value(self, val): self.manually_triggered = True self.slider.setValue(int((val - self.b) / self.a)) self.value_label.setText('%2.2f' % val) self.manually_triggered = False def val(self): return self.slider.value() * self.a + self.b
def __init__(self, theme='dark', emphasized=False): super().__init__(None) self.setProperty('emphasized', emphasized) self.setStyleSheet(template(raw_stylesheet, **palettes[theme])) lay = QVBoxLayout() self.setLayout(lay) lay.addWidget(QPushButton('push button')) box = QComboBox() box.addItems(['a', 'b', 'c', 'cd']) lay.addWidget(box) lay.addWidget(QFontComboBox()) hbox = QHBoxLayout() chk = QCheckBox('tristate') chk.setToolTip('I am a tooltip') chk.setTristate(True) chk.setCheckState(Qt.PartiallyChecked) chk3 = QCheckBox('checked') chk3.setChecked(True) hbox.addWidget(QCheckBox('unchecked')) hbox.addWidget(chk) hbox.addWidget(chk3) lay.addLayout(hbox) lay.addWidget(TabDemo(emphasized=emphasized)) sld = QSlider(Qt.Horizontal) sld.setValue(50) lay.addWidget(sld) scroll = QScrollBar(Qt.Horizontal) scroll.setValue(50) lay.addWidget(scroll) lay.addWidget(QHRangeSlider(parent=self)) text = QTextEdit() text.setMaximumHeight(100) text.setHtml(blurb) lay.addWidget(text) lay.addWidget(QTimeEdit()) edit = QLineEdit() edit.setPlaceholderText('LineEdit placeholder...') lay.addWidget(edit) lay.addWidget(QLabel('label')) prog = QProgressBar() prog.setValue(50) lay.addWidget(prog) groupBox = QGroupBox("Exclusive Radio Buttons") radio1 = QRadioButton("&Radio button 1") radio2 = QRadioButton("R&adio button 2") radio3 = QRadioButton("Ra&dio button 3") radio1.setChecked(True) hbox = QHBoxLayout() hbox.addWidget(radio1) hbox.addWidget(radio2) hbox.addWidget(radio3) hbox.addStretch(1) groupBox.setLayout(hbox) lay.addWidget(groupBox)
class QLabeledSlider(QWidget): """ A labeled slider widget """ range = None integer = None def __init__(self, parent=None): super(QLabeledSlider, self).__init__(parent) self._range = range self._slider = QSlider() self._slider.setMinimum(0) self._slider.setMaximum(100) self._slider.setOrientation(Qt.Horizontal) self._label = QLabel('') self._layout = QHBoxLayout() self._layout.setContentsMargins(2, 2, 2, 2) self._layout.addWidget(self._slider) self._layout.addWidget(self._label) self._slider.valueChanged.connect(self._update_label) self.setLayout(self._layout) def _update_label(self, *args): self._label.setText(str(self.value())) @property def valueChanged(self): return self._slider.valueChanged def value(self, layer=None, view=None): value = self._slider.value() / 100. * (self.range[1] - self.range[0]) + self.range[0] if self.integer: return int(value) else: return (value) _in_set_value = False def setValue(self, value): if self._in_set_value: return self._in_set_value = True value = int(100 * (value - self.range[0]) / (self.range[1] - self.range[0])) self._slider.setValue(value) self._in_set_value = False
def __init__(self, layer): super().__init__(layer) self.layer.events.edge_width.connect(self._on_edge_width_change) self.layer.events.edge_color.connect(self._on_edge_color_change) self.layer.events.face_color.connect(self._on_face_color_change) sld = QSlider(Qt.Horizontal, self) sld.setFocusPolicy(Qt.NoFocus) sld.setFixedWidth(75) sld.setMinimum(0) sld.setMaximum(40) sld.setSingleStep(1) value = self.layer.edge_width if isinstance(value, Iterable): if isinstance(value, list): value = np.asarray(value) value = value.mean() sld.setValue(int(value)) sld.valueChanged[int].connect(lambda value=sld: self.changeWidth(value)) self.widthSlider = sld self.grid_layout.addWidget(QLabel('width:'), 3, 0) self.grid_layout.addWidget(sld, 3, 1) face_comboBox = QComboBox() colors = self.layer._colors for c in colors: face_comboBox.addItem(c) index = face_comboBox.findText( self.layer.face_color, Qt.MatchFixedString) if index >= 0: face_comboBox.setCurrentIndex(index) face_comboBox.activated[str].connect(lambda text=face_comboBox: self.changeFaceColor(text)) self.faceComboBox = face_comboBox self.grid_layout.addWidget(QLabel('face_color:'), 4, 0) self.grid_layout.addWidget(face_comboBox, 4, 1) edge_comboBox = QComboBox() colors = self.layer._colors for c in colors: edge_comboBox.addItem(c) index = edge_comboBox.findText( self.layer.edge_color, Qt.MatchFixedString) if index >= 0: edge_comboBox.setCurrentIndex(index) edge_comboBox.activated[str].connect(lambda text=edge_comboBox: self.changeEdgeColor(text)) self.edgeComboBox = edge_comboBox self.grid_layout.addWidget(QLabel('edge_color:'), 5, 0) self.grid_layout.addWidget(edge_comboBox, 5, 1) self.setExpanded(False)
class QLabeledSlider(QWidget): """ A labeled slider widget """ range = None integer = None def __init__(self, parent=None): super(QLabeledSlider, self).__init__(parent) self._range = range self._slider = QSlider() self._slider.setMinimum(0) self._slider.setMaximum(100) self._slider.setOrientation(Qt.Horizontal) self._label = QLabel('') self._layout = QHBoxLayout() self._layout.setContentsMargins(2, 2, 2, 2) self._layout.addWidget(self._slider) self._layout.addWidget(self._label) self._slider.valueChanged.connect(self._update_label) self.setLayout(self._layout) def _update_label(self, *args): self._label.setText(str(self.value())) @property def valueChanged(self): return self._slider.valueChanged def value(self, layer=None, view=None): value = self._slider.value() / 100. * (self.range[1] - self.range[0]) + self.range[0] if self.integer: return int(value) else: return(value) _in_set_value = False def setValue(self, value): if self._in_set_value: return self._in_set_value = True value = int(100 * (value - self.range[0]) / (self.range[1] - self.range[0])) self._slider.setValue(value) self._in_set_value = False
def __init__(self, layer): super().__init__(layer) self.layer.events.colormap.connect(self._on_colormap_change) self.layer.events.gamma.connect(self._on_gamma_change) self.layer.events.contrast_limits.connect( self._on_contrast_limits_change ) comboBox = QtColormapComboBox(self) comboBox.setObjectName("colormapComboBox") comboBox._allitems = set(self.layer.colormaps) for name, cm in AVAILABLE_COLORMAPS.items(): if name in self.layer.colormaps: comboBox.addItem(cm._display_name, name) comboBox.activated[str].connect(self.changeColor) self.colormapComboBox = comboBox # Create contrast_limits slider self.contrastLimitsSlider = QHRangeSlider( self.layer.contrast_limits, self.layer.contrast_limits_range, parent=self, ) self.contrastLimitsSlider.mousePressEvent = self._clim_mousepress set_clim = partial(setattr, self.layer, 'contrast_limits') set_climrange = partial(setattr, self.layer, 'contrast_limits_range') self.contrastLimitsSlider.valuesChanged.connect(set_clim) self.contrastLimitsSlider.rangeChanged.connect(set_climrange) # gamma slider sld = QSlider(Qt.Horizontal, parent=self) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(2) sld.setMaximum(200) sld.setSingleStep(2) sld.setValue(100) sld.valueChanged.connect(self.gamma_slider_changed) self.gammaSlider = sld self._on_gamma_change() self.colorbarLabel = QLabel(parent=self) self.colorbarLabel.setObjectName('colorbar') self.colorbarLabel.setToolTip(trans._('Colorbar')) self._on_colormap_change()
def __init__(self, layer): super().__init__(layer) self.layer.events.colormap.connect(self._on_colormap_change) self.layer.events.contrast_limits.connect( lambda e: self.contrast_limits_slider_update() ) self.layer.events.gamma.connect(lambda e: self.gamma_slider_update()) comboBox = QComboBox() for cmap in self.layer.colormaps: comboBox.addItem(cmap) comboBox._allitems = set(self.layer.colormaps) comboBox.activated[str].connect( lambda text=comboBox: self.changeColor(text) ) self.colormapComboBox = comboBox # Create contrast_limits slider self.contrastLimitsSlider = QHRangeSlider( slider_range=[0, 1, 0.0001], values=[0, 1] ) self.contrastLimitsSlider.setEmitWhileMoving(True) self.contrastLimitsSlider.collapsable = False self.contrastLimitsSlider.setEnabled(True) self.contrastLimitsSlider.rangeChanged.connect( self.contrast_limits_slider_changed ) self.contrast_limits_slider_update() # gamma slider sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(2) sld.setMaximum(200) sld.setSingleStep(2) sld.setValue(100) sld.valueChanged[int].connect(self.gamma_slider_changed) self.gammaSlider = sld self.gamma_slider_update() self.colorbarLabel = QLabel() self.colorbarLabel.setObjectName('colorbar') self.colorbarLabel.setToolTip('Colorbar') self._on_colormap_change(None)
class SliderWidget(HLayoutMixin, LineEditWidget): """ IntItem with Slider """ DATA_TYPE = int def __init__(self, item, parent_layout): super(SliderWidget, self).__init__(item, parent_layout) self.slider = self.vmin = self.vmax = None if item.get_prop_value("display", "slider"): self.vmin = item.get_prop_value("data", "min") self.vmax = item.get_prop_value("data", "max") assert ( self.vmin is not None and self.vmax is not None ), "SliderWidget requires that item min/max have been defined" self.slider = QSlider() self.slider.setOrientation(Qt.Horizontal) self.setup_slider(item) self.slider.valueChanged.connect(self.value_changed) self.group.addWidget(self.slider) def value_to_slider(self, value): return value def slider_to_value(self, value): return value def setup_slider(self, item): self.slider.setRange(self.vmin, self.vmax) def update(self, value): """Reimplement LineEditWidget method""" LineEditWidget.update(self, value) if self.slider is not None and isinstance(value, self.DATA_TYPE): self.slider.blockSignals(True) self.slider.setValue(self.value_to_slider(value)) self.slider.blockSignals(False) def value_changed(self, ivalue): """Update the lineedit""" value = str(self.slider_to_value(ivalue)) self.edit.setText(value) self.update(value)
def open_perspective_popup(self): """Show a slider to control the viewer `camera.perspective`.""" if self.viewer.dims.ndisplay != 3: return # make slider connected to perspective parameter sld = QSlider(Qt.Horizontal, self) sld.setRange(0, max(90, self.viewer.camera.perspective)) sld.setValue(self.viewer.camera.perspective) sld.valueChanged.connect( lambda v: setattr(self.viewer.camera, 'perspective', v)) # make layout layout = QHBoxLayout() layout.addWidget(QLabel(trans._('Perspective'), self)) layout.addWidget(sld) # popup and show pop = QtPopup(self) pop.frame.setLayout(layout) pop.show_above_mouse()
def __init__(self, layer): super().__init__(layer) self.layer.events.colormap.connect(self._on_colormap_change) self.layer.events.gamma.connect(self.gamma_slider_update) self.layer.events.contrast_limits.connect(self._on_clims_change) comboBox = QComboBox() comboBox.addItems(self.layer.colormaps) comboBox._allitems = set(self.layer.colormaps) comboBox.activated[str].connect(self.changeColor) self.colormapComboBox = comboBox # Create contrast_limits slider self.contrastLimitsSlider = QHRangeSlider( self.layer.contrast_limits, self.layer.contrast_limits_range ) self.contrastLimitsSlider.mousePressEvent = self._clim_mousepress set_clim = partial(setattr, self.layer, 'contrast_limits') set_climrange = partial(setattr, self.layer, 'contrast_limits_range') self.contrastLimitsSlider.valuesChanged.connect(set_clim) self.contrastLimitsSlider.rangeChanged.connect(set_climrange) # gamma slider sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(2) sld.setMaximum(200) sld.setSingleStep(2) sld.setValue(100) sld.valueChanged.connect(self.gamma_slider_changed) self.gammaSlider = sld self.gamma_slider_update() self.colorbarLabel = QLabel() self.colorbarLabel.setObjectName('colorbar') self.colorbarLabel.setToolTip('Colorbar') self._on_colormap_change()
def __init__(self, parent): super(MainWidget, self).__init__(parent) self._layout = QHBoxLayout(self) self.setLayout(self._layout) roundbar = QRoundProgressBar(self) roundbar.setBarStyle(QRoundProgressBar.BarStyle.PIE) roundbar.setFixedWidth(300) roundbar.setFixedHeight(300) roundbar.setDecimals(1) self._layout.addWidget(roundbar) self._controlWidget = QWidget(self) self._controlWidget.setMaximumHeight(200) self._controlWidgetLayout = QFormLayout(self._controlWidget) self._controlWidget.setLayout(self._controlWidgetLayout) bar_style_label = QLabel("Bar style", self._controlWidget) style = QPushButton(self._controlWidget) style.setText("Change bar style") self._controlWidgetLayout.addRow(bar_style_label, style) app_style_label = QLabel("App style", self._controlWidget) picker = StylePickerHorizontal(self._controlWidget) self._controlWidgetLayout.addRow(app_style_label, picker) style.clicked.connect(lambda: roundbar.setBarStyle(get_style())) slider_label = QLabel("Progress", self._controlWidget) slider = QSlider(Qt.Horizontal, self._controlWidget) slider.setRange(0, 100) slider.valueChanged.connect(roundbar.setValue) slider.setValue(28) self._controlWidgetLayout.addRow(slider_label, slider) self._layout.addWidget(self._controlWidget)
class AnimateDialog(QDialog): def __init__(self, vpoints: Sequence[VPoint], vlinks: Sequence[VLink], path: _Paths, slider_path: _SliderPaths, monochrome: bool, parent: QWidget): super(AnimateDialog, self).__init__(parent) self.setWindowTitle("Vector Animation") self.setWindowFlags(self.windowFlags() | Qt.WindowMaximizeButtonHint & ~Qt.WindowContextHelpButtonHint) self.setMinimumSize(800, 600) self.setModal(True) main_layout = QVBoxLayout(self) self.canvas = _DynamicCanvas(vpoints, vlinks, path, slider_path, self) self.canvas.set_monochrome_mode(monochrome) self.canvas.update_pos.connect(self.__set_pos) layout = QHBoxLayout(self) pt_option = QComboBox(self) pt_option.addItems([f"P{p}" for p in range(len(vpoints))]) layout.addWidget(pt_option) value_label = QLabel(self) @Slot(int) def show_values(ind: int): vel, vel_deg = self.canvas.get_vel(ind) acc, acc_deg = self.canvas.get_acc(ind) value_label.setText( f"Velocity: {vel:.04f} ({vel_deg:.04f}deg) | " f"Acceleration: {acc:.04f} ({acc_deg:.04f}deg)") pt_option.currentIndexChanged.connect(show_values) layout.addWidget(value_label) self.pos_label = QLabel(self) layout.addItem( QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) layout.addWidget(self.pos_label) main_layout.addLayout(layout) main_layout.addWidget(self.canvas) layout = QHBoxLayout(self) self.play = QPushButton(QIcon(QPixmap(":/icons/play.png")), "", self) self.play.setCheckable(True) self.play.clicked.connect(self.__play) layout.addWidget(self.play) self.slider = QSlider(Qt.Horizontal, self) self.slider.setMaximum(max(len(p) for p in path) - 1) self.slider.valueChanged.connect(self.canvas.set_index) layout.addWidget(self.slider) layout.addWidget(QLabel("Total times:", self)) factor = QDoubleSpinBox(self) factor.valueChanged.connect(self.canvas.set_factor) factor.setSuffix('s') factor.setRange(0.01, 999999) factor.setValue(10) layout.addWidget(factor) main_layout.addLayout(layout) self.timer = QTimer() self.timer.setInterval(10) self.timer.timeout.connect(self.__move_ind) @Slot() def __move_ind(self): """Move indicator.""" value = self.slider.value() + 1 self.slider.setValue(value) if value > self.slider.maximum(): self.slider.setValue(0) @Slot(float, float) def __set_pos(self, x: float, y: float) -> None: """Set mouse position.""" self.pos_label.setText(f"({x:.04f}, {y:.04f})") @Slot() def __play(self): """Start playing.""" if self.play.isChecked(): self.timer.start() else: self.timer.stop()
def __init__(self, layer): super().__init__(layer) self.layer.events.mode.connect(self.set_mode) self.layer.events.edge_width.connect(self._on_edge_width_change) self.layer.events.edge_color.connect(self._on_edge_color_change) self.layer.events.face_color.connect(self._on_face_color_change) self.layer.events.editable.connect(self._on_editable_change) sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(0) sld.setMaximum(40) sld.setSingleStep(1) value = self.layer.edge_width if isinstance(value, Iterable): if isinstance(value, list): value = np.asarray(value) value = value.mean() sld.setValue(int(value)) sld.valueChanged[int].connect( lambda value=sld: self.changeWidth(value) ) self.widthSlider = sld face_comboBox = QComboBox() colors = self.layer._colors for c in colors: face_comboBox.addItem(c) face_comboBox.activated[str].connect( lambda text=face_comboBox: self.changeFaceColor(text) ) self.faceComboBox = face_comboBox self.faceColorSwatch = QFrame() self.faceColorSwatch.setObjectName('swatch') self.faceColorSwatch.setToolTip('Face color swatch') self._on_face_color_change(None) edge_comboBox = QComboBox() colors = self.layer._colors for c in colors: edge_comboBox.addItem(c) edge_comboBox.activated[str].connect( lambda text=edge_comboBox: self.changeEdgeColor(text) ) self.edgeComboBox = edge_comboBox self.edgeColorSwatch = QFrame() self.edgeColorSwatch.setObjectName('swatch') self.edgeColorSwatch.setToolTip('Edge color swatch') self._on_edge_color_change(None) self.select_button = QtModeButton( layer, 'select', Mode.SELECT, 'Select shapes' ) self.direct_button = QtModeButton( layer, 'direct', Mode.DIRECT, 'Select vertices' ) self.panzoom_button = QtModeButton( layer, 'zoom', Mode.PAN_ZOOM, 'Pan/zoom' ) self.rectangle_button = QtModeButton( layer, 'rectangle', Mode.ADD_RECTANGLE, 'Add rectangles' ) self.ellipse_button = QtModeButton( layer, 'ellipse', Mode.ADD_ELLIPSE, 'Add ellipses' ) self.line_button = QtModeButton( layer, 'line', Mode.ADD_LINE, 'Add lines' ) self.path_button = QtModeButton( layer, 'path', Mode.ADD_PATH, 'Add paths' ) self.polygon_button = QtModeButton( layer, 'polygon', Mode.ADD_POLYGON, 'Add polygons' ) self.vertex_insert_button = QtModeButton( layer, 'vertex_insert', Mode.VERTEX_INSERT, 'Insert vertex' ) self.vertex_remove_button = QtModeButton( layer, 'vertex_remove', Mode.VERTEX_REMOVE, 'Remove vertex' ) self.move_front_button = QtMoveFrontButton(layer) self.move_back_button = QtMoveBackButton(layer) self.delete_button = QtDeleteShapeButton(layer) self.panzoom_button.setChecked(True) self.button_group = QButtonGroup(self) self.button_group.addButton(self.select_button) self.button_group.addButton(self.direct_button) self.button_group.addButton(self.panzoom_button) self.button_group.addButton(self.rectangle_button) self.button_group.addButton(self.ellipse_button) self.button_group.addButton(self.line_button) self.button_group.addButton(self.path_button) self.button_group.addButton(self.polygon_button) self.button_group.addButton(self.vertex_insert_button) self.button_group.addButton(self.vertex_remove_button) button_grid = QGridLayout() button_grid.addWidget(self.vertex_remove_button, 0, 1) button_grid.addWidget(self.vertex_insert_button, 0, 2) button_grid.addWidget(self.delete_button, 0, 3) button_grid.addWidget(self.direct_button, 0, 4) button_grid.addWidget(self.select_button, 0, 5) button_grid.addWidget(self.panzoom_button, 0, 6) button_grid.addWidget(self.move_back_button, 1, 0) button_grid.addWidget(self.move_front_button, 1, 1) button_grid.addWidget(self.ellipse_button, 1, 2) button_grid.addWidget(self.rectangle_button, 1, 3) button_grid.addWidget(self.polygon_button, 1, 4) button_grid.addWidget(self.line_button, 1, 5) button_grid.addWidget(self.path_button, 1, 6) button_grid.setColumnStretch(2, 2) button_grid.setSpacing(4) # grid_layout created in QtLayerControls # addWidget(widget, row, column, [row_span, column_span]) self.grid_layout.addLayout(button_grid, 0, 0, 1, 3) self.grid_layout.addWidget(QLabel('opacity:'), 1, 0) self.grid_layout.addWidget(self.opacitySilder, 1, 1, 1, 2) self.grid_layout.addWidget(QLabel('edge width:'), 2, 0) self.grid_layout.addWidget(self.widthSlider, 2, 1, 1, 2) self.grid_layout.addWidget(QLabel('blending:'), 3, 0) self.grid_layout.addWidget(self.blendComboBox, 3, 1, 1, 2) self.grid_layout.addWidget(QLabel('face color:'), 4, 0) self.grid_layout.addWidget(self.faceComboBox, 4, 2) self.grid_layout.addWidget(self.faceColorSwatch, 4, 1) self.grid_layout.addWidget(QLabel('edge color:'), 5, 0) self.grid_layout.addWidget(self.edgeComboBox, 5, 2) self.grid_layout.addWidget(self.edgeColorSwatch, 5, 1) self.grid_layout.setRowStretch(6, 1) self.grid_layout.setColumnStretch(1, 1) self.grid_layout.setSpacing(4)
def __init__(self, layer): super().__init__(layer) self.layer.events.colormap.connect(self._on_colormap_change) self.layer.events.selected_label.connect(self._on_selection_change) self.layer.events.brush_size.connect(self._on_brush_size_change) self.layer.events.contiguous.connect(self._on_contig_change) self.layer.events.n_dimensional.connect(self._on_n_dim_change) self.colormap_update = QPushButton('click') self.colormap_update.setObjectName('shuffle') self.colormap_update.clicked.connect(self.changeColor) self.colormap_update.setFixedWidth(112) self.colormap_update.setFixedHeight(25) shuffle_label = QLabel('shuffle colors:') shuffle_label.setObjectName('shuffle-label') row = self.grid_layout.rowCount() self.grid_layout.addWidget(shuffle_label, row, self.name_column) self.grid_layout.addWidget( self.colormap_update, row, self.property_column ) # selection spinbox self.selection_spinbox = QSpinBox() self.selection_spinbox.setSingleStep(1) self.selection_spinbox.setMinimum(0) self.selection_spinbox.setMaximum(2147483647) self.selection_spinbox.setValue(self.layer.selected_label) self.selection_spinbox.setFixedWidth(75) self.selection_spinbox.valueChanged.connect(self.changeSelection) row = self.grid_layout.rowCount() self.grid_layout.addWidget(QLabel('label:'), row, self.name_column) self.grid_layout.addWidget( self.selection_spinbox, row, self.property_column ) sld = QSlider(Qt.Horizontal, self) sld.setFocusPolicy(Qt.NoFocus) sld.setFixedWidth(110) sld.setMinimum(1) sld.setMaximum(40) sld.setSingleStep(1) value = self.layer.brush_size if isinstance(value, Iterable): if isinstance(value, list): value = np.asarray(value) value = value[:2].mean() sld.setValue(int(value)) sld.valueChanged[int].connect(lambda value=sld: self.changeSize(value)) self.brush_size_slider = sld row = self.grid_layout.rowCount() self.grid_layout.addWidget( QLabel('brush size:'), row, self.name_column ) self.grid_layout.addWidget(sld, row, self.property_column) contig_cb = QCheckBox() contig_cb.setToolTip('contiguous editing') contig_cb.setChecked(self.layer.contiguous) contig_cb.stateChanged.connect( lambda state=contig_cb: self.change_contig(state) ) self.contig_checkbox = contig_cb row = self.grid_layout.rowCount() self.grid_layout.addWidget( QLabel('contiguous:'), row, self.name_column ) self.grid_layout.addWidget(contig_cb, row, self.property_column) ndim_cb = QCheckBox() ndim_cb.setToolTip('n-dimensional editing') ndim_cb.setChecked(self.layer.n_dimensional) ndim_cb.stateChanged.connect( lambda state=ndim_cb: self.change_ndim(state) ) self.ndim_checkbox = ndim_cb row = self.grid_layout.rowCount() self.grid_layout.addWidget(QLabel('n-dim:'), row, self.name_column) self.grid_layout.addWidget(ndim_cb, row, self.property_column) self.setExpanded(False)
def __init__(self, layer): super().__init__(layer) self.layer.events.mode.connect(self._on_mode_change) self.layer.events.edge_width.connect(self._on_edge_width_change) self.layer.events.current_edge_color.connect( self._on_current_edge_color_change) self.layer.events.current_face_color.connect( self._on_current_face_color_change) self.layer.events.editable.connect(self._on_editable_change) self.layer.text.events.visible.connect(self._on_text_visibility_change) sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(0) sld.setMaximum(40) sld.setSingleStep(1) value = self.layer.current_edge_width if isinstance(value, Iterable): if isinstance(value, list): value = np.asarray(value) value = value.mean() sld.setValue(int(value)) sld.valueChanged.connect(self.changeWidth) self.widthSlider = sld self.select_button = QtModeRadioButton(layer, 'select', Mode.SELECT, tooltip='Select shapes') self.direct_button = QtModeRadioButton(layer, 'direct', Mode.DIRECT, tooltip='Select vertices') self.panzoom_button = QtModeRadioButton(layer, 'zoom', Mode.PAN_ZOOM, tooltip='Pan/zoom', checked=True) self.rectangle_button = QtModeRadioButton(layer, 'rectangle', Mode.ADD_RECTANGLE, tooltip='Add rectangles') self.ellipse_button = QtModeRadioButton(layer, 'ellipse', Mode.ADD_ELLIPSE, tooltip='Add ellipses') self.line_button = QtModeRadioButton(layer, 'line', Mode.ADD_LINE, tooltip='Add lines') self.path_button = QtModeRadioButton(layer, 'path', Mode.ADD_PATH, tooltip='Add paths') self.polygon_button = QtModeRadioButton(layer, 'polygon', Mode.ADD_POLYGON, tooltip='Add polygons') self.vertex_insert_button = QtModeRadioButton(layer, 'vertex_insert', Mode.VERTEX_INSERT, tooltip='Insert vertex') self.vertex_remove_button = QtModeRadioButton(layer, 'vertex_remove', Mode.VERTEX_REMOVE, tooltip='Remove vertex') self.move_front_button = QtModePushButton( layer, 'move_front', slot=self.layer.move_to_front, tooltip='Move to front', ) self.move_back_button = QtModePushButton( layer, 'move_back', slot=self.layer.move_to_back, tooltip='Move to back', ) self.delete_button = QtModePushButton( layer, 'delete_shape', slot=self.layer.remove_selected, tooltip='Delete selected shapes', ) self.button_group = QButtonGroup(self) self.button_group.addButton(self.select_button) self.button_group.addButton(self.direct_button) self.button_group.addButton(self.panzoom_button) self.button_group.addButton(self.rectangle_button) self.button_group.addButton(self.ellipse_button) self.button_group.addButton(self.line_button) self.button_group.addButton(self.path_button) self.button_group.addButton(self.polygon_button) self.button_group.addButton(self.vertex_insert_button) self.button_group.addButton(self.vertex_remove_button) button_grid = QGridLayout() button_grid.addWidget(self.vertex_remove_button, 0, 2) button_grid.addWidget(self.vertex_insert_button, 0, 3) button_grid.addWidget(self.delete_button, 0, 4) button_grid.addWidget(self.direct_button, 0, 5) button_grid.addWidget(self.select_button, 0, 6) button_grid.addWidget(self.panzoom_button, 0, 7) button_grid.addWidget(self.move_back_button, 1, 1) button_grid.addWidget(self.move_front_button, 1, 2) button_grid.addWidget(self.ellipse_button, 1, 3) button_grid.addWidget(self.rectangle_button, 1, 4) button_grid.addWidget(self.polygon_button, 1, 5) button_grid.addWidget(self.line_button, 1, 6) button_grid.addWidget(self.path_button, 1, 7) button_grid.setContentsMargins(5, 0, 0, 5) button_grid.setColumnStretch(0, 1) button_grid.setSpacing(4) self.faceColorEdit = QColorSwatchEdit( initial_color=self.layer.current_face_color, tooltip='click to set current face color', ) self._on_current_face_color_change() self.edgeColorEdit = QColorSwatchEdit( initial_color=self.layer.current_edge_color, tooltip='click to set current edge color', ) self._on_current_edge_color_change() self.faceColorEdit.color_changed.connect(self.changeFaceColor) self.edgeColorEdit.color_changed.connect(self.changeEdgeColor) text_disp_cb = QCheckBox() text_disp_cb.setToolTip('toggle text visibility') text_disp_cb.setChecked(self.layer.text.visible) text_disp_cb.stateChanged.connect(self.change_text_visibility) self.textDispCheckBox = text_disp_cb # grid_layout created in QtLayerControls # addWidget(widget, row, column, [row_span, column_span]) self.grid_layout.addLayout(button_grid, 0, 0, 1, 2) self.grid_layout.addWidget(QLabel('opacity:'), 1, 0) self.grid_layout.addWidget(self.opacitySlider, 1, 1) self.grid_layout.addWidget(QLabel('edge width:'), 2, 0) self.grid_layout.addWidget(self.widthSlider, 2, 1) self.grid_layout.addWidget(QLabel('blending:'), 3, 0) self.grid_layout.addWidget(self.blendComboBox, 3, 1) self.grid_layout.addWidget(QLabel('face color:'), 4, 0) self.grid_layout.addWidget(self.faceColorEdit, 4, 1) self.grid_layout.addWidget(QLabel('edge color:'), 5, 0) self.grid_layout.addWidget(self.edgeColorEdit, 5, 1) self.grid_layout.addWidget(QLabel('display text:'), 6, 0) self.grid_layout.addWidget(self.textDispCheckBox, 6, 1) self.grid_layout.setRowStretch(7, 1) self.grid_layout.setColumnStretch(1, 1) self.grid_layout.setSpacing(4)
def create_wwwc_tab(apply_adjust): Conf = namedtuple("Conf", "min max step default") ww_conf = Conf(0, 2000, 1, 350) wc_conf = Conf(-2000, 2000, 1, 50) tab = QWidget() tab.layout = QFormLayout() # BUG: 只有一个负号的时候会变成0,应该保留负号 ww_edit = QLineEdit() ww_edit.setValidator(QtGui.QIntValidator(ww_conf.min, ww_conf.max)) ww_edit.setFixedWidth(50) wc_edit = QLineEdit() wc_edit.setValidator(QtGui.QIntValidator(wc_conf.min, wc_conf.max)) wc_edit.setFixedWidth(50) ww_slider = QSlider(Qt.Horizontal) # 窗宽滑动条 ww_slider.setMinimum(ww_conf.min) ww_slider.setMaximum(ww_conf.max) ww_slider.setSingleStep(ww_conf.step) ww_slider.setValue(ww_conf.default) wc_slider = QSlider(Qt.Horizontal) # 窗位滑动条 wc_slider.setMinimum(wc_conf.min) wc_slider.setMaximum(wc_conf.max) wc_slider.setSingleStep(wc_conf.step) wc_slider.setValue(wc_conf.default) ww_label = QLabel() ww_label.setText("窗宽: ") wc_label = QLabel() wc_label.setText("窗位: ") ww_combo = QHBoxLayout() ww_combo.addWidget(ww_edit) ww_combo.addWidget(ww_slider) wc_combo = QHBoxLayout() wc_combo.addWidget(wc_edit) wc_combo.addWidget(wc_slider) tab.layout.addRow(ww_label, ww_combo) tab.layout.addRow(wc_label, wc_combo) tab.setLayout(tab.layout) def slider_change(slider, editor): def func(): editor.setText(str(slider.value())) apply_adjust( functools.partial(wwwc, ww_slider.value(), wc_slider.value())) return func def edit_changed(editor, slider): def func(): value = editor.text() if value == "" or value == "-": value = 0 value = int(value) slider.setValue(value) return func ww_slider.valueChanged.connect(slider_change(ww_slider, ww_edit)) wc_slider.valueChanged.connect(slider_change(wc_slider, wc_edit)) ww_edit.textChanged.connect(edit_changed(ww_edit, ww_slider)) # wc_edit.textChanged.connect(wc_edit_change) return tab, "WW/WC"
class PyDMSlider(QFrame, TextFormatter, PyDMWritableWidget): """ A QSlider with support for Channels and more from PyDM. Parameters ---------- parent : QWidget The parent widget for the Label init_channel : str, optional The channel to be used by the widget. """ actionTriggered = Signal(int) rangeChanged = Signal(float, float) sliderMoved = Signal(float) sliderPressed = Signal() sliderReleased = Signal() valueChanged = Signal(float) def __init__(self, parent=None, init_channel=None): QFrame.__init__(self, parent) PyDMWritableWidget.__init__(self, init_channel=init_channel) self.alarmSensitiveContent = True self.alarmSensitiveBorder = False # Internal values for properties self._show_limit_labels = True self._show_value_label = True self._user_defined_limits = False self._needs_limit_info = True self._minimum = None self._maximum = None self._user_minimum = -10.0 self._user_maximum = 10.0 self._num_steps = 101 self._orientation = Qt.Horizontal # Set up all the internal widgets that make up a PyDMSlider. # We'll add all these things to layouts when we call setup_widgets_for_orientation label_size_policy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.low_lim_label = QLabel(self) self.low_lim_label.setObjectName("lowLimLabel") self.low_lim_label.setSizePolicy(label_size_policy) self.low_lim_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.value_label = QLabel(self) self.value_label.setObjectName("valueLabel") self.value_label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.high_lim_label = QLabel(self) self.high_lim_label.setObjectName("highLimLabel") self.high_lim_label.setSizePolicy(label_size_policy) self.high_lim_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._slider = QSlider(parent=self) self._slider.setOrientation(Qt.Horizontal) self._slider.sliderMoved.connect(self.internal_slider_moved) self._slider.sliderPressed.connect(self.internal_slider_pressed) self._slider.sliderReleased.connect(self.internal_slider_released) self._slider.valueChanged.connect(self.internal_slider_value_changed) # self.vertical_layout.addWidget(self._slider) # Other internal variables and final setup steps self._slider_position_to_value_map = None self._mute_internal_slider_changes = False self.setup_widgets_for_orientation(self._orientation) self.reset_slider_limits() def init_for_designer(self): """ Method called after the constructor to tweak configurations for when using the widget with the Qt Designer """ self.value = 0.0 @Property(Qt.Orientation) def orientation(self): """ The slider orientation (Horizontal or Vertical) Returns ------- int Qt.Horizontal or Qt.Vertical """ return self._orientation @orientation.setter def orientation(self, new_orientation): """ The slider orientation (Horizontal or Vertical) Parameters ---------- new_orientation : int Qt.Horizontal or Qt.Vertical """ self._orientation = new_orientation self.setup_widgets_for_orientation(new_orientation) def setup_widgets_for_orientation(self, new_orientation): """ Reconstruct the widget given the orientation. Parameters ---------- new_orientation : int Qt.Horizontal or Qt.Vertical """ if new_orientation not in (Qt.Horizontal, Qt.Vertical): logger.error("Invalid orientation '{0}'. The existing layout will not change.".format(new_orientation)) return layout = None if new_orientation == Qt.Horizontal: layout = QVBoxLayout() layout.setContentsMargins(4, 0, 4, 4) label_layout = QHBoxLayout() label_layout.addWidget(self.low_lim_label) label_layout.addStretch(0) label_layout.addWidget(self.value_label) label_layout.addStretch(0) label_layout.addWidget(self.high_lim_label) layout.addLayout(label_layout) self._slider.setOrientation(new_orientation) layout.addWidget(self._slider) elif new_orientation == Qt.Vertical: layout = QHBoxLayout() layout.setContentsMargins(0, 4, 4, 4) label_layout = QVBoxLayout() label_layout.addWidget(self.high_lim_label) label_layout.addStretch(0) label_layout.addWidget(self.value_label) label_layout.addStretch(0) label_layout.addWidget(self.low_lim_label) layout.addLayout(label_layout) self._slider.setOrientation(new_orientation) layout.addWidget(self._slider) if self.layout() is not None: # Trick to remove the existing layout by re-parenting it in an empty widget. QWidget().setLayout(self.layout()) self.setLayout(layout) def update_labels(self): """ Update the limits and value labels with the correct values. """ def set_label(value, label_widget): if value is None: label_widget.setText("") else: label_widget.setText(self.format_string.format(value)) set_label(self.minimum, self.low_lim_label) set_label(self.maximum, self.high_lim_label) set_label(self.value, self.value_label) def reset_slider_limits(self): """ Reset the limits and adjust the labels properly for the slider. """ if self.minimum is None or self.maximum is None: self._needs_limit_info = True self.set_enable_state() return self._needs_limit_info = False self._slider.setMinimum(0) self._slider.setMaximum(self._num_steps - 1) self._slider.setSingleStep(1) self._slider.setPageStep(10) self._slider_position_to_value_map = np.linspace(self.minimum, self.maximum, num=self._num_steps) self.update_labels() self.set_slider_to_closest_value(self.value) self.rangeChanged.emit(self.minimum, self.maximum) self.set_enable_state() def find_closest_slider_position_to_value(self, val): """ Find and returns the index for the closest position on the slider for a given value. Parameters ---------- val : float Returns ------- int """ diff = abs(self._slider_position_to_value_map - float(val)) return np.argmin(diff) def set_slider_to_closest_value(self, val): """ Set the value for the slider according to a given value. Parameters ---------- val : float """ if val is None or self._needs_limit_info: return # When we set the slider to the closest value, it may end up at a slightly # different position than val (if val is not in self._slider_position_to_value_map) # We don't want that slight difference to get broacast out and put the channel # somewhere new. For example, if the slider can only be at 0.4 or 0.5, but a # new value comes in of 0.45, its more important to keep the 0.45 than to change # it to where the slider gets set. Therefore, we mute the internal slider changes # so that its valueChanged signal doesn't cause us to emit a signal to PyDM to change # the value of the channel. self._mute_internal_slider_changes = True self._slider.setValue(self.find_closest_slider_position_to_value(val)) self._mute_internal_slider_changes = False def value_changed(self, new_val): """ Callback invoked when the Channel value is changed. Parameters ---------- new_val : int or float The new value from the channel. """ PyDMWritableWidget.value_changed(self, new_val) if hasattr(self, "value_label"): self.value_label.setText(self.format_string.format(self.value)) if not self._slider.isSliderDown(): self.set_slider_to_closest_value(self.value) def ctrl_limit_changed(self, which, new_limit): """ Callback invoked when the Channel receives new control limit values. Parameters ---------- which : str Which control limit was changed. "UPPER" or "LOWER" new_limit : float New value for the control limit """ PyDMWritableWidget.ctrl_limit_changed(self, which, new_limit) if not self.userDefinedLimits: self.reset_slider_limits() def update_format_string(self): """ Reconstruct the format string to be used when representing the output value. Returns ------- format_string : str The format string to be used including or not the precision and unit """ fs = super(PyDMSlider, self).update_format_string() self.update_labels() return fs def set_enable_state(self): """ Determines wether or not the widget must be enabled or not depending on the write access, connection state and presence of limits information """ # Even though by documentation disabling parent QFrame (self), should disable internal # slider, in practice it still remains interactive (PyQt 5.12.1). Disabling explicitly, solves # the problem. should_enable = self._write_access and self._connected and not self._needs_limit_info self.setEnabled(should_enable) self._slider.setEnabled(should_enable) @Slot(int) def internal_slider_action_triggered(self, action): self.actionTriggered.emit(action) @Slot(int) def internal_slider_moved(self, val): """ Method invoked when the slider is moved. Parameters ---------- val : float """ # Avoid potential crash if limits are undefined if self._slider_position_to_value_map is None: return # The user has moved the slider, we need to update our value. # Only update the underlying value, not the self.value property, # because we don't need to reset the slider position. If we change # self.value, we can get into a loop where the position changes, which # updates the value, which changes the position again, etc etc. self.value = self._slider_position_to_value_map[val] self.sliderMoved.emit(self.value) @Slot() def internal_slider_pressed(self): """ Method invoked when the slider is pressed """ self.sliderPressed.emit() @Slot() def internal_slider_released(self): """ Method invoked when the slider is released """ self.sliderReleased.emit() @Slot(int) def internal_slider_value_changed(self, val): """ Method invoked when a new value is selected on the slider. This will cause the new value to be emitted to the signal unless `mute_internal_slider_changes` is True. Parameters ---------- val : int """ # At this point, our local copy of the value reflects the position of the # slider, now all we need to do is emit a signal to PyDM so that the data # plugin will send a put to the channel. Don't update self.value or self._value # in here, it is pointless at best, and could cause an infinite loop at worst. if not self._mute_internal_slider_changes: self.send_value_signal[float].emit(self.value) @Property(bool) def showLimitLabels(self): """ Whether or not the high and low limits should be displayed on the slider. Returns ------- bool """ return self._show_limit_labels @showLimitLabels.setter def showLimitLabels(self, checked): """ Whether or not the high and low limits should be displayed on the slider. Parameters ---------- checked : bool """ self._show_limit_labels = checked if checked: self.low_lim_label.show() self.high_lim_label.show() else: self.low_lim_label.hide() self.high_lim_label.hide() @Property(bool) def showValueLabel(self): """ Whether or not the current value should be displayed on the slider. Returns ------- bool """ return self._show_value_label @showValueLabel.setter def showValueLabel(self, checked): """ Whether or not the current value should be displayed on the slider. Parameters ---------- checked : bool """ self._show_value_label = checked if checked: self.value_label.show() else: self.value_label.hide() @Property(QSlider.TickPosition) def tickPosition(self): """ Where to draw tick marks for the slider. Returns ------- QSlider.TickPosition """ return self._slider.tickPosition() @tickPosition.setter def tickPosition(self, position): """ Where to draw tick marks for the slider. Parameter --------- position : QSlider.TickPosition """ self._slider.setTickPosition(position) @Property(bool) def userDefinedLimits(self): """ Wether or not to use limits defined by the user and not from the channel Returns ------- bool """ return self._user_defined_limits @userDefinedLimits.setter def userDefinedLimits(self, user_defined_limits): """ Wether or not to use limits defined by the user and not from the channel Parameters ---------- user_defined_limits : bool """ self._user_defined_limits = user_defined_limits self.reset_slider_limits() @Property(float) def userMinimum(self): """ Lower user defined limit value Returns ------- float """ return self._user_minimum @userMinimum.setter def userMinimum(self, new_min): """ Lower user defined limit value Parameters ---------- new_min : float """ self._user_minimum = float(new_min) if new_min is not None else None if self.userDefinedLimits: self.reset_slider_limits() @Property(float) def userMaximum(self): """ Upper user defined limit value Returns ------- float """ return self._user_maximum @userMaximum.setter def userMaximum(self, new_max): """ Upper user defined limit value Parameters ---------- new_max : float """ self._user_maximum = float(new_max) if new_max is not None else None if self.userDefinedLimits: self.reset_slider_limits() @property def minimum(self): """ The current value being used for the lower limit Returns ------- float """ if self.userDefinedLimits: return self._user_minimum return self._lower_ctrl_limit @property def maximum(self): """ The current value being used for the upper limit Returns ------- float """ if self.userDefinedLimits: return self._user_maximum return self._upper_ctrl_limit @Property(int) def num_steps(self): """ The number of steps on the slider Returns ------- int """ return self._num_steps @num_steps.setter def num_steps(self, new_steps): """ The number of steps on the slider Parameters ---------- new_steps : int """ self._num_steps = int(new_steps) self.reset_slider_limits()
class Dimension(QWidget): stateChanged = Signal(int) valueChanged = Signal() """ pass in dimension state: one of (State.X, State.Y, State.NONE, State.DISBALE) Can be run independently by: from mantidqt.widgets.sliceviewer.dimensionwidget import Dimension from qtpy.QtWidgets import QApplication app = QApplication([]) window = Dimension({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'}) window.show() app.exec_() """ def __init__(self, dim_info, number=0, state=State.NONE, parent=None): super(Dimension, self).__init__(parent) self.minimum = dim_info['minimum'] self.nbins = dim_info['number_of_bins'] self.width = dim_info['width'] self.number = number self.layout = QHBoxLayout(self) self.name = QLabel(dim_info['name']) self.units = QLabel(dim_info['units']) self.x = QPushButton('X') self.x.setFixedSize(32,32) self.x.setCheckable(True) self.x.clicked.connect(self.x_clicked) self.y = QPushButton('Y') self.y.setFixedSize(32,32) self.y.setCheckable(True) self.y.clicked.connect(self.y_clicked) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.nbins-1) self.slider.valueChanged.connect(self.slider_changed) self.spinbox = QDoubleSpinBox() self.spinbox.setDecimals(3) self.spinbox.setRange(self.get_bin_center(0), self.get_bin_center(self.nbins-1)) self.spinbox.setSingleStep(self.width) self.spinbox.valueChanged.connect(self.spinbox_changed) self.layout.addWidget(self.name) self.layout.addWidget(self.x) self.layout.addWidget(self.y) self.layout.addWidget(self.slider, stretch=1) self.layout.addStretch(0) self.layout.addWidget(self.spinbox) self.layout.addWidget(self.units) self.set_value(0) if self.nbins < 2: state = State.DISABLE self.set_state(state) def set_state(self, state): self.state = state if self.state == State.X: self.x.setChecked(True) self.y.setChecked(False) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.Y: self.x.setChecked(False) self.y.setChecked(True) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.NONE: self.x.setChecked(False) self.y.setChecked(False) self.slider.show() self.spinbox.show() self.units.show() else: self.x.setChecked(False) self.x.setDisabled(True) self.y.setChecked(False) self.y.setDisabled(True) self.slider.hide() self.spinbox.show() self.spinbox.setDisabled(True) self.units.show() def get_state(self): return self.state def x_clicked(self): old_state = self.state self.set_state(State.X) if self.state != old_state: self.stateChanged.emit(self.number) def y_clicked(self): old_state = self.state self.set_state(State.Y) if self.state != old_state: self.stateChanged.emit(self.number) def spinbox_changed(self): self.value = self.spinbox.value() self.update_slider() self.valueChanged.emit() def slider_changed(self): self.value = self.get_bin_center(self.slider.value()) self.update_spinbox() self.valueChanged.emit() def get_bin_center(self, n): return (n+0.5)*self.width+self.minimum def update_slider(self): i = (self.value-self.minimum)/self.width self.slider.setValue(int(min(max(i, 0), self.nbins-1))) def update_spinbox(self): self.spinbox.setValue(self.value) def set_value(self, value): self.value = value self.update_slider() self.update_spinbox() def get_value(self): return self.value
class EditGeometryProperties(PyDialog): force = True def __init__(self, data, win_parent=None): """ +------------------+ | Edit Actor Props | +------------------+------+ | Name1 | | Name2 | | Name3 | | Name4 | | | | Active_Name main | | Color box | | Line_Width 2 | | Point_Size 2 | | Bar_Scale 2 | | Opacity 0.5 | | Show/Hide | | | | Apply OK Cancel | +-------------------------+ """ PyDialog.__init__(self, data, win_parent) self.set_font_size(data['font_size']) del self.out_data['font_size'] self.setWindowTitle('Edit Geometry Properties') self.allow_update = True #default #self.win_parent = win_parent #self.out_data = data self.keys = sorted(data.keys()) self.keys = data.keys() keys = self.keys #nrows = len(keys) self.active_key = 'main' items = list(keys) header_labels = ['Groups'] table_model = Model(items, header_labels, self) view = SingleChoiceQTableView(self) #Call your custom QTableView here view.setModel(table_model) #if qt_version == 4: #view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.table = view #self.opacity_edit.valueChanged.connect(self.on_opacity) #mListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemClicked(QListWidgetItem*))); #self.table.itemClicked.connect(self.table.mouseDoubleClickEvent) actor_obj = data[self.active_key] name = actor_obj.name line_width = actor_obj.line_width point_size = actor_obj.point_size bar_scale = actor_obj.bar_scale opacity = actor_obj.opacity color = actor_obj.color show = actor_obj.is_visible self.representation = actor_obj.representation # table header = self.table.horizontalHeader() header.setStretchLastSection(True) self._default_is_apply = False self.name = QLabel("Name:") self.name_edit = QLineEdit(str(name)) self.name_edit.setDisabled(True) self.color = QLabel("Color:") self.color_edit = QPushButton() #self.color_edit.setFlat(True) color = self.out_data[self.active_key].color qcolor = QtGui.QColor() qcolor.setRgb(*color) #print('color =%s' % str(color)) palette = QtGui.QPalette(self.color_edit.palette()) # make a copy of the palette #palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Base, \ #qcolor) palette.setColor(QtGui.QPalette.Background, QtGui.QColor('blue')) # ButtonText self.color_edit.setPalette(palette) self.color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(color) + #"border:1px solid rgb(255, 170, 255); " "}") self.use_slider = True self.is_opacity_edit_active = False self.is_opacity_edit_slider_active = False self.is_line_width_edit_active = False self.is_line_width_edit_slider_active = False self.is_point_size_edit_active = False self.is_point_size_edit_slider_active = False self.is_bar_scale_edit_active = False self.is_bar_scale_edit_slider_active = False self.opacity = QLabel("Opacity:") self.opacity_edit = QDoubleSpinBox(self) self.opacity_edit.setRange(0.1, 1.0) self.opacity_edit.setDecimals(1) self.opacity_edit.setSingleStep(0.1) self.opacity_edit.setValue(opacity) if self.use_slider: self.opacity_slider_edit = QSlider(QtCore.Qt.Horizontal) self.opacity_slider_edit.setRange(1, 10) self.opacity_slider_edit.setValue(opacity * 10) self.opacity_slider_edit.setTickInterval(1) self.opacity_slider_edit.setTickPosition(QSlider.TicksBelow) self.line_width = QLabel("Line Width:") self.line_width_edit = QSpinBox(self) self.line_width_edit.setRange(1, MAX_LINE_WIDTH) self.line_width_edit.setSingleStep(1) self.line_width_edit.setValue(line_width) if self.use_slider: self.line_width_slider_edit = QSlider(QtCore.Qt.Horizontal) self.line_width_slider_edit.setRange(1, MAX_LINE_WIDTH) self.line_width_slider_edit.setValue(line_width) self.line_width_slider_edit.setTickInterval(1) self.line_width_slider_edit.setTickPosition(QSlider.TicksBelow) if self.representation in ['point', 'surface']: self.line_width.setEnabled(False) self.line_width_edit.setEnabled(False) self.line_width_slider_edit.setEnabled(False) self.point_size = QLabel("Point Size:") self.point_size_edit = QSpinBox(self) self.point_size_edit.setRange(1, MAX_POINT_SIZE) self.point_size_edit.setSingleStep(1) self.point_size_edit.setValue(point_size) self.point_size.setVisible(False) self.point_size_edit.setVisible(False) if self.use_slider: self.point_size_slider_edit = QSlider(QtCore.Qt.Horizontal) self.point_size_slider_edit.setRange(1, MAX_POINT_SIZE) self.point_size_slider_edit.setValue(point_size) self.point_size_slider_edit.setTickInterval(1) self.point_size_slider_edit.setTickPosition(QSlider.TicksBelow) self.point_size_slider_edit.setVisible(False) if self.representation in ['wire', 'surface']: self.point_size.setEnabled(False) self.point_size_edit.setEnabled(False) if self.use_slider: self.point_size_slider_edit.setEnabled(False) self.bar_scale = QLabel("Bar Scale:") self.bar_scale_edit = QDoubleSpinBox(self) #self.bar_scale_edit.setRange(0.01, 1.0) # was 0.1 #self.bar_scale_edit.setRange(0.05, 5.0) self.bar_scale_edit.setDecimals(1) #self.bar_scale_edit.setSingleStep(bar_scale / 10.) self.bar_scale_edit.setSingleStep(0.1) self.bar_scale_edit.setValue(bar_scale) #if self.use_slider: #self.bar_scale_slider_edit = QSlider(QtCore.Qt.Horizontal) #self.bar_scale_slider_edit.setRange(1, 100) # 1/0.05 = 100/5.0 #self.bar_scale_slider_edit.setValue(opacity * 0.05) #self.bar_scale_slider_edit.setTickInterval(10) #self.bar_scale_slider_edit.setTickPosition(QSlider.TicksBelow) if self.representation != 'bar': self.bar_scale.setEnabled(False) self.bar_scale_edit.setEnabled(False) self.bar_scale.setVisible(False) self.bar_scale_edit.setVisible(False) #self.bar_scale_slider_edit.setVisible(False) #self.bar_scale_slider_edit.setEnabled(False) # show/hide self.checkbox_show = QCheckBox("Show") self.checkbox_hide = QCheckBox("Hide") self.checkbox_show.setChecked(show) self.checkbox_hide.setChecked(not show) if name == 'main': self.color.setEnabled(False) self.color_edit.setEnabled(False) self.point_size.setEnabled(False) self.point_size_edit.setEnabled(False) if self.use_slider: self.point_size_slider_edit.setEnabled(False) self.cancel_button = QPushButton("Close") self.create_layout() self.set_connections() def on_delete(self, irow): """deletes an actor based on the row number""" if irow == 0: # main return nkeys = len(self.keys) if nkeys in [0, 1]: return name = self.keys[irow] nrows = nkeys - 1 self.keys.pop(irow) header_labels = ['Groups'] table_model = Model(self.keys, header_labels, self) self.table.setModel(table_model) if len(self.keys) == 0: self.update() self.set_as_null() return if irow == nrows: irow -= 1 new_name = self.keys[irow] self.update_active_name(new_name) if self.is_gui: self.win_parent.delete_actor(name) def set_as_null(self): """sets the null case""" self.name.setVisible(False) self.name_edit.setVisible(False) self.color.setVisible(False) self.color_edit.setVisible(False) self.line_width.setVisible(False) self.line_width_edit.setVisible(False) self.point_size.setVisible(False) self.point_size_edit.setVisible(False) self.bar_scale.setVisible(False) self.bar_scale_edit.setVisible(False) self.opacity.setVisible(False) self.opacity_edit.setVisible(False) self.opacity_slider_edit.setVisible(False) self.point_size_slider_edit.setVisible(False) self.line_width_slider_edit.setVisible(False) self.checkbox_show.setVisible(False) self.checkbox_hide.setVisible(False) def on_update_geometry_properties_window(self, data): """Not Implemented""" return #new_keys = sorted(data.keys()) #if self.active_key in new_keys: #i = new_keys.index(self.active_key) #else: #i = 0 #self.table.update_data(new_keys) #self.out_data = data #self.update_active_key(i) def update_active_key(self, index): """ Parameters ---------- index : PyQt4.QtCore.QModelIndex the index of the list Internal Parameters ------------------- name : str the name of obj obj : CoordProperties, AltGeometry the storage object for things like line_width, point_size, etc. """ name = str(index.data()) #print('name = %r' % name) #i = self.keys.index(self.active_key) self.update_active_name(name) def update_active_name(self, name): self.active_key = name self.name_edit.setText(name) obj = self.out_data[name] if isinstance(obj, CoordProperties): opacity = 1.0 representation = 'coord' is_visible = obj.is_visible elif isinstance(obj, AltGeometry): line_width = obj.line_width point_size = obj.point_size bar_scale = obj.bar_scale opacity = obj.opacity representation = obj.representation is_visible = obj.is_visible self.color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(obj.color) + #"border:1px solid rgb(255, 170, 255); " "}") self.allow_update = False self.force = False self.line_width_edit.setValue(line_width) self.point_size_edit.setValue(point_size) self.bar_scale_edit.setValue(bar_scale) self.force = True self.allow_update = True else: raise NotImplementedError(obj) #allowed_representations = [ #'main', 'surface', 'coord', 'toggle', 'wire', 'point', 'bar'] if self.representation != representation: self.representation = representation #if representation not in allowed_representations: #msg = 'name=%r; representation=%r is invalid\nrepresentations=%r' % ( #name, representation, allowed_representations) if self.representation == 'coord': self.color.setVisible(False) self.color_edit.setVisible(False) self.line_width.setVisible(False) self.line_width_edit.setVisible(False) self.point_size.setVisible(False) self.point_size_edit.setVisible(False) self.bar_scale.setVisible(False) self.bar_scale_edit.setVisible(False) self.opacity.setVisible(False) self.opacity_edit.setVisible(False) if self.use_slider: self.opacity_slider_edit.setVisible(False) self.point_size_slider_edit.setVisible(False) self.line_width_slider_edit.setVisible(False) #self.bar_scale_slider_edit.setVisible(False) else: self.color.setVisible(True) self.color_edit.setVisible(True) self.line_width.setVisible(True) self.line_width_edit.setVisible(True) self.point_size.setVisible(True) self.point_size_edit.setVisible(True) self.bar_scale.setVisible(True) #self.bar_scale_edit.setVisible(True) self.opacity.setVisible(True) self.opacity_edit.setVisible(True) if self.use_slider: self.opacity_slider_edit.setVisible(True) self.line_width_slider_edit.setVisible(True) self.point_size_slider_edit.setVisible(True) #self.bar_scale_slider_edit.setVisible(True) if name == 'main': self.color.setEnabled(False) self.color_edit.setEnabled(False) self.point_size.setEnabled(False) self.point_size_edit.setEnabled(False) self.line_width.setEnabled(True) self.line_width_edit.setEnabled(True) self.bar_scale.setEnabled(False) self.bar_scale_edit.setEnabled(False) show_points = False show_line_width = True show_bar_scale = False if self.use_slider: self.line_width_slider_edit.setEnabled(True) #self.bar_scale_slider_edit.setVisible(False) else: self.color.setEnabled(True) self.color_edit.setEnabled(True) show_points = False if self.representation in ['point', 'wire+point']: show_points = True show_line_width = False if self.representation in ['wire', 'wire+point', 'bar', 'toggle']: show_line_width = True if representation == 'bar': show_bar_scale = True else: show_bar_scale = False #self.bar_scale_button.setVisible(show_bar_scale) #self.bar_scale_edit.setSingleStep(bar_scale / 10.) #if self.use_slider: #self.bar_scale_slider_edit.setEnabled(False) self.point_size.setEnabled(show_points) self.point_size_edit.setEnabled(show_points) self.point_size.setVisible(show_points) self.point_size_edit.setVisible(show_points) self.line_width.setEnabled(show_line_width) self.line_width_edit.setEnabled(show_line_width) self.bar_scale.setEnabled(show_bar_scale) self.bar_scale_edit.setEnabled(show_bar_scale) self.bar_scale.setVisible(show_bar_scale) self.bar_scale_edit.setVisible(show_bar_scale) if self.use_slider: self.point_size_slider_edit.setEnabled(show_points) self.point_size_slider_edit.setVisible(show_points) self.line_width_slider_edit.setEnabled(show_line_width) #if self.representation in ['wire', 'surface']: self.opacity_edit.setValue(opacity) #if self.use_slider: #self.opacity_slider_edit.setValue(opacity*10) self.checkbox_show.setChecked(is_visible) self.checkbox_hide.setChecked(not is_visible) passed = self.on_validate() #self.on_apply(force=True) # TODO: was turned on...do I want this??? #self.allow_update = True def create_layout(self): ok_cancel_box = QHBoxLayout() ok_cancel_box.addWidget(self.cancel_button) grid = QGridLayout() irow = 0 grid.addWidget(self.name, irow, 0) grid.addWidget(self.name_edit, irow, 1) irow += 1 grid.addWidget(self.color, irow, 0) grid.addWidget(self.color_edit, irow, 1) irow += 1 grid.addWidget(self.opacity, irow, 0) if self.use_slider: grid.addWidget(self.opacity_edit, irow, 2) grid.addWidget(self.opacity_slider_edit, irow, 1) else: grid.addWidget(self.opacity_edit, irow, 1) irow += 1 grid.addWidget(self.line_width, irow, 0) if self.use_slider: grid.addWidget(self.line_width_edit, irow, 2) grid.addWidget(self.line_width_slider_edit, irow, 1) else: grid.addWidget(self.line_width_edit, irow, 1) irow += 1 grid.addWidget(self.point_size, irow, 0) if self.use_slider: grid.addWidget(self.point_size_edit, irow, 2) grid.addWidget(self.point_size_slider_edit, irow, 1) else: grid.addWidget(self.point_size_edit, irow, 1) irow += 1 grid.addWidget(self.bar_scale, irow, 0) if self.use_slider and 0: grid.addWidget(self.bar_scale_edit, irow, 2) grid.addWidget(self.bar_scale_slider_edit, irow, 1) else: grid.addWidget(self.bar_scale_edit, irow, 1) irow += 1 checkboxs = QButtonGroup(self) checkboxs.addButton(self.checkbox_show) checkboxs.addButton(self.checkbox_hide) vbox = QVBoxLayout() vbox.addWidget(self.table, stretch=1) vbox.addLayout(grid) vbox1 = QVBoxLayout() vbox1.addWidget(self.checkbox_show) vbox1.addWidget(self.checkbox_hide) vbox.addLayout(vbox1) vbox.addStretch() #vbox.addWidget(self.check_apply) vbox.addLayout(ok_cancel_box) self.setLayout(vbox) def set_connections(self): self.opacity_edit.valueChanged.connect(self.on_opacity) self.line_width_edit.valueChanged.connect(self.on_line_width) self.point_size_edit.valueChanged.connect(self.on_point_size) self.bar_scale_edit.valueChanged.connect(self.on_bar_scale) if self.use_slider: self.opacity_slider_edit.valueChanged.connect(self.on_opacity_slider) self.line_width_slider_edit.valueChanged.connect(self.on_line_width_slider) self.point_size_slider_edit.valueChanged.connect(self.on_point_size_slider) #self.bar_scale_slider_edit.valueChanged.connect(self.on_bar_scale_slider) # self.connect(self.opacity_edit, QtCore.SIGNAL('clicked()'), self.on_opacity) # self.connect(self.line_width, QtCore.SIGNAL('clicked()'), self.on_line_width) # self.connect(self.point_size, QtCore.SIGNAL('clicked()'), self.on_point_size) if qt_version == 4: self.connect(self, QtCore.SIGNAL('triggered()'), self.closeEvent) self.color_edit.clicked.connect(self.on_color) self.checkbox_show.clicked.connect(self.on_show) self.checkbox_hide.clicked.connect(self.on_hide) self.cancel_button.clicked.connect(self.on_cancel) # closeEvent def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.close() def closeEvent(self, event): self.on_cancel() def on_color(self): """called when the user clicks on the color box""" name = self.active_key obj = self.out_data[name] rgb_color_ints = obj.color msg = name col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self, "Choose a %s color" % msg) if col.isValid(): color_float = col.getRgbF()[:3] obj.color = color_float color_int = [int(colori * 255) for colori in color_float] self.color_edit.setStyleSheet("QPushButton {" "background-color: rgb(%s, %s, %s);" % tuple(color_int) + #"border:1px solid rgb(255, 170, 255); " "}") self.on_apply(force=self.force) #print(self.allow_update) def on_show(self): """shows the actor""" name = self.active_key is_checked = self.checkbox_show.isChecked() self.out_data[name].is_visible = is_checked self.on_apply(force=self.force) def on_hide(self): """hides the actor""" name = self.active_key is_checked = self.checkbox_hide.isChecked() self.out_data[name].is_visible = not is_checked self.on_apply(force=self.force) def on_line_width(self): """increases/decreases the wireframe (for solid bodies) or the bar thickness""" self.is_line_width_edit_active = True name = self.active_key line_width = self.line_width_edit.value() self.out_data[name].line_width = line_width if not self.is_line_width_edit_slider_active: if self.use_slider: self.line_width_slider_edit.setValue(line_width) self.is_line_width_edit_active = False self.on_apply(force=self.force) self.is_line_width_edit_active = False def on_line_width_slider(self): """increases/decreases the wireframe (for solid bodies) or the bar thickness""" self.is_line_width_edit_slider_active = True #name = self.active_key line_width = self.line_width_slider_edit.value() if not self.is_line_width_edit_active: self.line_width_edit.setValue(line_width) self.is_line_width_edit_slider_active = False def on_point_size(self): """increases/decreases the point size""" self.is_point_size_edit_active = True name = self.active_key point_size = self.point_size_edit.value() self.out_data[name].point_size = point_size if not self.is_point_size_edit_slider_active: if self.use_slider: self.point_size_slider_edit.setValue(point_size) self.is_point_size_edit_active = False self.on_apply(force=self.force) self.is_point_size_edit_active = False def on_point_size_slider(self): """increases/decreases the point size""" self.is_point_size_edit_slider_active = True #name = self.active_key point_size = self.point_size_slider_edit.value() if not self.is_point_size_edit_active: self.point_size_edit.setValue(point_size) self.is_point_size_edit_slider_active = False def on_bar_scale(self): """ Vectors start at some xyz coordinate and can increase in length. Increases/decreases the length scale factor. """ self.is_bar_scale_edit_active = True name = self.active_key float_bar_scale = self.bar_scale_edit.value() self.out_data[name].bar_scale = float_bar_scale if not self.is_bar_scale_edit_slider_active: #int_bar_scale = int(round(float_bar_scale * 20, 0)) #if self.use_slider: #self.bar_scale_slider_edit.setValue(int_bar_scale) self.is_bar_scale_edit_active = False self.on_apply(force=self.force) self.is_bar_scale_edit_active = False def on_bar_scale_slider(self): """ Vectors start at some xyz coordinate and can increase in length. Increases/decreases the length scale factor. """ self.is_bar_scale_edit_slider_active = True #name = self.active_key int_bar_scale = self.bar_scale_slider_edit.value() if not self.is_bar_scale_edit_active: float_bar_scale = int_bar_scale / 20. self.bar_scale_edit.setValue(float_bar_scale) self.is_bar_scale_edit_slider_active = False def on_opacity(self): """ opacity = 1.0 (solid/opaque) opacity = 0.0 (invisible) """ self.is_opacity_edit_active = True name = self.active_key float_opacity = self.opacity_edit.value() self.out_data[name].opacity = float_opacity if not self.is_opacity_edit_slider_active: int_opacity = int(round(float_opacity * 10, 0)) if self.use_slider: self.opacity_slider_edit.setValue(int_opacity) self.is_opacity_edit_active = False self.on_apply(force=self.force) self.is_opacity_edit_active = False def on_opacity_slider(self): """ opacity = 1.0 (solid/opaque) opacity = 0.0 (invisible) """ self.is_opacity_edit_slider_active = True #name = self.active_key int_opacity = self.opacity_slider_edit.value() if not self.is_opacity_edit_active: float_opacity = int_opacity / 10. self.opacity_edit.setValue(float_opacity) self.is_opacity_edit_slider_active = False def on_validate(self): self.out_data['clicked_ok'] = True self.out_data['clicked_cancel'] = False old_obj = self.out_data[self.active_key] old_obj.line_width = self.line_width_edit.value() old_obj.point_size = self.point_size_edit.value() old_obj.bar_scale = self.bar_scale_edit.value() old_obj.opacity = self.opacity_edit.value() #old_obj.color = self.color_edit old_obj.is_visible = self.checkbox_show.isChecked() return True #name_value, flag0 = self.check_name(self.name_edit) #ox_value, flag1 = self.check_float(self.transparency_edit) #if flag0 and flag1: #self.out_data['clicked_ok'] = True #return True #return False @property def is_gui(self): return hasattr(self.win_parent, 'on_update_geometry_properties') def on_apply(self, force=False): passed = self.on_validate() #print("passed=%s force=%s allow=%s" % (passed, force, self.allow_update)) if (passed or force) and self.allow_update and self.is_gui: #print('obj = %s' % self.out_data[self.active_key]) self.win_parent.on_update_geometry_properties(self.out_data, name=self.active_key) return passed def on_cancel(self): passed = self.on_apply(force=True) if passed: self.close()
class MiscellaneousLauncher(QWidget): def __init__(self, parent): super().__init__() # set title self.setWindowTitle(config.thisTranslation["cp4"]) # set up variables self.parent = parent # setup interface self.setupUI() def setupUI(self): mainLayout = QGridLayout() leftLayout = QVBoxLayout() rightLayout = QVBoxLayout() self.highLightLauncher = HighlightLauncher(self) leftLayout.addWidget(self.highLightLauncher) rightLayout.addWidget(self.noteEditor()) rightLayout.addWidget(self.textToSpeechUtility()) rightLayout.addWidget(self.utilities()) rightLayout.addStretch() mainLayout.addLayout(leftLayout, 0, 0, 1, 2) mainLayout.addLayout(rightLayout, 0, 2, 1, 1) self.setLayout(mainLayout) def noteEditor(self): box = QGroupBox(config.thisTranslation["note_editor"]) subLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["menu7_create"]) button.setToolTip(config.thisTranslation["menu7_create"]) button.clicked.connect(self.parent.parent.createNewNoteFile) subLayout.addWidget(button) button = QPushButton(config.thisTranslation["menu7_open"]) button.setToolTip(config.thisTranslation["menu7_open"]) button.clicked.connect(self.parent.parent.openTextFileDialog) subLayout.addWidget(button) box.setLayout(subLayout) return box def utilities(self): box = QGroupBox(config.thisTranslation["utilities"]) subLayout = QHBoxLayout() button = QPushButton(config.thisTranslation["presentation"]) button.setToolTip(config.thisTranslation["presentation"]) button.clicked.connect( lambda: self.parent.parent.runPlugin("Presentation")) subLayout.addWidget(button) if config.isYoutubeDownloaderInstalled: button = QPushButton(config.thisTranslation["youtube_utility"]) button.setToolTip(config.thisTranslation["youtube_utility"]) button.clicked.connect(self.parent.parent.openYouTube) subLayout.addWidget(button) box.setLayout(subLayout) return box def textToSpeechUtility(self): box = QGroupBox(config.thisTranslation["tts_utility"]) layout = QVBoxLayout() subLayout = QHBoxLayout() self.ttsEdit = QLineEdit() self.ttsEdit.setClearButtonEnabled(True) self.ttsEdit.setToolTip(config.thisTranslation["enter_text_here"]) self.ttsEdit.returnPressed.connect(self.speakText) subLayout.addWidget(self.ttsEdit) layout.addLayout(subLayout) self.ttsSlider = QSlider(Qt.Horizontal) self.ttsSlider.setToolTip(config.thisTranslation["adjustSpeed"]) self.ttsSlider.setMinimum(10) self.ttsSlider.setMaximum(310) self.ttsSlider.setValue(config.espeakSpeed if config.espeak else ( 160 + config.qttsSpeed * 150)) self.ttsSlider.valueChanged.connect( self.changeEspeakSpeed if config.espeak else self.changeQttsSpeed) layout.addWidget(self.ttsSlider) subLayout = QHBoxLayout() self.languageCombo = QComboBox() subLayout.addWidget(self.languageCombo) if config.espeak: languages = TtsLanguages().isoLang2epeakLang else: languages = TtsLanguages().isoLang2qlocaleLang self.languageCodes = list(languages.keys()) for code in self.languageCodes: self.languageCombo.addItem(languages[code][1]) # Check if selected tts engine has the language user specify. if not (config.ttsDefaultLangauge in self.languageCodes): config.ttsDefaultLangauge = "en" # Set initial index # It is essential. Otherwise, default tts language is changed by defaultTtsLanguageChanged method. ttsLanguageIndex = self.languageCodes.index(config.ttsDefaultLangauge) self.languageCombo.setCurrentIndex(ttsLanguageIndex) # Change default tts language as users select a new language self.languageCombo.currentIndexChanged.connect( self.defaultTtsLanguageChanged) button = QPushButton(config.thisTranslation["speak"]) button.setToolTip(config.thisTranslation["speak"]) button.clicked.connect(self.speakText) subLayout.addWidget(button) button = QPushButton(config.thisTranslation["stop"]) button.setToolTip(config.thisTranslation["stop"]) button.clicked.connect( self.parent.parent.textCommandParser.stopTtsAudio) subLayout.addWidget(button) layout.addLayout(subLayout) box.setLayout(layout) return box def defaultTtsLanguageChanged(self, index): config.ttsDefaultLangauge = self.languageCodes[index] def speakText(self): text = self.ttsEdit.text() if text: if config.isTtsInstalled: if ":::" in text: text = text.split(":::")[-1] command = "SPEAK:::{0}:::{1}".format( self.languageCodes[self.languageCombo.currentIndex()], text) self.parent.isRefreshing = True self.parent.runTextCommand(command) self.parent.isRefreshing = False else: self.parent.displayMessage( config.thisTranslation["message_noSupport"]) else: self.parent.displayMessage( config.thisTranslation["enterTextFirst"]) def changeQttsSpeed(self, value): config.qttsSpeed = (value * (1.5 / 300) - .5) def changeEspeakSpeed(self, value): config.espeakSpeed = value def refresh(self): ttsLanguageIndex = self.languageCodes.index(config.ttsDefaultLangauge) self.languageCombo.setCurrentIndex(ttsLanguageIndex) self.highLightLauncher.refresh()
def __init__(self, layer): super().__init__(layer) self.layer.events.n_dimensional.connect(self._on_n_dim_change) self.layer.events.symbol.connect(self._on_symbol_change) self.layer.events.size.connect(self._on_size_change) self.layer.events.edge_color.connect(self._on_edge_color_change) self.layer.events.face_color.connect(self._on_face_color_change) sld = QSlider(Qt.Horizontal, self) sld.setFocusPolicy(Qt.NoFocus) sld.setFixedWidth(110) sld.setMinimum(0) sld.setMaximum(100) sld.setSingleStep(1) value = self.layer.size if isinstance(value, Iterable): if isinstance(value, list): value = np.asarray(value) value = value.mean() sld.setValue(int(value)) sld.valueChanged[int].connect(lambda value=sld: self.changeSize(value)) self.sizeSlider = sld self.grid_layout.addWidget(QLabel('size:'), 3, 0) self.grid_layout.addWidget(sld, 3, 1) face_comboBox = QComboBox() colors = self.layer._colors for c in colors: face_comboBox.addItem(c) index = face_comboBox.findText(self.layer.face_color, Qt.MatchFixedString) face_comboBox.setCurrentIndex(index) face_comboBox.activated[str].connect( lambda text=face_comboBox: self.changeFaceColor(text)) self.faceComboBox = face_comboBox self.grid_layout.addWidget(QLabel('face_color:'), 4, 0) self.grid_layout.addWidget(face_comboBox, 4, 1) edge_comboBox = QComboBox() colors = self.layer._colors for c in colors: edge_comboBox.addItem(c) index = edge_comboBox.findText(self.layer.edge_color, Qt.MatchFixedString) edge_comboBox.setCurrentIndex(index) edge_comboBox.activated[str].connect( lambda text=edge_comboBox: self.changeEdgeColor(text)) self.edgeComboBox = edge_comboBox self.grid_layout.addWidget(QLabel('edge_color:'), 5, 0) self.grid_layout.addWidget(edge_comboBox, 5, 1) symbol_comboBox = QComboBox() for s in Symbol: symbol_comboBox.addItem(str(s)) index = symbol_comboBox.findText(self.layer.symbol, Qt.MatchFixedString) symbol_comboBox.setCurrentIndex(index) symbol_comboBox.activated[str].connect( lambda text=symbol_comboBox: self.changeSymbol(text)) self.symbolComboBox = symbol_comboBox self.grid_layout.addWidget(QLabel('symbol:'), 6, 0) self.grid_layout.addWidget(symbol_comboBox, 6, 1) ndim_cb = QCheckBox() ndim_cb.setToolTip('N-dimensional markers') ndim_cb.setChecked(self.layer.n_dimensional) ndim_cb.stateChanged.connect( lambda state=ndim_cb: self.change_ndim(state)) self.ndimCheckBox = ndim_cb self.grid_layout.addWidget(QLabel('n-dim:'), 7, 0) self.grid_layout.addWidget(ndim_cb, 7, 1) self.setExpanded(False)
def __init__(self, layer): super().__init__(layer) self.layer.events.mode.connect(self._on_mode_change) self.layer.events.n_dimensional.connect(self._on_n_dimensional_change) self.layer.events.symbol.connect(self._on_symbol_change) self.layer.events.size.connect(self._on_size_change) self.layer.events.current_edge_color.connect( self._on_current_edge_color_change) self.layer.events.current_face_color.connect( self._on_current_face_color_change) self.layer.events.editable.connect(self._on_editable_change) self.layer.text.events.visible.connect(self._on_text_visibility_change) sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(1) sld.setMaximum(100) sld.setSingleStep(1) value = self.layer.current_size sld.setValue(int(value)) sld.valueChanged.connect(self.changeSize) self.sizeSlider = sld self.faceColorEdit = QColorSwatchEdit( initial_color=self.layer.current_face_color, tooltip='click to set current face color', ) self.edgeColorEdit = QColorSwatchEdit( initial_color=self.layer.current_edge_color, tooltip='click to set current edge color', ) self.faceColorEdit.color_changed.connect(self.changeFaceColor) self.edgeColorEdit.color_changed.connect(self.changeEdgeColor) symbol_comboBox = QComboBox() symbol_comboBox.addItems([str(s) for s in Symbol]) index = symbol_comboBox.findText(self.layer.symbol, Qt.MatchFixedString) symbol_comboBox.setCurrentIndex(index) symbol_comboBox.activated[str].connect(self.changeSymbol) self.symbolComboBox = symbol_comboBox ndim_cb = QCheckBox() ndim_cb.setToolTip('N-dimensional points') ndim_cb.setChecked(self.layer.n_dimensional) ndim_cb.stateChanged.connect(self.change_ndim) self.ndimCheckBox = ndim_cb self.select_button = QtModeRadioButton(layer, 'select_points', Mode.SELECT, tooltip='Select points') self.addition_button = QtModeRadioButton(layer, 'add_points', Mode.ADD, tooltip='Add points') self.panzoom_button = QtModeRadioButton(layer, 'pan_zoom', Mode.PAN_ZOOM, tooltip='Pan/zoom', checked=True) self.delete_button = QtModePushButton( layer, 'delete_shape', slot=self.layer.remove_selected, tooltip='Delete selected points', ) text_disp_cb = QCheckBox() text_disp_cb.setToolTip('toggle text visibility') text_disp_cb.setChecked(self.layer.text.visible) text_disp_cb.stateChanged.connect(self.change_text_visibility) self.textDispCheckBox = text_disp_cb self.button_group = QButtonGroup(self) self.button_group.addButton(self.select_button) self.button_group.addButton(self.addition_button) self.button_group.addButton(self.panzoom_button) button_row = QHBoxLayout() button_row.addStretch(1) button_row.addWidget(self.delete_button) button_row.addWidget(self.addition_button) button_row.addWidget(self.select_button) button_row.addWidget(self.panzoom_button) button_row.setContentsMargins(0, 0, 0, 5) button_row.setSpacing(4) # grid_layout created in QtLayerControls # addWidget(widget, row, column, [row_span, column_span]) self.grid_layout.addLayout(button_row, 0, 1) self.grid_layout.addWidget(QLabel('opacity:'), 1, 0) self.grid_layout.addWidget(self.opacitySlider, 1, 1) self.grid_layout.addWidget(QLabel('point size:'), 2, 0) self.grid_layout.addWidget(self.sizeSlider, 2, 1) self.grid_layout.addWidget(QLabel('blending:'), 3, 0) self.grid_layout.addWidget(self.blendComboBox, 3, 1) self.grid_layout.addWidget(QLabel('symbol:'), 4, 0) self.grid_layout.addWidget(self.symbolComboBox, 4, 1) self.grid_layout.addWidget(QLabel('face color:'), 5, 0) self.grid_layout.addWidget(self.faceColorEdit, 5, 1) self.grid_layout.addWidget(QLabel('edge color:'), 6, 0) self.grid_layout.addWidget(self.edgeColorEdit, 6, 1) self.grid_layout.addWidget(QLabel('display text:'), 7, 0) self.grid_layout.addWidget(self.textDispCheckBox, 7, 1) self.grid_layout.addWidget(QLabel('n-dim:'), 8, 0) self.grid_layout.addWidget(self.ndimCheckBox, 8, 1) self.grid_layout.setRowStretch(9, 1) self.grid_layout.setColumnStretch(1, 1) self.grid_layout.setSpacing(4)
class Dimension(QWidget): stateChanged = Signal(int) valueChanged = Signal() """ pass in dimension state: one of (State.X, State.Y, State.NONE, State.DISABLE) Can be run independently by: from mantidqt.widgets.sliceviewer.dimensionwidget import Dimension from qtpy.QtWidgets import QApplication app = QApplication([]) window = Dimension({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'}) window.show() app.exec_() """ def __init__(self, dim_info, number=0, state=State.NONE, parent=None): super().__init__(parent) self.minimum = dim_info['minimum'] self.nbins = dim_info['number_of_bins'] self.width = dim_info['width'] self.number = number self.layout = QHBoxLayout(self) self.name = QLabel(dim_info['name']) self.units = QLabel(dim_info['units']) self.x = QPushButton('X') self.x.setFixedSize(32, 32) self.x.setCheckable(True) self.x.clicked.connect(self.x_clicked) self.y = QPushButton('Y') self.y.setFixedSize(32, 32) self.y.setCheckable(True) self.y.clicked.connect(self.y_clicked) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.nbins - 1) self.slider.valueChanged.connect(self.slider_changed) self.spinbox = QDoubleSpinBox() self.spinbox.setDecimals(3) self.spinbox.setRange(self.get_bin_center(0), self.get_bin_center(self.nbins - 1)) self.spinbox.setSingleStep(self.width) self.spinbox.editingFinished.connect(self.spinbox_changed) self.layout.addWidget(self.name) self.layout.addWidget(self.x) self.layout.addWidget(self.y) self.layout.addWidget(self.slider, stretch=1) self.layout.addStretch(0) self.layout.addWidget(self.spinbox) self.layout.addWidget(self.units) self.set_value(0) if self.nbins < 2: state = State.DISABLE self.set_state(state) def set_state(self, state): self.state = state if self.state == State.X: self.x.setChecked(True) self.y.setChecked(False) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.Y: self.x.setChecked(False) self.y.setChecked(True) self.slider.hide() self.spinbox.hide() self.units.hide() elif self.state == State.NONE: self.x.setChecked(False) self.y.setChecked(False) self.slider.show() self.spinbox.show() self.units.show() else: self.x.setChecked(False) self.x.setDisabled(True) self.y.setChecked(False) self.y.setDisabled(True) self.slider.hide() self.spinbox.show() self.spinbox.setDisabled(True) self.units.show() def get_state(self): return self.state def x_clicked(self): old_state = self.state self.set_state(State.X) if self.state != old_state: self.stateChanged.emit(self.number) def y_clicked(self): old_state = self.state self.set_state(State.Y) if self.state != old_state: self.stateChanged.emit(self.number) def spinbox_changed(self): self.value = self.spinbox.value() self.update_slider() def slider_changed(self): self.value = self.get_bin_center(self.slider.value()) self.update_spinbox() self.valueChanged.emit() def get_bin_center(self, n): return (n + 0.5) * self.width + self.minimum def update_slider(self): i = (self.value - self.minimum) / self.width self.slider.setValue(int(min(max(i, 0), self.nbins - 1))) def update_spinbox(self): self.spinbox.setValue(self.value) def set_value(self, value): self.value = value self.update_slider() self.update_spinbox() def get_value(self): return self.value
class QtTracksControls(QtLayerControls): """Qt view and controls for the Tracks layer. Parameters ---------- layer : napari.layers.Tracks An instance of a Tracks layer. Attributes ---------- grid_layout : qtpy.QtWidgets.QGridLayout Layout of Qt widget controls for the layer. layer : layers.Tracks An instance of a Tracks layer. """ layer: 'napari.layers.Tracks' def __init__(self, layer): super().__init__(layer) # NOTE(arl): there are no events fired for changing checkboxes self.layer.events.tail_width.connect(self._on_tail_width_change) self.layer.events.tail_length.connect(self._on_tail_length_change) self.layer.events.head_length.connect(self._on_head_length_change) self.layer.events.properties.connect(self._on_properties_change) self.layer.events.colormap.connect(self._on_colormap_change) self.layer.events.color_by.connect(self._on_color_by_change) # combo box for track coloring, we can get these from the properties # keys self.color_by_combobox = QComboBox() self.color_by_combobox.addItems(self.layer.properties_to_color_by) self.colormap_combobox = QComboBox() for name, colormap in AVAILABLE_COLORMAPS.items(): display_name = colormap._display_name self.colormap_combobox.addItem(display_name, name) # slider for track head length self.head_length_slider = QSlider(Qt.Horizontal) self.head_length_slider.setFocusPolicy(Qt.NoFocus) self.head_length_slider.setMinimum(0) self.head_length_slider.setMaximum(self.layer._max_length) self.head_length_slider.setSingleStep(1) # slider for track tail length self.tail_length_slider = QSlider(Qt.Horizontal) self.tail_length_slider.setFocusPolicy(Qt.NoFocus) self.tail_length_slider.setMinimum(1) self.tail_length_slider.setMaximum(self.layer._max_length) self.tail_length_slider.setSingleStep(1) # slider for track edge width self.tail_width_slider = QSlider(Qt.Horizontal) self.tail_width_slider.setFocusPolicy(Qt.NoFocus) self.tail_width_slider.setMinimum(1) self.tail_width_slider.setMaximum(int(2 * self.layer._max_width)) self.tail_width_slider.setSingleStep(1) # checkboxes for display self.id_checkbox = QCheckBox() self.tail_checkbox = QCheckBox() self.tail_checkbox.setChecked(True) self.graph_checkbox = QCheckBox() self.graph_checkbox.setChecked(True) self.tail_width_slider.valueChanged.connect(self.change_tail_width) self.tail_length_slider.valueChanged.connect(self.change_tail_length) self.head_length_slider.valueChanged.connect(self.change_head_length) self.tail_checkbox.stateChanged.connect(self.change_display_tail) self.id_checkbox.stateChanged.connect(self.change_display_id) self.graph_checkbox.stateChanged.connect(self.change_display_graph) self.color_by_combobox.currentTextChanged.connect(self.change_color_by) self.colormap_combobox.currentTextChanged.connect(self.change_colormap) self.layout().addRow(trans._('color by:'), self.color_by_combobox) self.layout().addRow(trans._('colormap:'), self.colormap_combobox) self.layout().addRow(trans._('blending:'), self.blendComboBox) self.layout().addRow(trans._('opacity:'), self.opacitySlider) self.layout().addRow(trans._('tail width:'), self.tail_width_slider) self.layout().addRow(trans._('tail length:'), self.tail_length_slider) self.layout().addRow(trans._('head length:'), self.head_length_slider) self.layout().addRow(trans._('tail:'), self.tail_checkbox) self.layout().addRow(trans._('show ID:'), self.id_checkbox) self.layout().addRow(trans._('graph:'), self.graph_checkbox) self._on_tail_length_change() self._on_tail_width_change() self._on_colormap_change() self._on_color_by_change() def _on_tail_width_change(self): """Receive layer model track line width change event and update slider.""" with self.layer.events.tail_width.blocker(): value = int(2 * self.layer.tail_width) self.tail_width_slider.setValue(value) def _on_tail_length_change(self): """Receive layer model track line width change event and update slider.""" with self.layer.events.tail_length.blocker(): value = self.layer.tail_length self.tail_length_slider.setValue(value) def _on_head_length_change(self): """Receive layer model track line width change event and update slider.""" with self.layer.events.head_length.blocker(): value = self.layer.head_length self.head_length_slider.setValue(value) def _on_properties_change(self): """Change the properties that can be used to color the tracks.""" with self.layer.events.properties.blocker(): with qt_signals_blocked(self.color_by_combobox): self.color_by_combobox.clear() self.color_by_combobox.addItems(self.layer.properties_to_color_by) def _on_colormap_change(self): """Receive layer model colormap change event and update combobox.""" with self.layer.events.colormap.blocker(): self.colormap_combobox.setCurrentIndex( self.colormap_combobox.findData(self.layer.colormap)) def _on_color_by_change(self): """Receive layer model color_by change event and update combobox.""" with self.layer.events.color_by.blocker(): color_by = self.layer.color_by idx = self.color_by_combobox.findText(color_by, Qt.MatchFixedString) self.color_by_combobox.setCurrentIndex(idx) def change_tail_width(self, value): """Change track line width of shapes on the layer model. Parameters ---------- value : float Line width of track tails. """ self.layer.tail_width = float(value) / 2.0 def change_tail_length(self, value): """Change edge line backward length of shapes on the layer model. Parameters ---------- value : int Line length of track tails. """ self.layer.tail_length = value def change_head_length(self, value): """Change edge line forward length of shapes on the layer model. Parameters ---------- value : int Line length of track tails. """ self.layer.head_length = value def change_display_tail(self, state): self.layer.display_tail = self.tail_checkbox.isChecked() def change_display_id(self, state): self.layer.display_id = self.id_checkbox.isChecked() def change_display_graph(self, state): self.layer.display_graph = self.graph_checkbox.isChecked() def change_color_by(self, value: str): self.layer.color_by = value def change_colormap(self, colormap: str): self.layer.colormap = self.colormap_combobox.currentData()
class QtTracksControls(QtLayerControls): """Qt view and controls for the Tracks layer. Parameters ---------- layer : napari.layers.Tracks An instance of a Tracks layer. Attributes ---------- grid_layout : qtpy.QtWidgets.QGridLayout Layout of Qt widget controls for the layer. layer : layers.Tracks An instance of a Tracks layer. """ def __init__(self, layer): super().__init__(layer) # NOTE(arl): there are no events fired for changing checkboxes self.layer.events.tail_width.connect(self._on_tail_width_change) self.layer.events.tail_length.connect(self._on_tail_length_change) self.layer.events.properties.connect(self._on_properties_change) self.layer.events.colormap.connect(self._on_colormap_change) self.layer.events.color_by.connect(self._on_color_by_change) # combo box for track coloring, we can get these from the properties # keys self.color_by_combobox = QComboBox() self.color_by_combobox.addItems(self.layer.properties_to_color_by) self.colormap_combobox = QComboBox() for name, colormap in AVAILABLE_COLORMAPS.items(): display_name = colormap._display_name self.colormap_combobox.addItem(display_name, name) # slider for track tail length self.tail_length_slider = QSlider(Qt.Horizontal) self.tail_length_slider.setFocusPolicy(Qt.NoFocus) self.tail_length_slider.setMinimum(1) self.tail_length_slider.setMaximum(MAX_TAIL_LENGTH) self.tail_length_slider.setSingleStep(1) # slider for track edge width self.tail_width_slider = QSlider(Qt.Horizontal) self.tail_width_slider.setFocusPolicy(Qt.NoFocus) self.tail_width_slider.setMinimum(1) self.tail_width_slider.setMaximum(MAX_TAIL_WIDTH) self.tail_width_slider.setSingleStep(1) # checkboxes for display self.id_checkbox = QCheckBox() self.tail_checkbox = QCheckBox() self.tail_checkbox.setChecked(True) self.graph_checkbox = QCheckBox() self.graph_checkbox.setChecked(True) self.tail_width_slider.valueChanged.connect(self.change_tail_width) self.tail_length_slider.valueChanged.connect(self.change_tail_length) self.tail_checkbox.stateChanged.connect(self.change_display_tail) self.id_checkbox.stateChanged.connect(self.change_display_id) self.graph_checkbox.stateChanged.connect(self.change_display_graph) self.color_by_combobox.currentTextChanged.connect(self.change_color_by) self.colormap_combobox.currentTextChanged.connect(self.change_colormap) # grid_layout created in QtLayerControls # addWidget(widget, row, column, [row_span, column_span]) self.grid_layout.addWidget(QLabel(trans._('color by:')), 0, 0) self.grid_layout.addWidget(self.color_by_combobox, 0, 1) self.grid_layout.addWidget(QLabel(trans._('colormap:')), 1, 0) self.grid_layout.addWidget(self.colormap_combobox, 1, 1) self.grid_layout.addWidget(QLabel(trans._('blending:')), 2, 0) self.grid_layout.addWidget(self.blendComboBox, 2, 1) self.grid_layout.addWidget(QLabel(trans._('opacity:')), 3, 0) self.grid_layout.addWidget(self.opacitySlider, 3, 1) self.grid_layout.addWidget(QLabel(trans._('tail width:')), 4, 0) self.grid_layout.addWidget(self.tail_width_slider, 4, 1) self.grid_layout.addWidget(QLabel(trans._('tail length:')), 5, 0) self.grid_layout.addWidget(self.tail_length_slider, 5, 1) self.grid_layout.addWidget(QLabel(trans._('tail:')), 6, 0) self.grid_layout.addWidget(self.tail_checkbox, 6, 1) self.grid_layout.addWidget(QLabel(trans._('show ID:')), 7, 0) self.grid_layout.addWidget(self.id_checkbox, 7, 1) self.grid_layout.addWidget(QLabel(trans._('graph:')), 8, 0) self.grid_layout.addWidget(self.graph_checkbox, 8, 1) self.grid_layout.setRowStretch(9, 1) self.grid_layout.setColumnStretch(1, 1) self.grid_layout.setSpacing(4) self._on_tail_length_change() self._on_tail_width_change() self._on_colormap_change() self._on_color_by_change() def _on_tail_width_change(self, event=None): """Receive layer model track line width change event and update slider. Parameters ---------- event : qtpy.QtCore.QEvent, optional. Event from the Qt context, by default None. """ with self.layer.events.tail_width.blocker(): value = self.layer.tail_width value = np.clip(int(2 * value), 1, MAX_TAIL_WIDTH) self.tail_width_slider.setValue(value) def _on_tail_length_change(self, event=None): """Receive layer model track line width change event and update slider. Parameters ---------- event : qtpy.QtCore.QEvent, optional. Event from the Qt context, by default None. """ with self.layer.events.tail_length.blocker(): value = self.layer.tail_length value = np.clip(value, 1, MAX_TAIL_LENGTH) self.tail_length_slider.setValue(value) def _on_properties_change(self, event=None): """Change the properties that can be used to color the tracks.""" with self.layer.events.properties.blocker(): with qt_signals_blocked(self.color_by_combobox): self.color_by_combobox.clear() self.color_by_combobox.addItems(self.layer.properties_to_color_by) def _on_colormap_change(self, event=None): """Receive layer model colormap change event and update combobox. Parameters ---------- event : qtpy.QtCore.QEvent, optional. Event from the Qt context, by default None. """ with self.layer.events.colormap.blocker(): self.colormap_combobox.setCurrentIndex( self.colormap_combobox.findData(self.layer.colormap)) def _on_color_by_change(self, event=None): """Receive layer model color_by change event and update combobox. Parameters ---------- event : qtpy.QtCore.QEvent, optional. Event from the Qt context, by default None. """ with self.layer.events.color_by.blocker(): color_by = self.layer.color_by idx = self.color_by_combobox.findText(color_by, Qt.MatchFixedString) self.color_by_combobox.setCurrentIndex(idx) def change_tail_width(self, value): """Change track line width of shapes on the layer model. Parameters ---------- value : float Line width of track tails. """ self.layer.tail_width = float(value) / 2.0 def change_tail_length(self, value): """Change edge line width of shapes on the layer model. Parameters ---------- value : int Line length of track tails. """ self.layer.tail_length = value def change_display_tail(self, state): self.layer.display_tail = self.tail_checkbox.isChecked() def change_display_id(self, state): self.layer.display_id = self.id_checkbox.isChecked() def change_display_graph(self, state): self.layer.display_graph = self.graph_checkbox.isChecked() def change_color_by(self, value: str): self.layer.color_by = value def change_colormap(self, colormap: str): self.layer.colormap = self.colormap_combobox.currentData()
def __init__(self, layer): super().__init__(layer) self.layer.events.interpolation.connect(self._on_interpolation_change) self.layer.events.rendering.connect(self._on_rendering_change) self.layer.events.iso_threshold.connect(self._on_iso_threshold_change) self.layer.events.attenuation.connect(self._on_attenuation_change) self.layer.dims.events.ndisplay.connect(self._on_ndisplay_change) self.interpComboBox = QComboBox(self) self.interpComboBox.activated[str].connect(self.changeInterpolation) self.interpLabel = QLabel('interpolation:') renderComboBox = QComboBox(self) renderComboBox.addItems(Rendering.keys()) index = renderComboBox.findText( self.layer.rendering, Qt.MatchFixedString ) renderComboBox.setCurrentIndex(index) renderComboBox.activated[str].connect(self.changeRendering) self.renderComboBox = renderComboBox self.renderLabel = QLabel('rendering:') sld = QSlider(Qt.Horizontal, parent=self) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(0) sld.setMaximum(100) sld.setSingleStep(1) sld.setValue(int(self.layer.iso_threshold * 100)) sld.valueChanged.connect(self.changeIsoThreshold) self.isoThresholdSlider = sld self.isoThresholdLabel = QLabel('iso threshold:') sld = QSlider(Qt.Horizontal, parent=self) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(0) sld.setMaximum(100) sld.setSingleStep(1) sld.setValue(int(self.layer.attenuation * 200)) sld.valueChanged.connect(self.changeAttenuation) self.attenuationSlider = sld self.attenuationLabel = QLabel('attenuation:') self._on_ndisplay_change() colormap_layout = QHBoxLayout() colormap_layout.addWidget(self.colorbarLabel) colormap_layout.addWidget(self.colormapComboBox) colormap_layout.addStretch(1) # grid_layout created in QtLayerControls # addWidget(widget, row, column, [row_span, column_span]) self.grid_layout.addWidget(QLabel('opacity:'), 0, 0) self.grid_layout.addWidget(self.opacitySlider, 0, 1) self.grid_layout.addWidget(QLabel('contrast limits:'), 1, 0) self.grid_layout.addWidget(self.contrastLimitsSlider, 1, 1) self.grid_layout.addWidget(QLabel('gamma:'), 2, 0) self.grid_layout.addWidget(self.gammaSlider, 2, 1) self.grid_layout.addWidget(QLabel('colormap:'), 3, 0) self.grid_layout.addLayout(colormap_layout, 3, 1) self.grid_layout.addWidget(QLabel('blending:'), 4, 0) self.grid_layout.addWidget(self.blendComboBox, 4, 1) self.grid_layout.addWidget(self.interpLabel, 5, 0) self.grid_layout.addWidget(self.interpComboBox, 5, 1) self.grid_layout.addWidget(self.renderLabel, 6, 0) self.grid_layout.addWidget(self.renderComboBox, 6, 1) self.grid_layout.addWidget(self.isoThresholdLabel, 7, 0) self.grid_layout.addWidget(self.isoThresholdSlider, 7, 1) self.grid_layout.addWidget(self.attenuationLabel, 8, 0) self.grid_layout.addWidget(self.attenuationSlider, 8, 1) self.grid_layout.setRowStretch(9, 1) self.grid_layout.setColumnStretch(1, 1) self.grid_layout.setSpacing(4)
def __init__(self, layer): super().__init__() self.layer = layer layer.events.select.connect(lambda v: self.setSelected(True)) layer.events.deselect.connect(lambda v: self.setSelected(False)) layer.events.name.connect(self._on_layer_name_change) layer.events.blending.connect(self._on_blending_change) layer.events.opacity.connect(self._on_opacity_change) layer.events.visible.connect(self._on_visible_change) layer.events.thumbnail.connect(self._on_thumbnail_change) self.setObjectName('layer') self.vbox_layout = QVBoxLayout() self.top = QFrame() self.top_layout = QHBoxLayout() self.grid = QFrame() self.grid_layout = QGridLayout() self.vbox_layout.addWidget(self.top) self.vbox_layout.addWidget(self.grid) self.vbox_layout.setSpacing(0) self.top.setFixedHeight(38) self.top_layout.setContentsMargins(0, 0, 0, 0) self.grid_layout.setContentsMargins(0, 0, 0, 0) self.top_layout.setAlignment(Qt.AlignCenter) self.top.setLayout(self.top_layout) self.grid.setLayout(self.grid_layout) self.setLayout(self.vbox_layout) self.name_column = 0 self.property_column = 1 cb = QCheckBox(self) cb.setObjectName('visibility') cb.setToolTip('Layer visibility') cb.setChecked(self.layer.visible) cb.setProperty('mode', 'visibility') cb.stateChanged.connect(lambda state=cb: self.changeVisible(state)) self.visibleCheckBox = cb self.top_layout.addWidget(cb) tb = QLabel(self) tb.setObjectName('thumbmnail') tb.setToolTip('Layer thumbmnail') self.thumbnail_label = tb self._on_thumbnail_change(None) self.top_layout.addWidget(tb) textbox = QLineEdit(self) textbox.setText(layer.name) textbox.home(False) textbox.setToolTip('Layer name') textbox.setAcceptDrops(False) textbox.setEnabled(True) textbox.editingFinished.connect(self.changeText) self.nameTextBox = textbox self.top_layout.addWidget(textbox) pb = QPushButton(self) pb.setToolTip('Expand properties') pb.clicked.connect(self.changeExpanded) pb.setObjectName('expand') self.expand_button = pb self.top_layout.addWidget(pb) row = self.grid_layout.rowCount() sld = QSlider(Qt.Horizontal, self) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(0) sld.setMaximum(100) sld.setSingleStep(1) sld.setValue(self.layer.opacity * 100) sld.valueChanged[int].connect( lambda value=sld: self.changeOpacity(value)) self.opacitySilder = sld row = self.grid_layout.rowCount() self.grid_layout.addWidget(QLabel('opacity:'), row, self.name_column) self.grid_layout.addWidget(sld, row, self.property_column) row = self.grid_layout.rowCount() blend_comboBox = QComboBox() for blend in Blending: blend_comboBox.addItem(str(blend)) index = blend_comboBox.findText(self.layer.blending, Qt.MatchFixedString) blend_comboBox.setCurrentIndex(index) blend_comboBox.activated[str].connect( lambda text=blend_comboBox: self.changeBlending(text)) self.blendComboBox = blend_comboBox self.grid_layout.addWidget(QLabel('blending:'), row, self.name_column) self.grid_layout.addWidget(blend_comboBox, row, self.property_column) msg = 'Click to select\nDrag to rearrange\nDouble click to expand' self.setToolTip(msg) self.setExpanded(False) self.setFixedWidth(250) self.grid_layout.setColumnMinimumWidth(0, 100) self.grid_layout.setColumnMinimumWidth(1, 100) self.setSelected(self.layer.selected)
class QtSizeSliderPreviewWidget(QWidget): """ Widget displaying a description, textedit and slider to adjust font size with preview. Parameters ---------- parent : qtpy.QtWidgets.QWidget, optional Default is None. description : str, optional Default is "". preview_text : str, optional Default is "". value : int, optional Default is None. min_value : int, optional Default is 1. max_value : int, optional Default is 50. unit : str, optional Default is "px". """ valueChanged = Signal(int) def __init__( self, parent: QWidget = None, description: str = None, preview_text: str = None, value: int = None, min_value: int = 1, max_value: int = 50, unit: str = "px", ): super().__init__(parent) description = description or "" preview_text = preview_text or "" self._value = value if value else self.fontMetrics().height() self._min_value = min_value self._max_value = max_value # Widget self._lineedit = QLineEdit() self._description_label = QLabel(self) self._unit_label = QLabel(self) self._slider = QSlider(Qt.Horizontal, self) self._slider_min_label = QLabel(self) self._slider_max_label = QLabel(self) self._preview = QtFontSizePreview(self) self._preview_label = QLabel(self) self._validator = None # Widgets setup self._description_label.setText(description) self._description_label.setWordWrap(True) self._unit_label.setText(unit) self._lineedit.setAlignment(Qt.AlignRight) self._slider_min_label.setText(str(min_value)) self._slider_max_label.setText(str(max_value)) self._slider.setMinimum(min_value) self._slider.setMaximum(max_value) self._preview.setText(preview_text) self._preview_label.setText(trans._("preview")) self._preview_label.setAlignment(Qt.AlignHCenter) self.setFocusProxy(self._lineedit) # Layout left_bottom_layout = QHBoxLayout() left_bottom_layout.addWidget(self._lineedit) left_bottom_layout.addWidget(self._unit_label) left_bottom_layout.addWidget(self._slider_min_label) left_bottom_layout.addWidget(self._slider) left_bottom_layout.addWidget(self._slider_max_label) left_layout = QVBoxLayout() left_layout.addWidget(self._description_label) left_layout.addLayout(left_bottom_layout) right_layout = QVBoxLayout() right_layout.addWidget(self._preview) right_layout.addWidget(self._preview_label) layout = QHBoxLayout() layout.addLayout(left_layout, 2) layout.addLayout(right_layout, 1) self.setLayout(layout) # Signals self._slider.valueChanged.connect(self._update_value) self._lineedit.textChanged.connect(self._update_value) self._update_line_width() self._update_validator() self._update_value(self._value) def _update_validator(self): self._validator = QIntValidator(self._min_value, self._max_value, self) self._lineedit.setValidator(self._validator) def _update_line_width(self): """Update width ofg line text edit.""" size = self._lineedit.fontMetrics().horizontalAdvance( "m" * (1 + len(str(self._max_value)))) self._lineedit.setMaximumWidth(size) self._lineedit.setMinimumWidth(size) def _update_value(self, value: int): """Update internal value and emit if changed.""" if value == "": value = int(self._value) value = int(value) if value > self._max_value: value = self._max_value elif value < self._min_value: value = self._min_value if value != self._value: self.valueChanged.emit(value) self._value = value self._refresh(self._value) def _refresh(self, value: int = None): """Refresh the value on all subwidgets.""" value = value if value else self._value self.blockSignals(True) self._lineedit.setText(str(value)) self._slider.setValue(value) font = QFont() font.setPixelSize(value) self._preview.setFont(font) font = QFont() font.setPixelSize(self.fontMetrics().height() - 4) self._preview_label.setFont(font) self.blockSignals(False) def description(self) -> str: """Return the current widget description. Returns ------- str The description text. """ return self._description_label.text() def setDescription(self, text: str): """Set the current widget description. Parameters ---------- text : str The description text. """ self._description_label.setText(text) def previewText(self) -> str: """Return the current preview text. Returns ------- str The current preview text. """ return self._preview.text() def setPreviewText(self, text: str): """Set the current preview text. Parameters ---------- text : str The current preview text. """ self._preview.setText(text) def unit(self) -> str: """Return the current unit text. Returns ------- str The current unit text. """ return self._unit_label.text() def setUnit(self, text: str): """Set the current unit text. Parameters ---------- text : str The current preview text. """ self._unit_label.setText(text) def minimum(self) -> int: """Return the current minimum value for the slider and value in textbox. Returns ------- int The minimum value for the slider. """ return self._min_value def setMinimum(self, value: int): """Set the current minimum value for the slider and value in textbox. Parameters ---------- value : int The minimum value for the slider. """ value = int(value) if value < self._max_value: self._min_value = value self._value = (self._min_value if self._value < self._min_value else self._value) self._slider_min_label.setText(str(value)) self._slider.setMinimum(value) self._update_validator() self._refresh() else: raise ValueError( trans._("Minimum value must be smaller than {}".format( self._max_value))) def maximum(self) -> int: """Return the maximum value for the slider and value in textbox. Returns ------- int The maximum value for the slider. """ return self._max_value def setMaximum(self, value: int): """Set the maximum value for the slider and value in textbox. Parameters ---------- value : int The maximum value for the slider. """ value = int(value) if value > self._min_value: self._max_value = value self._value = (self._max_value if self._value > self._max_value else self._value) self._slider_max_label.setText(str(value)) self._slider.setMaximum(value) self._update_validator() self._update_line_width() self._refresh() else: raise ValueError( trans._("Maximum value must be larger than {}".format( self._min_value))) def value(self) -> int: """Return the current widget value. Returns ------- int The current value. """ return self._value def setValue(self, value: int): """Set the current widget value. Parameters ---------- value : int The current value. """ self._update_value(value)
class PyDMSlider(QFrame, PyDMWritableWidget): """ A QSlider with support for Channels and more from PyDM. Parameters ---------- parent : QWidget The parent widget for the Label init_channel : str, optional The channel to be used by the widget. """ actionTriggered = Signal(int) rangeChanged = Signal(float, float) sliderMoved = Signal(float) sliderPressed = Signal() sliderReleased = Signal() valueChanged = Signal(float) def __init__(self, parent=None, init_channel=None): QFrame.__init__(self, parent) PyDMWritableWidget.__init__(self, init_channel=init_channel) self.alarmSensitiveContent = True self.alarmSensitiveBorder = False # Internal values for properties self.set_enable_state() self._show_limit_labels = True self._show_value_label = True self._user_defined_limits = False self._needs_limit_info = True self._minimum = None self._maximum = None self._user_minimum = -10.0 self._user_maximum = 10.0 self._num_steps = 101 self._orientation = Qt.Horizontal # Set up all the internal widgets that make up a PyDMSlider. # We'll add all these things to layouts when we call setup_widgets_for_orientation label_size_policy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.low_lim_label = QLabel(self) self.low_lim_label.setObjectName("lowLimLabel") self.low_lim_label.setSizePolicy(label_size_policy) self.low_lim_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter) self.value_label = QLabel(self) self.value_label.setObjectName("valueLabel") self.value_label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.high_lim_label = QLabel(self) self.high_lim_label.setObjectName("highLimLabel") self.high_lim_label.setSizePolicy(label_size_policy) self.high_lim_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._slider = QSlider(parent=self) self._slider.setOrientation(Qt.Horizontal) self._slider.sliderMoved.connect(self.internal_slider_moved) self._slider.sliderPressed.connect(self.internal_slider_pressed) self._slider.sliderReleased.connect(self.internal_slider_released) self._slider.valueChanged.connect(self.internal_slider_value_changed) # self.vertical_layout.addWidget(self._slider) # Other internal variables and final setup steps self._slider_position_to_value_map = None self._mute_internal_slider_changes = False self.setup_widgets_for_orientation(self._orientation) self.reset_slider_limits() def init_for_designer(self): """ Method called after the constructor to tweak configurations for when using the widget with the Qt Designer """ self.value = 0.0 @Property(Qt.Orientation) def orientation(self): """ The slider orientation (Horizontal or Vertical) Returns ------- int Qt.Horizontal or Qt.Vertical """ return self._orientation @orientation.setter def orientation(self, new_orientation): """ The slider orientation (Horizontal or Vertical) Parameters ---------- new_orientation : int Qt.Horizontal or Qt.Vertical """ self._orientation = new_orientation self.setup_widgets_for_orientation(new_orientation) def setup_widgets_for_orientation(self, new_orientation): """ Reconstruct the widget given the orientation. Parameters ---------- new_orientation : int Qt.Horizontal or Qt.Vertical """ if new_orientation not in (Qt.Horizontal, Qt.Vertical): logger.error( "Invalid orientation '{0}'. The existing layout will not change." .format(new_orientation)) return layout = None if new_orientation == Qt.Horizontal: layout = QVBoxLayout() layout.setContentsMargins(4, 0, 4, 4) label_layout = QHBoxLayout() label_layout.addWidget(self.low_lim_label) label_layout.addStretch(0) label_layout.addWidget(self.value_label) label_layout.addStretch(0) label_layout.addWidget(self.high_lim_label) layout.addLayout(label_layout) self._slider.setOrientation(new_orientation) layout.addWidget(self._slider) elif new_orientation == Qt.Vertical: layout = QHBoxLayout() layout.setContentsMargins(0, 4, 4, 4) label_layout = QVBoxLayout() label_layout.addWidget(self.high_lim_label) label_layout.addStretch(0) label_layout.addWidget(self.value_label) label_layout.addStretch(0) label_layout.addWidget(self.low_lim_label) layout.addLayout(label_layout) self._slider.setOrientation(new_orientation) layout.addWidget(self._slider) if self.layout() is not None: # Trick to remove the existing layout by re-parenting it in an empty widget. QWidget().setLayout(self.layout()) self.setLayout(layout) def update_labels(self): """ Update the limits and value labels with the correct values. """ def set_label(value, label_widget): if value is None: label_widget.setText("") else: label_widget.setText(self.format_string.format(value)) set_label(self.minimum, self.low_lim_label) set_label(self.maximum, self.high_lim_label) set_label(self.value, self.value_label) def reset_slider_limits(self): """ Reset the limits and adjust the labels properly for the slider. """ if self.minimum is None or self.maximum is None: self._needs_limit_info = True self.set_enable_state() return self._needs_limit_info = False self._slider.setMinimum(0) self._slider.setMaximum(self._num_steps - 1) self._slider.setSingleStep(1) self._slider.setPageStep(10) self._slider_position_to_value_map = np.linspace(self.minimum, self.maximum, num=self._num_steps) self.update_labels() self.set_slider_to_closest_value(self.value) self.rangeChanged.emit(self.minimum, self.maximum) self.set_enable_state() def find_closest_slider_position_to_value(self, val): """ Find and returns the index for the closest position on the slider for a given value. Parameters ---------- val : float Returns ------- int """ diff = abs(self._slider_position_to_value_map - float(val)) return np.argmin(diff) def set_slider_to_closest_value(self, val): """ Set the value for the slider according to a given value. Parameters ---------- val : float """ if val is None or self._needs_limit_info: return # When we set the slider to the closest value, it may end up at a slightly # different position than val (if val is not in self._slider_position_to_value_map) # We don't want that slight difference to get broacast out and put the channel # somewhere new. For example, if the slider can only be at 0.4 or 0.5, but a # new value comes in of 0.45, its more important to keep the 0.45 than to change # it to where the slider gets set. Therefore, we mute the internal slider changes # so that its valueChanged signal doesn't cause us to emit a signal to PyDM to change # the value of the channel. self._mute_internal_slider_changes = True self._slider.setValue(self.find_closest_slider_position_to_value(val)) self._mute_internal_slider_changes = False def value_changed(self, new_val): """ Callback invoked when the Channel value is changed. Parameters ---------- new_val : int or float The new value from the channel. """ PyDMWritableWidget.value_changed(self, new_val) if hasattr(self, "value_label"): self.value_label.setText(self.format_string.format(self.value)) if not self._slider.isSliderDown(): self.set_slider_to_closest_value(self.value) def ctrl_limit_changed(self, which, new_limit): """ Callback invoked when the Channel receives new control limit values. Parameters ---------- which : str Which control limit was changed. "UPPER" or "LOWER" new_limit : float New value for the control limit """ PyDMWritableWidget.ctrl_limit_changed(self, which, new_limit) if not self.userDefinedLimits: self.reset_slider_limits() def update_format_string(self): """ Reconstruct the format string to be used when representing the output value. Returns ------- format_string : str The format string to be used including or not the precision and unit """ fs = PyDMWritableWidget.update_format_string(self) self.update_labels() return fs def set_enable_state(self): """ Determines wether or not the widget must be enabled or not depending on the write access, connection state and presence of limits information """ self.setEnabled(self._write_access and self._connected and not self._needs_limit_info) @Slot(int) def internal_slider_action_triggered(self, action): self.actionTriggered.emit(action) @Slot(int) def internal_slider_moved(self, val): """ Method invoked when the slider is moved. Parameters ---------- val : float """ # The user has moved the slider, we need to update our value. # Only update the underlying value, not the self.value property, # because we don't need to reset the slider position. If we change # self.value, we can get into a loop where the position changes, which # updates the value, which changes the position again, etc etc. self.value = self._slider_position_to_value_map[val] self.sliderMoved.emit(self.value) @Slot() def internal_slider_pressed(self): """ Method invoked when the slider is pressed """ self.sliderPressed.emit() @Slot() def internal_slider_released(self): """ Method invoked when the slider is released """ self.sliderReleased.emit() @Slot(int) def internal_slider_value_changed(self, val): """ Method invoked when a new value is selected on the slider. This will cause the new value to be emitted to the signal unless `mute_internal_slider_changes` is True. Parameters ---------- val : int """ # At this point, our local copy of the value reflects the position of the # slider, now all we need to do is emit a signal to PyDM so that the data # plugin will send a put to the channel. Don't update self.value or self._value # in here, it is pointless at best, and could cause an infinite loop at worst. if not self._mute_internal_slider_changes: self.send_value_signal[float].emit(self.value) @Property(bool) def showLimitLabels(self): """ Whether or not the high and low limits should be displayed on the slider. Returns ------- bool """ return self._show_limit_labels @showLimitLabels.setter def showLimitLabels(self, checked): """ Whether or not the high and low limits should be displayed on the slider. Parameters ---------- checked : bool """ self._show_limit_labels = checked if checked: self.low_lim_label.show() self.high_lim_label.show() else: self.low_lim_label.hide() self.high_lim_label.hide() @Property(bool) def showValueLabel(self): """ Whether or not the current value should be displayed on the slider. Returns ------- bool """ return self._show_value_label @showValueLabel.setter def showValueLabel(self, checked): """ Whether or not the current value should be displayed on the slider. Parameters ---------- checked : bool """ self._show_value_label = checked if checked: self.value_label.show() else: self.value_label.hide() @Property(QSlider.TickPosition) def tickPosition(self): """ Where to draw tick marks for the slider. Returns ------- QSlider.TickPosition """ return self._slider.tickPosition() @tickPosition.setter def tickPosition(self, position): """ Where to draw tick marks for the slider. Parameter --------- position : QSlider.TickPosition """ self._slider.setTickPosition(position) @Property(bool) def userDefinedLimits(self): """ Wether or not to use limits defined by the user and not from the channel Returns ------- bool """ return self._user_defined_limits @userDefinedLimits.setter def userDefinedLimits(self, user_defined_limits): """ Wether or not to use limits defined by the user and not from the channel Parameters ---------- user_defined_limits : bool """ self._user_defined_limits = user_defined_limits self.reset_slider_limits() @Property(float) def userMinimum(self): """ Lower user defined limit value Returns ------- float """ return self._user_minimum @userMinimum.setter def userMinimum(self, new_min): """ Lower user defined limit value Parameters ---------- new_min : float """ self._user_minimum = float(new_min) if new_min is not None else None if self.userDefinedLimits: self.reset_slider_limits() @Property(float) def userMaximum(self): """ Upper user defined limit value Returns ------- float """ return self._user_maximum @userMaximum.setter def userMaximum(self, new_max): """ Upper user defined limit value Parameters ---------- new_max : float """ self._user_maximum = float(new_max) if new_max is not None else None if self.userDefinedLimits: self.reset_slider_limits() @property def minimum(self): """ The current value being used for the lower limit Returns ------- float """ if self.userDefinedLimits: return self._user_minimum return self._lower_ctrl_limit @property def maximum(self): """ The current value being used for the upper limit Returns ------- float """ if self.userDefinedLimits: return self._user_maximum return self._upper_ctrl_limit @Property(int) def num_steps(self): """ The number of steps on the slider Returns ------- int """ return self._num_steps @num_steps.setter def num_steps(self, new_steps): """ The number of steps on the slider Parameters ---------- new_steps : int """ self._num_steps = int(new_steps) self.reset_slider_limits()
def __init__(self, layer): super().__init__(layer) self.layer.events.mode.connect(self._on_mode_change) self.layer.events.edge_width.connect(self._on_edge_width_change) self.layer.events.current_edge_color.connect( self._on_current_edge_color_change ) self.layer.events.current_face_color.connect( self._on_current_face_color_change ) self.layer.events.editable.connect(self._on_editable_change) self.layer.text.events.visible.connect(self._on_text_visibility_change) sld = QSlider(Qt.Horizontal) sld.setFocusPolicy(Qt.NoFocus) sld.setMinimum(0) sld.setMaximum(40) sld.setSingleStep(1) value = self.layer.current_edge_width if isinstance(value, Iterable): if isinstance(value, list): value = np.asarray(value) value = value.mean() sld.setValue(int(value)) sld.valueChanged.connect(self.changeWidth) self.widthSlider = sld def _radio_button( parent, btn_name, mode, action_name, extra_tooltip_text='', **kwargs, ): """ Convenience local function to create a RadioButton and bind it to an action at the same time. Parameters ---------- parent : Any Parent of the generated QtModeRadioButton btn_name : str name fo the button mode : Enum Value Associated to current button action_name : str Action triggered when button pressed extra_tooltip_text : str Text you want added after the automatic tooltip set by the action manager **kwargs: Passed to QtModeRadioButton Returns ------- button: QtModeRadioButton button bound (or that will be bound to) to action `action_name` Notes ----- When shortcuts are modifed/added/removed via the action manager, the tooltip will be updated to reflect the new shortcut. """ action_name = 'napari:' + action_name btn = QtModeRadioButton(parent, btn_name, mode, **kwargs) action_manager.bind_button( action_name, btn, extra_tooltip_text='', ) return btn self.select_button = _radio_button( layer, 'select', Mode.SELECT, "activate_select_mode" ) self.direct_button = _radio_button( layer, 'direct', Mode.DIRECT, "activate_direct_mode" ) self.panzoom_button = _radio_button( layer, 'zoom', Mode.PAN_ZOOM, "napari:activate_shape_pan_zoom_mode", extra_tooltip_text=trans._('(or hold Space)'), checked=True, ) self.rectangle_button = _radio_button( layer, 'rectangle', Mode.ADD_RECTANGLE, "activate_add_rectangle_mode", ) self.ellipse_button = _radio_button( layer, 'ellipse', Mode.ADD_ELLIPSE, "activate_add_ellipse_mode", ) self.line_button = _radio_button( layer, 'line', Mode.ADD_LINE, "activate_add_line_mode" ) self.path_button = _radio_button( layer, 'path', Mode.ADD_PATH, "activate_add_path_mode" ) self.polygon_button = _radio_button( layer, 'polygon', Mode.ADD_POLYGON, "activate_add_polygon_mode", ) self.vertex_insert_button = _radio_button( layer, 'vertex_insert', Mode.VERTEX_INSERT, "activate_vertex_insert_mode", ) self.vertex_remove_button = _radio_button( layer, 'vertex_remove', Mode.VERTEX_REMOVE, "activate_vertex_remove_mode", ) self.move_front_button = QtModePushButton( layer, 'move_front', slot=self.layer.move_to_front, tooltip=trans._('Move to front'), ) action_manager.bind_button( 'napari:move_shapes_selection_to_front', self.move_front_button ) self.move_back_button = QtModePushButton( layer, 'move_back', slot=self.layer.move_to_back, tooltip=trans._('Move to back'), ) action_manager.bind_button( 'napari:move_shapes_selection_to_back', self.move_back_button ) self.delete_button = QtModePushButton( layer, 'delete_shape', slot=self.layer.remove_selected, tooltip=trans._( "Delete selected shapes ({shortcut})", shortcut=Shortcut('Backspace').platform, ), ) self.button_group = QButtonGroup(self) self.button_group.addButton(self.select_button) self.button_group.addButton(self.direct_button) self.button_group.addButton(self.panzoom_button) self.button_group.addButton(self.rectangle_button) self.button_group.addButton(self.ellipse_button) self.button_group.addButton(self.line_button) self.button_group.addButton(self.path_button) self.button_group.addButton(self.polygon_button) self.button_group.addButton(self.vertex_insert_button) self.button_group.addButton(self.vertex_remove_button) button_grid = QGridLayout() button_grid.addWidget(self.vertex_remove_button, 0, 2) button_grid.addWidget(self.vertex_insert_button, 0, 3) button_grid.addWidget(self.delete_button, 0, 4) button_grid.addWidget(self.direct_button, 0, 5) button_grid.addWidget(self.select_button, 0, 6) button_grid.addWidget(self.panzoom_button, 0, 7) button_grid.addWidget(self.move_back_button, 1, 1) button_grid.addWidget(self.move_front_button, 1, 2) button_grid.addWidget(self.ellipse_button, 1, 3) button_grid.addWidget(self.rectangle_button, 1, 4) button_grid.addWidget(self.polygon_button, 1, 5) button_grid.addWidget(self.line_button, 1, 6) button_grid.addWidget(self.path_button, 1, 7) button_grid.setContentsMargins(5, 0, 0, 5) button_grid.setColumnStretch(0, 1) button_grid.setSpacing(4) self.faceColorEdit = QColorSwatchEdit( initial_color=self.layer.current_face_color, tooltip=trans._('click to set current face color'), ) self._on_current_face_color_change() self.edgeColorEdit = QColorSwatchEdit( initial_color=self.layer.current_edge_color, tooltip=trans._('click to set current edge color'), ) self._on_current_edge_color_change() self.faceColorEdit.color_changed.connect(self.changeFaceColor) self.edgeColorEdit.color_changed.connect(self.changeEdgeColor) text_disp_cb = QCheckBox() text_disp_cb.setToolTip(trans._('toggle text visibility')) text_disp_cb.setChecked(self.layer.text.visible) text_disp_cb.stateChanged.connect(self.change_text_visibility) self.textDispCheckBox = text_disp_cb # grid_layout created in QtLayerControls # addWidget(widget, row, column, [row_span, column_span]) self.grid_layout.addLayout(button_grid, 0, 0, 1, 2) self.grid_layout.addWidget(QLabel(trans._('opacity:')), 1, 0) self.grid_layout.addWidget(self.opacitySlider, 1, 1) self.grid_layout.addWidget(QLabel(trans._('edge width:')), 2, 0) self.grid_layout.addWidget(self.widthSlider, 2, 1) self.grid_layout.addWidget(QLabel(trans._('blending:')), 3, 0) self.grid_layout.addWidget(self.blendComboBox, 3, 1) self.grid_layout.addWidget(QLabel(trans._('face color:')), 4, 0) self.grid_layout.addWidget(self.faceColorEdit, 4, 1) self.grid_layout.addWidget(QLabel(trans._('edge color:')), 5, 0) self.grid_layout.addWidget(self.edgeColorEdit, 5, 1) self.grid_layout.addWidget(QLabel(trans._('display text:')), 6, 0) self.grid_layout.addWidget(self.textDispCheckBox, 6, 1) self.grid_layout.setRowStretch(7, 1) self.grid_layout.setColumnStretch(1, 1) self.grid_layout.setSpacing(4)
class SliderSpinBox(QWidget): valueChanged = Signal(float) def __init__(self, parent=None, value_range=(0, 100), slider_steps=100, spinbox_steps=1000, decimals=None): QWidget.__init__(self, parent) layout = QHBoxLayout(self) self.setLayout(layout) self.horizontalSlider = QSlider(Qt.Horizontal, self) self.doubleSpinBox = QDoubleSpinBox(self) self.decimals = decimals layout.setMargin(0) layout.addWidget(self.doubleSpinBox) layout.addWidget(self.horizontalSlider) self.doubleSpinBox.valueChanged.connect(self.spinbox_changed) self.horizontalSlider.valueChanged.connect(self.slider_changed) self.wt = [] self.changer = None self.slider_steps = slider_steps self.horizontalSlider.setMaximum(slider_steps) self.spinbox_steps = spinbox_steps self.set_range(value_range) def set_value(self, value): self.doubleSpinBox.setValue(value) value = property(lambda self: self.doubleSpinBox.value(), set_value) def set_range(self, value_range): self.changer = "set_range" spinbox_step_decimal = np.ceil(np.log10(1. / (float(value_range[1] - value_range[0]) / self.spinbox_steps))) self.slider_decimals = int(np.ceil(np.log10(self.slider_steps) - np.log10(value_range[1] - value_range[0]))) if self.decimals is None: self.doubleSpinBox.setDecimals(spinbox_step_decimal + 1) else: self.doubleSpinBox.setDecimals(self.decimals) spinbox_step_decimal = min(self.decimals, spinbox_step_decimal) self.slider_decimals = min(self.decimals, self.slider_decimals) self.doubleSpinBox.setSingleStep(10 ** -spinbox_step_decimal) self.value_range = value_range self.doubleSpinBox.setMinimum(value_range[0]) self.doubleSpinBox.setMaximum(value_range[1]) self.horizontalSlider.setValue(np.floor(value_range[0])) self.changer = None self.doubleSpinBox.setValue(value_range[0]) def range(self): return self.doubleSpinBox.minimum(), self.doubleSpinBox.maximum() def slider_changed(self, value): if self.changer is None: self.changer = 'slider' value = np.round(value * (self.value_range[1] - self.value_range[0]) / self.slider_steps + self.value_range[0], self.slider_decimals) self.doubleSpinBox.setValue(value) self.changer = None self.value_changed(value) def spinbox_changed(self, value): if self.changer is None: self.changer = 'spinbox' slider_value = .5 + (value - self.value_range[0]) * self.slider_steps / (self.value_range[1] - self.value_range[0]) self.horizontalSlider.setValue(slider_value) self.changer = None self.value_changed(value) @postpone_until_last_call_finishes def value_changed(self, value): self.valueChanged.emit(value)