class SourceSelectorDialog(QDialog): def __init__(self, parent, flags=Qt.WindowFlags()): QDialog.__init__(self, parent, flags) self.setModal(False) self.setWindowTitle("Select sources by...") lo = QVBoxLayout(self) lo.setContentsMargins(10, 10, 10, 10) lo.setSpacing(5) # select by lo1 = QHBoxLayout() lo.addLayout(lo1) lo1.setContentsMargins(0, 0, 0, 0) # lab = QLabel("Select:") # lo1.addWidget(lab) self.wselby = QComboBox(self) lo1.addWidget(self.wselby, 0) self.wselby.activated[str].connect(self._setup_selection_by) # under/over self.wgele = QComboBox(self) lo1.addWidget(self.wgele, 0) self.wgele.addItems([">", ">=", "<=", "<", "sum<=", "sum>", "=="]) self.wgele.activated[str].connect(self._select_threshold) # threshold value self.wthreshold = QLineEdit(self) self.wthreshold.editingFinished.connect(self._select_threshold) lo1.addWidget(self.wthreshold, 1) # min and max label self.wminmax = QLabel(self) lo.addWidget(self.wminmax) # selection slider lo1 = QHBoxLayout() lo.addLayout(lo1) self.wpercent = QSlider(self) self.wpercent.setTracking(False) self.wpercent.valueChanged[int].connect(self._select_percentile) self.wpercent.sliderMoved[int].connect( self._select_percentile_threshold) self.wpercent.setRange(0, 100) self.wpercent.setOrientation(Qt.Horizontal) lo1.addWidget(self.wpercent) self.wpercent_lbl = QLabel("0%", self) self.wpercent_lbl.setMinimumWidth(64) lo1.addWidget(self.wpercent_lbl) # # hide button # lo.addSpacing(10) # lo2 = QHBoxLayout() # lo.addLayout(lo2) # lo2.setContentsMargins(0,0,0,0) # hidebtn = QPushButton("Close",self) # hidebtn.setMinimumWidth(128) # QObject.connect(hidebtn,pyqtSignal("clicked()"),self.hide) # lo2.addStretch(1) # lo2.addWidget(hidebtn) # lo2.addStretch(1) # self.setMinimumWidth(384) self._in_select_threshold = False self._sort_index = None self.qerrmsg = QErrorMessage(self) def resetModel(self): """Resets dialog based on current model.""" if not self.model: return # getset of model tags, and remove the non-sorting tags alltags = set(self.model.tagnames) alltags -= NonSortingTags # make list of tags from StandardTags that are present in model self.sorttags = [ tag for tag in StandardTags if tag in alltags or tag in TagAccessors ] # append model tags that were not in StandardTags self.sorttags += list(alltags - set(self.sorttags)) # set selector self.wselby.clear() self.wselby.addItems(self.sorttags) for tag in "Iapp", "I": if tag in self.sorttags: self.wselby.setCurrentIndex(self.sorttags.index(tag)) break self._setup_selection_by(self.wselby.currentText()) def _reset_percentile(self): self.wthreshold.setText("") self.wpercent.setValue(50) self.wpercent_lbl.setText("--%") def _setup_selection_by(self, tag): tag = str(tag) # may be QString # clear threshold value and percentiles self._reset_percentile() # get min/max values, and sort indices # _sort_index will be an array of (value,src,cumsum) tuples, sorted by tag value (high to low), # where src is the source, and cumsum is the sum of all values in the list from 0 up to and including the current one self._sort_index = [] minval = maxval = value = None for isrc, src in enumerate(self.model.sources): try: if hasattr(src, tag): # test if item can be cast to float try: float(getattr(src, tag)) except: continue else: value = float(getattr(src, tag)) elif tag in TagAccessors: value = float(TagAccessors[tag](src)) else: # not existant for this source (maybe a tag or something??) value = np.nan # skip source if failed to access this tag as a float except: traceback.print_exc() continue if value is not None: self._sort_index.append( [value if not np.isnan(value) else -np.inf, src, 0.]) minval = min(minval, value if not np.isnan(value) else np.inf) if minval is not None else value maxval = max(maxval, value if not np.isnan(value) else -np.inf) if maxval is not None else value # add label if minval is None: self._range = None self.wminmax.setText( "<font color=red>'%s' is not a numeric attribute</font>" % tag) for w in self.wgele, self.wthreshold, self.wpercent, self.wpercent_lbl: w.setEnabled(False) else: self._range = (minval, maxval) self.wminmax.setText("min: %g max: %g" % self._range) for w in self.wgele, self.wthreshold, self.wpercent, self.wpercent_lbl: w.setEnabled(True) # sort index by descending values self._sort_index.sort(reverse=True, key=operator.itemgetter(0)) # generate cumulative sums cumsum = 0. for entry in self._sort_index: if not np.isneginf(entry[0]): cumsum += entry[0] entry[2] = cumsum # Maps comparison operators to callables. Used in _select_threshold. # Each callable takes two arguments: e is a tuple of (value,src,cumsum) (see _sort_index above), and x is a threshold # Second argument is a flag: if False, selection is inverted w.r.t. operator Operators = { "<": ((lambda e, x: e[0] >= x), False), "<=": ((lambda e, x: e[0] > x), False), ">": ((lambda e, x: e[0] > x), True), ">=": ((lambda e, x: e[0] >= x), True), "sum<=": ((lambda e, x: e[2] <= x), True), "sum>": ((lambda e, x: e[2] <= x), False), "==": ((lambda e, x: np.abs(e[0] - x) < 1.0e-8), True), } def _select_threshold(self, *dum): dprint(1, "select_threshold", dum) self._in_select_threshold = True busy = BusyIndicator() try: # get threshold, ignore if not set threshold = str(self.wthreshold.text()) if not threshold: self._reset_percentile() return # try to parse threshold, ignore if invalid try: threshold = float(threshold) except: self._reset_percentile() return # get comparison operator op, select = self.Operators[str(self.wgele.currentText())] # apply to initial segment (that matches operator) for num, entry in enumerate(self._sort_index): if not op(entry, threshold): break entry[1].selected = select else: num = len(self._sort_index) # apply to remaining segment for val, src, cumsum in self._sort_index[num:]: src.selected = not select # set percentile percent = round(float(num * 100) / len(self._sort_index)) if not select: percent = 100 - percent self.wpercent.setValue(percent) self.wpercent_lbl.setText("%3d%%" % percent) # emit signal self.model.emitSelection(self) finally: self._in_select_threshold = False busy.reset_cursor() def _select_percentile(self, percent): self._select_percentile_threshold(percent, do_select=True) def _select_percentile_threshold(self, percent, do_select=False): # ignore if no sort index set up, or if _select_threshold() is being called if self._sort_index is None or self._in_select_threshold: return dprint(1, "select_precentile_threshold", percent) busy = BusyIndicator() # number of objects to select nsrc = len(self._sort_index) nsel = int(math.ceil(nsrc * float(percent) / 100)) # get comparison operator opstr = str(self.wgele.currentText()) op, select = self.Operators[opstr] # select head or tail of list, depending on direction of operator if select: thr = self._sort_index[min(nsel, nsrc - 1)] slc1 = slice(0, nsel) slc2 = slice(nsel, None) else: thr = self._sort_index[-min(nsel + 1, nsrc)] slc1 = slice(nsrc - nsel, None) slc2 = slice(0, nsrc - nsel) if do_select: for val, src, cumsum in self._sort_index[slc1]: src.selected = True for val, src, cumsum in self._sort_index[slc2]: src.selected = False self.model.emitSelection(self) self.wpercent_lbl.setText("%3d%%" % percent) self.wthreshold.setText( "%g" % (thr[2] if opstr.startswith("sum") else thr[0])) busy.reset_cursor() return nsel def setModel(self, model): """Sets the current model. If dialog is visible, applies the changes""" self.model = model if self.isVisible(): self.resetModel() if not model: self.hide() def show(self): """Shows dialog, resetting the model if it was invisible.""" if not self.isVisible(): self.resetModel() QDialog.show(self)
def __init__(self, window, plugin, keystore, device_id): title = _("{} Settings").format(plugin.device) super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() config = devmgr.config handler = keystore.handler thread = keystore.thread hs_rows, hs_cols = (64, 128) def invoke_client(method, *args, **kw_args): unpair_after = kw_args.pop('unpair_after', False) def task(): client = devmgr.client_by_id(device_id) if not client: raise RuntimeError("Device not connected") if method: getattr(client, method)(*args, **kw_args) if unpair_after: devmgr.unpair_id(device_id) return client.features thread.add(task, on_success=update) def update(features): self.features = features set_label_enabled() if features.bootloader_hash: bl_hash = bh2u(features.bootloader_hash) bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]]) else: bl_hash = "N/A" noyes = [_("No"), _("Yes")] endis = [_("Enable Passphrases"), _("Disable Passphrases")] disen = [_("Disabled"), _("Enabled")] setchange = [_("Set a PIN"), _("Change PIN")] version = "%d.%d.%d" % (features.major_version, features.minor_version, features.patch_version) device_label.setText(features.label) pin_set_label.setText(noyes[features.pin_protection]) passphrases_label.setText(disen[features.passphrase_protection]) bl_hash_label.setText(bl_hash) label_edit.setText(features.label) device_id_label.setText(features.device_id) initialized_label.setText(noyes[features.initialized]) version_label.setText(version) clear_pin_button.setVisible(features.pin_protection) clear_pin_warning.setVisible(features.pin_protection) pin_button.setText(setchange[features.pin_protection]) pin_msg.setVisible(not features.pin_protection) passphrase_button.setText(endis[features.passphrase_protection]) language_label.setText(features.language) def set_label_enabled(): label_apply.setEnabled(label_edit.text() != self.features.label) def rename(): invoke_client('change_label', label_edit.text()) def toggle_passphrase(): title = _("Confirm Toggle Passphrase Protection") currently_enabled = self.features.passphrase_protection if currently_enabled: msg = _("After disabling passphrases, you can only pair this " "Electrum wallet if it had an empty passphrase. " "If its passphrase was not empty, you will need to " "create a new wallet with the install wizard. You " "can use this wallet again at any time by re-enabling " "passphrases and entering its passphrase.") else: msg = _("Your current Electrum wallet can only be used with " "an empty passphrase. You must create a separate " "wallet with the install wizard for other passphrases " "as each one generates a new set of addresses.") msg += "\n\n" + _("Are you sure you want to proceed?") if not self.question(msg, title=title): return invoke_client('toggle_passphrase', unpair_after=currently_enabled) def change_homescreen(): dialog = QFileDialog(self, _("Choose Homescreen")) filename, __ = dialog.getOpenFileName() if not filename: return # user cancelled if filename.endswith('.toif'): img = open(filename, 'rb').read() if img[:8] != b'TOIf\x90\x00\x90\x00': handler.show_error('File is not a TOIF file with size of \ 144x144') return else: from PIL import Image # FIXME im = Image.open(filename) if im.size != (128, 64): handler.show_error('Image must be 128 x 64 pixels') return im = im.convert('1') pix = im.load() img = bytearray(1024) for j in range(64): for i in range(128): if pix[i, j]: o = (i + j * 128) img[o // 8] |= (1 << (7 - o % 8)) img = bytes(img) invoke_client('change_homescreen', img) def clear_homescreen(): invoke_client('change_homescreen', b'\x00') def set_pin(): invoke_client('set_pin', remove=False) def clear_pin(): invoke_client('set_pin', remove=True) def wipe_device(): wallet = window.wallet if wallet and sum(wallet.get_balance()): title = _("Confirm Device Wipe") msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has bitcoins in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True) def slider_moved(): mins = timeout_slider.sliderPosition() timeout_minutes.setText(_("%2d minutes") % mins) def slider_released(): config.set_session_timeout(timeout_slider.sliderPosition() * 60) # Information tab info_tab = QWidget() info_layout = QVBoxLayout(info_tab) info_glayout = QGridLayout() info_glayout.setColumnStretch(2, 1) device_label = QLabel() pin_set_label = QLabel() passphrases_label = QLabel() version_label = QLabel() device_id_label = QLabel() bl_hash_label = QLabel() bl_hash_label.setWordWrap(True) language_label = QLabel() initialized_label = QLabel() rows = [ (_("Device Label"), device_label), (_("PIN set"), pin_set_label), (_("Passphrases"), passphrases_label), (_("Firmware Version"), version_label), (_("Device ID"), device_id_label), (_("Bootloader Hash"), bl_hash_label), (_("Language"), language_label), (_("Initialized"), initialized_label), ] for row_num, (label, widget) in enumerate(rows): info_glayout.addWidget(QLabel(label), row_num, 0) info_glayout.addWidget(widget, row_num, 1) info_layout.addLayout(info_glayout) # Settings tab settings_tab = QWidget() settings_layout = QVBoxLayout(settings_tab) settings_glayout = QGridLayout() # Settings tab - Label label_msg = QLabel( _("Name this {}. If you have multiple devices " "their labels help distinguish them.").format(plugin.device)) label_msg.setWordWrap(True) label_label = QLabel(_("Device Label")) label_edit = QLineEdit() label_edit.setMinimumWidth(150) label_edit.setMaxLength(plugin.MAX_LABEL_LEN) label_apply = QPushButton(_("Apply")) label_apply.clicked.connect(rename) label_edit.textChanged.connect(set_label_enabled) settings_glayout.addWidget(label_label, 0, 0) settings_glayout.addWidget(label_edit, 0, 1, 1, 2) settings_glayout.addWidget(label_apply, 0, 3) settings_glayout.addWidget(label_msg, 1, 1, 1, -1) pin_button = QPushButton() # Settings tab - PIN pin_label = QLabel(_("PIN Protection")) pin_button.clicked.connect(set_pin) settings_glayout.addWidget(pin_label, 2, 0) settings_glayout.addWidget(pin_button, 2, 1) pin_msg = QLabel( _("PIN protection is strongly recommended. " "A PIN is your only protection against someone " "stealing your bitcoins if they obtain physical " "access to your {}.").format(plugin.device)) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 1, 1, -1) # Settings tab - Homescreen homescreen_label = QLabel(_("Homescreen")) homescreen_change_button = QPushButton(_("Change...")) homescreen_clear_button = QPushButton(_("Reset")) homescreen_change_button.clicked.connect(change_homescreen) try: import PIL except ImportError: homescreen_change_button.setDisabled(True) homescreen_change_button.setToolTip( _("Required package 'PIL' is not available - Please install \ it or use the OctoWallet website instead.")) homescreen_clear_button.clicked.connect(clear_homescreen) homescreen_msg = QLabel( _("You can set the homescreen on your " "device to personalize it. You must " "choose a {} x {} monochrome black and " "white image.").format(hs_rows, hs_cols)) homescreen_msg.setWordWrap(True) settings_glayout.addWidget(homescreen_label, 4, 0) settings_glayout.addWidget(homescreen_change_button, 4, 1) settings_glayout.addWidget(homescreen_clear_button, 4, 2) settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1) # Settings tab - Session Timeout timeout_label = QLabel(_("Session Timeout")) timeout_minutes = QLabel() timeout_slider = QSlider(Qt.Horizontal) timeout_slider.setRange(1, 60) timeout_slider.setSingleStep(1) timeout_slider.setTickInterval(5) timeout_slider.setTickPosition(QSlider.TicksBelow) timeout_slider.setTracking(True) timeout_msg = QLabel( _("Clear the session after the specified period " "of inactivity. Once a session has timed out, " "your PIN and passphrase (if enabled) must be " "re-entered to use the device.")) timeout_msg.setWordWrap(True) timeout_slider.setSliderPosition(config.get_session_timeout() // 60) slider_moved() timeout_slider.valueChanged.connect(slider_moved) timeout_slider.sliderReleased.connect(slider_released) settings_glayout.addWidget(timeout_label, 6, 0) settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3) settings_glayout.addWidget(timeout_minutes, 6, 4) settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1) settings_layout.addLayout(settings_glayout) settings_layout.addStretch(1) # Advanced tab advanced_tab = QWidget() advanced_layout = QVBoxLayout(advanced_tab) advanced_glayout = QGridLayout() # Advanced tab - clear PIN clear_pin_button = QPushButton(_("Disable PIN")) clear_pin_button.clicked.connect(clear_pin) clear_pin_warning = QLabel( _("If you disable your PIN, anyone with physical access to your " "{} device can spend your bitcoins.").format(plugin.device)) clear_pin_warning.setWordWrap(True) clear_pin_warning.setStyleSheet("color: red") advanced_glayout.addWidget(clear_pin_button, 0, 2) advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5) # Advanced tab - toggle passphrase protection passphrase_button = QPushButton() passphrase_button.clicked.connect(toggle_passphrase) passphrase_msg = WWLabel(PASSPHRASE_HELP) passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN) passphrase_warning.setStyleSheet("color: red") advanced_glayout.addWidget(passphrase_button, 3, 2) advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5) advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5) # Advanced tab - wipe device wipe_device_button = QPushButton(_("Wipe Device")) wipe_device_button.clicked.connect(wipe_device) wipe_device_msg = QLabel( _("Wipe the device, removing all data from it. The firmware " "is left unchanged.")) wipe_device_msg.setWordWrap(True) wipe_device_warning = QLabel( _("Only wipe a device if you have the recovery seed written down " "and the device wallet(s) are empty, otherwise the bitcoins " "will be lost forever.")) wipe_device_warning.setWordWrap(True) wipe_device_warning.setStyleSheet("color: red") advanced_glayout.addWidget(wipe_device_button, 6, 2) advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5) advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5) advanced_layout.addLayout(advanced_glayout) advanced_layout.addStretch(1) tabs = QTabWidget(self) tabs.addTab(info_tab, _("Information")) tabs.addTab(settings_tab, _("Settings")) tabs.addTab(advanced_tab, _("Advanced")) dialog_vbox = QVBoxLayout(self) dialog_vbox.addWidget(tabs) dialog_vbox.addLayout(Buttons(CloseButton(self))) # Update information invoke_client(None)
class Slider(QMainWindow): def __init__(self, application): super().__init__() self._init_ui() self._initPygame(application) self.setWindowTitle('Settings') # allow slider to handle float def _valueHandler(self, value): # type of "value" is int so you need to convert it to float # in order to get float type for "scaledValue" scaledValue = float(value) / 100 print(scaledValue, type(scaledValue)) def _animate(self): if self.application.isAnimating: self.application.isAnimating = False else: self.application.isAnimating = True def _init_ui(self): self.statusBar().showMessage('Ready') # ------- FILE MENU menubar = self.menuBar() fileMenu = menubar.addMenu('File') impMenu = QMenu('Import', self) impAct = QAction('Import obj', self) impMenu.addAction(impAct) newAct = QAction('New', self) fileMenu.addAction(newAct) fileMenu.addMenu(impMenu) # ------- Icon exit and animate exitAct = QAction( QIcon('models/icon_exit.png'), 'Exit', self) exitAct.setShortcut('Ctrl+Q') exitAct.triggered.connect(qApp.quit) animationButton = QAction( QIcon('models/icon_play.png'), 'Animate', self) animationButton.setShortcut('Space') animationButton.triggered.connect(self._animate) # self.action.setShortcut("ESC") # ------- Display slider value lcdAperture = QLCDNumber(self) lcdFocalLength = QLCDNumber(self) # lcdNear = QLCDNumber(self) lcdFar = QLCDNumber(self) # ------- Slider creation and connection to lcd self.sldAperture = QSlider(Qt.Horizontal, self) self.sldAperture.setTickPosition(QSlider.TicksBothSides) self.sldFocalLength = QSlider(Qt.Horizontal, self) self.sldFocalLength.setTickPosition(QSlider.TicksBothSides) ''' self.sldNear = QSlider(Qt.Horizontal, self) self.sldNear.setTickPosition(QSlider.TicksBothSides) ''' self.sldFar = QSlider(Qt.Horizontal, self) self.sldFar.setTickPosition(QSlider.TicksBothSides) # ------- Connect slider to lcd self.sldAperture.valueChanged.connect(lcdAperture.display) self.sldFocalLength.valueChanged.connect(lcdFocalLength.display) ''' self.sldNear.valueChanged.connect(lcdNear.display) ''' self.sldFar.valueChanged.connect(lcdFar.display) # ------- Slider parameter and specifications # self.sldAperture.setMinimum(0) # self.sldAperture.setMaximum(80) self.sldAperture.setValue(sC.aperture) self.sldAperture.setRange(10, 100) self.sldFocalLength.setValue(sC.focalLength) self.sldFocalLength.setRange(1, 15) self.sldFocalLength.valueChanged.connect(self._valueHandler) ''' self.sldNear.setValue(sC.near) self.sldNear.setRange(0,10) self.sldNear.valueChanged.connect(self._valueHandler) ''' self.sldFar.setValue(sC.far) self.sldFar.setRange(50, 150) # ------- Show slide bar self.exitToolbar = self.addToolBar('exit') self.exitToolbar.addAction(exitAct) self.exitToolbar.addAction(animationButton) # ------- Go back to line self.addToolBarBreak() self.lcdToolbar = self.addToolBar('lcd') self.lcdToolbar.addWidget(lcdAperture) self.apertureToolbar = self.addToolBar('aperture') self.apertureToolbar.addWidget(self.sldAperture) self.apertureToolbar.addWidget(QLabel("Aperture")) self.addToolBarBreak() self.lcdToolbar2 = self.addToolBar('lcd2') self.lcdToolbar2.addWidget(lcdFocalLength) self.focalLengthToolbar = self.addToolBar('focalLength') self.focalLengthToolbar.addWidget(self.sldFocalLength) self.focalLengthToolbar.addWidget(QLabel("focalLength *100")) self.addToolBarBreak() ''' self.lcdToolbarNear = self.addToolBar('lcd2') self.lcdToolbarNear.addWidget(lcdNear) self.nearToolbar = self.addToolBar('near') self.nearToolbar.addWidget(self.sldNear) self.nearToolbar.addWidget(QLabel("near(/100)")) self.addToolBarBreak() ''' self.lcdToolbarFar = self.addToolBar('lcdFar') self.lcdToolbarFar.addWidget(lcdFar) self.farToolbar = self.addToolBar('far') self.farToolbar.addWidget(self.sldFar) self.farToolbar.addWidget(QLabel("far")) # ------- required to display self.setGeometry(600, 600, 600, 600) self.show() def _initPygame(self, application): # https://stackoverflow.com/questions/46656634/pyqt5-qtimer-count-until-specific-seconds self.application = application self.timer = QTimer() self.timer.timeout.connect(self._pygame_loop) self.timer.start(0) def _uiUpdate(self): sC.aperture = self.sldAperture.value() sC.focalLength = self.sldFocalLength.value() # sC.near = self.sldNear.value() sC.far = self.sldFar.value() sC.update() def _pygame_loop(self): self._uiUpdate() if self.application._run(self): self.close()
def init_stiffness_ctrl(self): slayout = QVBoxLayout() prefix = "meka_roscontrol" suffix = "stiffness_controller/command" button = QPushButton("Stiffness controller (beta)") self.stiffness_pub = rospy.Publisher("/" + prefix + "/" + suffix, Float64MultiArray, queue_size=1) group_names = ["right_arm", "left_arm", "right_hand", "left_hand", "head", "torso", "zlift"] # slider for each group joint_names = [ "right_arm_j0", "right_arm_j1", "right_arm_j2", "right_arm_j3", "right_arm_j4", "right_arm_j5", "right_arm_j6", "left_arm_j0", "left_arm_j1", "left_arm_j2", "left_arm_j3", "left_arm_j4", "left_arm_j5", "left_arm_j6", "right_hand_j0", "right_hand_j1", "right_hand_j2", "right_hand_j3", "right_hand_j4", "left_hand_j0", "left_hand_j1", "left_hand_j2", "left_hand_j3", "left_hand_j4", "head_j0", "head_j1", "torso_j0", "torso_j1", "zlift_j0"] self._stiffness_dict = OrderedDict((name, 1.0) for name in joint_names) menu = QMenu("Menu") menu.setStyleSheet("QMenu { menu-scrollable: 1; }"); self.stiffnessvals = {} for group in group_names: glayout = QHBoxLayout() glayout.addWidget(QLabel(group)) slider = QSlider(Qt.Horizontal) slider.setRange(0,100) slider.setValue(100) slider.setTickPosition(QSlider.TicksBelow) slider.setTickInterval(10) slider.setFixedSize(200,15) slider.setSingleStep(10) slider.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) val = QLabel("1.0") btn = QPushButton("apply") self.stiffnessvals[group] = val btn.clicked.connect(partial(self.on_stiffness_apply, group)) glayout.addWidget(slider) glayout.addWidget(val) glayout.addWidget(btn) slider.valueChanged.connect(partial(self.on_stiffness_change, slider, val, group)) slayout.addLayout(glayout) groupm = menu.addMenu(group) #for joint in joint_names: #groupm.addAction("set stiffness", partial(self.set_stiffness, groupm)) #if group in joint: # groupm.addAction(self._stiffness_dict[joint]) # s.addAction(joint, partial(self.request_fields, component, s)) button.setMenu(menu) return slayout
class SliderWidget(QDialog): ''' class SliderWidget ''' valueChanged = QtCore.pyqtSignal(float) def __init__(self, title, parent = None): super(SliderWidget, self).__init__(parent, Qt.FramelessWindowHint) self._mousePressed = False self._orgPos = QPoint(0, 0) self.setObjectName('SliderWidget') self.resize(500, 150) # self.stylize() # main layout labelTitle = QLabel(title, self) buttonClose = JCloseButton(self) buttonClose.setObjectName('buttonClose') buttonClose.setToolTip('关闭') horiLayoutTitle = QHBoxLayout() horiLayoutTitle.setContentsMargins(6, 0, 6, 6) horiLayoutTitle.addWidget(labelTitle, 0, Qt.AlignTop) horiLayoutTitle.addStretch() horiLayoutTitle.addWidget(buttonClose, 0, Qt.AlignTop) self.doubleSpinBox = QDoubleSpinBox(self) self.doubleSpinBox.setObjectName('doubleSpinBox') self.doubleSpinBox.setMinimumWidth(200) self.doubleSpinBox.setRange(0, 6000) self.doubleSpinBox.setDecimals(2) self.doubleSpinBox.setSingleStep(0.01) self.slider = QSlider(Qt.Horizontal, self) self.slider.setObjectName('slider') self.slider.setRange(self.doubleSpinBox.minimum(), self.doubleSpinBox.maximum()) vertLayoutMain = QVBoxLayout(self) vertLayoutMain.addLayout(horiLayoutTitle) vertLayoutMain.addWidget(self.doubleSpinBox, 0, Qt.AlignHCenter) vertLayoutMain.addSpacing(5) vertLayoutMain.addWidget(self.slider) self.slider.rangeChanged.connect(self.doubleSpinBox.setRange) self.doubleSpinBox.valueChanged.connect(self.doubleSpinBoxValueChanged) self.slider.valueChanged.connect(self.setValue) buttonClose.clicked.connect(self.close) def setRange(self, minValue, maxValue): self.slider.setRange(minValue, maxValue) def setDecimals(self, prec): self.doubleSpinBox.setDecimals(prec) def setSingleStep(self, value): self.doubleSpinBox.setSingleStep(value) def setPrefix(self, prefix): self.doubleSpinBox.setPrefix(prefix) def setSuffix(self, suffix): self.doubleSpinBox.setSuffix(suffix) def doubleSpinBoxValueChanged(self, value): self.slider.setValue(value) self.valueChanged.emit(value) @QtCore.pyqtSlot(float) def setValue(self, value): self.doubleSpinBox.setValue(value) @QtCore.pyqtSlot() def stylize(self): styles.stylize(self) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self._mousePressed = True self._orgPos = event.pos() self.setCursor(Qt.ClosedHandCursor) def mouseMoveEvent(self, event): if self._mousePressed: curPos = event.pos() curGeom = self.geometry() self.move(curGeom.topLeft() + curPos - self._orgPos) def mouseReleaseEvent(self, event): self._mousePressed = False self.setCursor(Qt.ArrowCursor)