def bindSpinboxAndSlider(editor: QSpinBox, slider: QSlider, slot): # 联动 editor.valueChanged.connect(lambda value: slider.setValue(value)) slider.valueChanged.connect(lambda value: editor.setValue(value)) # 绑定槽函数 slider.valueChanged.connect(slot)
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)
class XArmUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(XArmUI, self).__init__() self.handler = XArmHandler(self) self.lang = self.main_ui.lang self.set_ui() self.set_disable(True) def set_ui(self): self._set_common_top_ui() self._set_tab() self._set_common_down_ui() self.connect_slot() def _set_common_top_ui(self): top_frame = QFrame() top_frame.setMaximumHeight(60) top_layout = QVBoxLayout(top_frame) self.layout.addWidget(top_frame) common_top_frame = QFrame() common_top_frame.setMinimumHeight(50) common_top_layout = QHBoxLayout(common_top_frame) top_layout.addWidget(common_top_frame) label_1 = QLabel(i18n[self.lang]['Connected'] + ':') self.label_connected = QLabel() img = QImage() self.label_connected.setMaximumHeight(20) self.label_connected.setMaximumWidth(20) self.label_connected.setScaledContents(True) if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) label_2 = QLabel(i18n[self.lang]['Reported'] + ':') self.label_reported = QLabel() img = QImage() self.label_reported.setMaximumHeight(20) self.label_reported.setMaximumWidth(20) self.label_reported.setScaledContents(True) if img.load(disconnect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) self.lnt_addr = QLineEdit('192.168.1.182') self.lnt_addr.setMaximumWidth(100) self.lnt_addr.setMinimumWidth(60) self.btn_connect = QPushButton(i18n[self.lang]['Connect']) # self.btn_connect.setMaximumWidth(50) # common_top_layout.addStretch(0) common_top_layout.setSpacing(10) common_top_layout.addWidget(label_1) common_top_layout.addWidget(self.label_connected) common_top_layout.addWidget(label_2) common_top_layout.addWidget(self.label_reported) common_top_layout.addWidget(self.lnt_addr) common_top_layout.addWidget(self.btn_connect) # common_down_frame = QFrame() # common_down_layout = QHBoxLayout(common_down_frame) # common_down_layout.setSpacing(0) # top_layout.addWidget(common_down_frame) common_down_layout = common_top_layout label = QLabel(i18n[self.lang]['WarnCode'] + ':') self.label_warn_code = QLabel('0') self.label_warn_code.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_warn_code) label = QLabel(i18n[self.lang]['ErrorCode'] + ':') self.label_error_code = QLabel('0') self.label_error_code.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_error_code) label = QLabel(i18n[self.lang]['CmdCount'] + ':') self.label_cmd_count = QLabel('0') self.label_cmd_count.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_cmd_count) label = QLabel(i18n[self.lang]['State'] + ':') self.label_state = QLabel('4') self.label_state.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_state) label = QLabel(i18n[self.lang]['Maable'] + ':') self.label_maable = QLabel('128') self.label_maable.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_maable) label = QLabel(i18n[self.lang]['Mtbrake'] + ':') self.label_mtbrake = QLabel('128') self.label_mtbrake.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_mtbrake) def _set_tab(self): tab_widget = QTabWidget() tab_widget.setMaximumHeight(self.main_ui.window.geometry().height() // 2) self.layout.addWidget(tab_widget) toolBox1 = QToolBox() toolBox2 = QToolBox() groupBox1 = QGroupBox() groupBox2 = QGroupBox() toolBox1.addItem(groupBox1, "") toolBox2.addItem(groupBox2, "") tab_widget.addTab(toolBox1, i18n[self.lang]['Joint']) tab_widget.addTab(toolBox2, i18n[self.lang]['Cartesian']) joint_layout = QVBoxLayout(groupBox1) cartesian_layout = QVBoxLayout(groupBox2) self.cartesian_ui = CartesianUI(self, cartesian_layout) self.axis_ui = JointUI(self, joint_layout) def _set_common_down_ui(self): slider_frame = QFrame() slider_layout = QGridLayout(slider_frame) self.layout.addWidget(slider_frame) label = QLabel(i18n[self.lang]['Speed'] + ':') self.slider_speed = QSlider(Qt.Horizontal) self.spinbox_speed = QSpinBox() self.slider_speed.setMinimum(1) self.slider_speed.setMaximum(1000) self.slider_speed.setValue(50) self.spinbox_speed.setSingleStep(1) self.spinbox_speed.setMinimum(1) self.spinbox_speed.setMaximum(1000) self.spinbox_speed.setValue(50) slider_layout.addWidget(label, 0, 0) slider_layout.addWidget(self.slider_speed, 0, 1) slider_layout.addWidget(self.spinbox_speed, 0, 2) label = QLabel(i18n[self.lang]['Acc'] + ':') self.slider_acc = QSlider(Qt.Horizontal) self.spinbox_acc = QSpinBox() self.slider_acc.setMinimum(1) self.slider_acc.setMaximum(100000) self.slider_acc.setValue(5000) self.spinbox_acc.setSingleStep(1) self.spinbox_acc.setMinimum(1) self.spinbox_acc.setMaximum(100000) self.spinbox_acc.setValue(5000) slider_layout.addWidget(label, 0, 3) slider_layout.addWidget(self.slider_acc, 0, 4) slider_layout.addWidget(self.spinbox_acc, 0, 5) common_frame = QFrame() common_layout = QGridLayout(common_frame) self.layout.addWidget(common_frame) self.btn_stop = QPushButton(i18n[self.lang]['Stop']) self.btn_clean = QPushButton(i18n[self.lang]['CleanErrorWarn']) self.btn_reset = QPushButton(i18n[self.lang]['Reset']) self.btn_get_servo_dbmsg = QPushButton( i18n[self.lang]['GetServoDebugMsg']) common_layout.addWidget(self.btn_stop, 0, 0) common_layout.addWidget(self.btn_clean, 0, 2) common_layout.addWidget(self.btn_reset, 0, 3) common_layout.addWidget(self.btn_get_servo_dbmsg, 0, 4) btn_frame = QFrame() btn_layout = QGridLayout(btn_frame) self.layout.addWidget(btn_frame) self.combobox_servo = QComboBox() self.combobox_servo.setStyleSheet('''color: blue;''') for item in [ 'axis-all', 'axis-1', 'axis-2', 'axis-3', 'axis-4', 'axis-5', 'axis-6', 'axis-7' ]: self.combobox_servo.addItem(item) self.combobox_servo.setCurrentIndex(1) btn_layout.addWidget(self.combobox_servo, 0, 0) self.btn_motion_enable = QPushButton(i18n[self.lang]['MotionEnable']) self.btn_motion_disable = QPushButton(i18n[self.lang]['MotionDisable']) self.btn_servo_attach = QPushButton(i18n[self.lang]['ServoAttach']) self.btn_servo_detach = QPushButton(i18n[self.lang]['ServoDetach']) self.combobox_state = QComboBox() self.combobox_state.setStyleSheet('''color: blue;''') for item in ['sport', 'pause', 'stop']: self.combobox_state.addItem(item) self.combobox_state.setCurrentIndex(0) self.btn_set_state = QPushButton(i18n[self.lang]['SetState']) btn_layout.addWidget(self.btn_motion_enable, 0, 1) btn_layout.addWidget(self.btn_motion_disable, 0, 2) btn_layout.addWidget(self.btn_servo_attach, 0, 3) btn_layout.addWidget(self.btn_servo_detach, 0, 4) btn_layout.addWidget(self.combobox_state, 0, 5) btn_layout.addWidget(self.btn_set_state, 0, 6) self.lnt_servo_addr = QLineEdit('servo_addr') self.lnt_servo_addr_value = QLineEdit('value') self.btn_get_servo_addr16 = QPushButton( i18n[self.lang]['GetServoAddr16']) self.btn_set_servo_addr16 = QPushButton( i18n[self.lang]['SetServoAddr16']) self.btn_get_servo_addr32 = QPushButton( i18n[self.lang]['GetServoAddr32']) self.btn_set_servo_addr32 = QPushButton( i18n[self.lang]['SetServoAddr32']) self.btn_set_servo_zero = QPushButton(i18n[self.lang]['SetServoZero']) btn_layout.addWidget(self.lnt_servo_addr, 1, 0) btn_layout.addWidget(self.lnt_servo_addr_value, 1, 1) btn_layout.addWidget(self.btn_get_servo_addr16, 1, 2) btn_layout.addWidget(self.btn_set_servo_addr16, 1, 3) btn_layout.addWidget(self.btn_get_servo_addr32, 1, 4) btn_layout.addWidget(self.btn_set_servo_addr32, 1, 5) btn_layout.addWidget(self.btn_set_servo_zero, 1, 6) def connect_slot(self): self.btn_connect.clicked.connect(self.connect) self.slider_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_speed, scale=1)) self.spinbox_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_speed, scale=1)) self.slider_acc.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_acc, scale=1)) self.spinbox_acc.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_acc, scale=1)) self.btn_stop.clicked.connect(self.stop) self.btn_clean.clicked.connect(self.clean) self.btn_reset.clicked.connect(self.reset) self.btn_get_servo_dbmsg.clicked.connect( functools.partial(self.handler.get_servo_debug_msg, only_log_error_servo=False)) self.btn_motion_enable.clicked.connect(self.motion_enable) self.btn_motion_disable.clicked.connect(self.motion_disable) self.btn_servo_attach.clicked.connect(self.set_servo_attach) self.btn_servo_detach.clicked.connect(self.set_servo_detach) self.btn_set_state.clicked.connect(self.set_state) self.btn_get_servo_addr16.clicked.connect(self.get_servo_addr_16) self.btn_set_servo_addr16.clicked.connect(self.set_servo_addr_16) self.btn_get_servo_addr32.clicked.connect(self.get_servo_addr_32) self.btn_set_servo_addr32.clicked.connect(self.set_servo_addr_32) self.btn_set_servo_zero.clicked.connect(self.set_servo_zero) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def reset_flag(self): self.cartesian_ui.reset_flag() self.axis_ui.reset_flag() def update_maable_mtbrake(self, maable, mtbrake): try: self.label_maable.setText(str(maable)) self.label_mtbrake.setText(str(mtbrake)) self.label_maable.setStyleSheet('''color: green;font:bold;''') self.label_mtbrake.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def update_cmd_count(self, cmdnum): try: self.label_cmd_count.setText(str(cmdnum)) self.label_cmd_count.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def update_state(self, state): try: if state == 1: state_str = 'sport' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: green;font:bold;''') elif state == 2: state_str = 'sleep' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: gray;font:bold;''') elif state == 3: state_str = 'pause' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: orange;font:bold;''') elif state == 4: state_str = 'stop' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: red;font:bold;''') except Exception as e: print(e) # getattr(self, 'label_state').setText(state_str) # getattr(self, 'label_state').setText(str(state)) if state != 1: self.reset_flag() def update_warn_error(self, item): try: warn, error = item self.label_warn_code.setText(str(warn)) self.label_error_code.setText(str(error)) if warn != 0: self.label_warn_code.setStyleSheet('''color: red;font:bold;''') else: self.label_warn_code.setStyleSheet( '''color: green;font:bold;''') if error != 0: self.label_error_code.setStyleSheet( '''color: red;font:bold;''') else: self.label_error_code.setStyleSheet( '''color: green;font:bold;''') except Exception as e: print(e) def update_connect_status(self, item): try: img = QImage() if item[0]: logger.info('connect to {} success, report: {}'.format( self.handler.addr, self.handler.report_type)) if img.load(connect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Disconnect']) self.btn_connect.setStyleSheet('''color: red;font:bold;''') self.set_disable(False) else: logger.info('disconnect from or failed connect {}'.format( self.handler.addr)) self.handler.cmd_que.queue.clear() if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet( '''color: green;font:bold;''') self.set_disable(True) if item[1]: if img.load(connect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) else: if img.load(disconnect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) except Exception as e: print(e) def connect(self, event): try: if str(self.btn_connect.text()) == i18n[self.lang]['Connect']: addr = self.lnt_addr.text().strip() if addr == '192.168.1.': addr = 'localhost' report_type = 'normal' else: tmp = addr.split(':') addr = tmp[0] report_type = tmp[1] if len(tmp) > 1 else 'normal' self.btn_connect.setText('Connecting') self.btn_connect.setStyleSheet('''color: orange;font:bold;''') self.handler.connect(addr, report_type=report_type) # if self.window.connect(addr, report_type=report_type): # self.btn_connect.setText(self.disconnect_label) # self.btn_connect.setStyleSheet('''color: red;font:bold;''') elif str(self.btn_connect.text()) == i18n[self.lang]['Disconnect']: self.handler.disconnect() self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def stop(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': 0, 'enable': True } } self.handler.put_cmd_que(item) item = { 'cmd': 'urgent_stop', } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) def clean(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) except Exception as e: print(e) def reset(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': 0, 'enable': True } } self.handler.put_cmd_que(item) item = {'cmd': 'set_state', 'kwargs': {'state': 0}} self.handler.put_cmd_que(item) item = { 'cmd': 'move_gohome', 'kwargs': { 'speed': 30, 'mvacc': 5000, } } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) def get_servo_addr_16(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要获取电机{}的地址{}的值吗?'.format(servo_id, addr) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'get_servo_addr_16', 'kwargs': { 'servo_id': servo_id, 'addr': addr } } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_servo_addr_32(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要获取电机{}的地址{}的值吗?'.format(servo_id, addr) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'get_servo_addr_32', 'kwargs': { 'servo_id': servo_id, 'addr': addr } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_addr_16(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return value = self.lnt_servo_addr_value.text().strip() try: value = float(value) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的值, 值必须是float32类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要设置电机{}的地址{}的值为{}吗?'.format(servo_id, addr, value) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_addr_16', 'kwargs': { 'servo_id': servo_id, 'addr': addr, 'value': value } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_addr_32(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return value = self.lnt_servo_addr_value.text().strip() try: value = float(value) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的值, 值必须是float32类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要设置电机{}的地址{}的值为{}吗?'.format(servo_id, addr, value) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_addr_32', 'kwargs': { 'servo_id': servo_id, 'addr': addr, 'value': value } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_zero(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) if servo_id == 8: tmp = '你确定要设置所有电机的零点吗?' else: tmp = '你确定要设置电机{}的零点吗?'.format(servo_id) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_zero', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_attach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) item = { 'cmd': 'set_servo_attach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': servo_id, 'enable': True } } self.handler.put_cmd_que(item) item = {'cmd': 'set_state', 'kwargs': {'state': 0}} self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_detach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) if servo_id == 8: tmp = '你确定要解锁所有电机吗?' else: tmp = '你确定要解锁电机{}吗?'.format(servo_id) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_detach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def motion_enable(self, event): self._motion_enable(True) def motion_disable(self, event): self._motion_enable(False) def _motion_enable(self, enable=True): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': servo_id, 'enable': enable } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_state(self, event): try: text = self.combobox_state.currentText() if text == 'sport': state = 0 elif text == 'pause': state = 3 elif text == 'stop': state = 4 else: return if state in [0, 3, 4]: item = {'cmd': 'set_state', 'kwargs': {'state': state}} self.handler.put_cmd_que(item) except Exception as e: print(e) def set_disable(self, disable): try: self.btn_stop.setDisabled(disable) self.btn_clean.setDisabled(disable) self.btn_reset.setDisabled(disable) self.btn_get_servo_dbmsg.setDisabled(disable) self.combobox_servo.setDisabled(disable) self.combobox_state.setDisabled(disable) self.btn_motion_enable.setDisabled(disable) self.btn_motion_disable.setDisabled(disable) self.btn_servo_attach.setDisabled(disable) self.btn_servo_detach.setDisabled(disable) self.btn_set_state.setDisabled(disable) self.lnt_servo_addr.setDisabled(disable) self.lnt_servo_addr_value.setDisabled(disable) self.btn_get_servo_addr16.setDisabled(disable) self.btn_set_servo_addr16.setDisabled(disable) self.btn_get_servo_addr32.setDisabled(disable) self.btn_set_servo_addr32.setDisabled(disable) self.btn_set_servo_zero.setDisabled(disable) self.slider_speed.setDisabled(disable) self.spinbox_speed.setDisabled(disable) self.slider_acc.setDisabled(disable) self.spinbox_acc.setDisabled(disable) self.axis_ui.set_disable(disable) self.cartesian_ui.set_disable(disable) except Exception as e: print(e)
class GcodeUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(GcodeUI, self).__init__() self.isOutlineMode = True self.isLaserMode = True self.handler = GcodeHandler(self) self.set_ui() self.connect_slot() self.gcode = '' def set_ui(self): self._set_up_frame_ui() self._set_middle_frame_ui() self._set_down_frame_ui() def _set_up_frame_ui(self): self.up_frame = QFrame() self.up_frame.setMinimumHeight(300) self.up_frame.setMaximumHeight(500) self.up_layout = QHBoxLayout(self.up_frame) up_left_frame = QFrame() # up_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2) # up_left_frame.setMaximumWidth(self.geometry().width() / 2) up_right_frame = QFrame() # up_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2) # up_right_frame.setMaximumWidth(self.geometry().width() / 2) self.up_left_layout = QHBoxLayout(up_left_frame) self.up_right_layout = QHBoxLayout(up_right_frame) self.up_layout.addWidget(up_left_frame) # self.up_layout.addWidget(up_right_frame) self.layout.addWidget(self.up_frame) self.label_img = QLabel() # self.label_img.setMaximumHeight(320) # self.label_img.setMaximumWidth(480) # self.label_img.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # self.label_img.setScaledContents(True) img = QImage() if img.load(os.path.join(icon_path, 'tmp.svg')): self.label_img.setPixmap(QPixmap.fromImage(img)) with open(os.path.join(icon_path, 'tmp.svg'), 'rb') as f: self.handler.source = f.read() self.up_left_layout.addWidget(self.label_img) self.label_img_preview = QLabel() # self.label_img_preview.setMaximumHeight(320) # self.label_img_preview.setMaximumWidth(480) self.label_img_preview.setDisabled(True) # # self.label_img_preview.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # # self.label_img_preview.setScaledContents(True) # data = np.zeros(320 * 240) # img = QImage(data, 320, 240, QImage.Format_RGB888) # pixmap = QPixmap.fromImage(img) # self.label_img_preview.setPixmap(pixmap) self.up_right_layout.addWidget(self.label_img_preview) # self.up_frame.hide() def _set_middle_frame_ui(self): middle_frame = QFrame() self.middle_layout = QHBoxLayout(middle_frame) middle_left_frame = QFrame() # middle_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20) middle_right_frame = QFrame() # middle_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20) self.middle_left_layout = QGridLayout(middle_left_frame) self.middle_right_layout = QGridLayout(middle_right_frame) self.middle_layout.addWidget(middle_left_frame) self.middle_layout.addWidget(middle_right_frame) self.layout.addWidget(middle_frame) row = 0 self.checkbox_outline = QRadioButton('OutLine') self.checkbox_gray = QRadioButton('Gray') self.checkbox_gray.hide() self.btn_load_img = QPushButton('LoadImage') self.checkbox_outline.toggle() self.isOutlineMode = True self.checkbox_outline.setDisabled(True) self.middle_left_layout.addWidget(self.checkbox_outline, row, 0) self.middle_left_layout.addWidget(self.checkbox_gray, row, 1) self.middle_left_layout.addWidget(self.btn_load_img, row, 2) row += 1 label_x_home = QLabel('x_home:') self.slider_x_home = QSlider(QtCore.Qt.Horizontal) self.slider_x_home.setMinimum(0) self.slider_x_home.setMaximum(2000) self.slider_x_home.setValue(1500) self.spinbox_x_home = QDoubleSpinBox() self.spinbox_x_home.setDecimals(1) self.spinbox_x_home.setSingleStep(0.1) self.spinbox_x_home.setMinimum(0.0) self.spinbox_x_home.setMaximum(200.0) self.spinbox_x_home.setValue(150.0) self.slider_x_home.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_x_home.mouseReleaseEvent) self.spinbox_x_home.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_x_home.focusOutEvent) self.middle_left_layout.addWidget(label_x_home, row, 0) self.middle_left_layout.addWidget(self.slider_x_home, row, 1) self.middle_left_layout.addWidget(self.spinbox_x_home, row, 2) row += 1 label_y_home = QLabel('y_home:') self.slider_y_home = QSlider(QtCore.Qt.Horizontal) self.slider_y_home.setMinimum(-1500) self.slider_y_home.setMaximum(1500) self.slider_y_home.setValue(0) self.spinbox_y_home = QDoubleSpinBox() self.spinbox_y_home.setDecimals(1) self.spinbox_y_home.setSingleStep(0.1) self.spinbox_y_home.setMinimum(-150.0) self.spinbox_y_home.setMaximum(150.0) self.spinbox_y_home.setValue(0.0) self.slider_y_home.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_y_home.mouseReleaseEvent) self.spinbox_y_home.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_y_home.focusOutEvent) self.middle_left_layout.addWidget(label_y_home, row, 0) self.middle_left_layout.addWidget(self.slider_y_home, row, 1) self.middle_left_layout.addWidget(self.spinbox_y_home, row, 2) row += 1 label_z_home = QLabel('z_home:') self.slider_z_home = QSlider(QtCore.Qt.Horizontal) self.slider_z_home.setMinimum(0) self.slider_z_home.setMaximum(1500) self.slider_z_home.setValue(900) self.spinbox_z_home = QDoubleSpinBox() self.spinbox_z_home.setDecimals(1) self.spinbox_z_home.setSingleStep(0.1) self.spinbox_z_home.setMinimum(0.0) self.spinbox_z_home.setMaximum(150.0) self.spinbox_z_home.setValue(90.0) self.slider_z_home.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_z_home.mouseReleaseEvent) self.spinbox_z_home.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_z_home.focusOutEvent) self.middle_left_layout.addWidget(label_z_home, row, 0) self.middle_left_layout.addWidget(self.slider_z_home, row, 1) self.middle_left_layout.addWidget(self.spinbox_z_home, row, 2) row += 1 label_x_offset = QLabel('x_offset:') self.slider_x_offset = QSlider(QtCore.Qt.Horizontal) self.slider_x_offset.setMinimum(-5000) self.slider_x_offset.setMaximum(5000) self.slider_x_offset.setValue(0) self.spinbox_x_offset = QDoubleSpinBox() self.spinbox_x_offset.setSingleStep(0.1) self.spinbox_x_offset.setDecimals(1) self.spinbox_x_offset.setMinimum(-500.0) self.spinbox_x_offset.setMaximum(500.0) self.spinbox_x_offset.setValue(0.0) self.slider_x_offset.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_x_offset.mouseReleaseEvent) self.spinbox_x_offset.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_x_offset.focusOutEvent) self.middle_left_layout.addWidget(label_x_offset, row, 0) self.middle_left_layout.addWidget(self.slider_x_offset, row, 1) self.middle_left_layout.addWidget(self.spinbox_x_offset, row, 2) row += 1 label_y_offset = QLabel('y_offset:') self.slider_y_offset = QSlider(QtCore.Qt.Horizontal) self.slider_y_offset.setMinimum(-5000) self.slider_y_offset.setMaximum(5000) self.slider_y_offset.setValue(0) self.spinbox_y_offset = QDoubleSpinBox() self.spinbox_y_offset.setDecimals(1) self.spinbox_y_offset.setSingleStep(0.1) self.spinbox_y_offset.setMinimum(-500.0) self.spinbox_y_offset.setMaximum(500.0) self.spinbox_y_offset.setValue(0.0) self.slider_y_offset.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_y_offset.mouseReleaseEvent) self.spinbox_y_offset.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_y_offset.focusOutEvent) self.middle_left_layout.addWidget(label_y_offset, row, 0) self.middle_left_layout.addWidget(self.slider_y_offset, row, 1) self.middle_left_layout.addWidget(self.spinbox_y_offset, row, 2) row += 1 label_z_offset = QLabel('z_offset:') self.slider_z_offset = QSlider(QtCore.Qt.Horizontal) self.slider_z_offset.setMinimum(-1000) self.slider_z_offset.setMaximum(1500) self.slider_z_offset.setValue(900) self.spinbox_z_offset = QDoubleSpinBox() self.spinbox_z_offset.setDecimals(1) self.spinbox_z_offset.setSingleStep(0.1) self.spinbox_z_offset.setMinimum(-100.0) self.spinbox_z_offset.setMaximum(150.0) self.spinbox_z_offset.setValue(90.0) self.slider_z_offset.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_z_offset.mouseReleaseEvent) self.spinbox_z_offset.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_z_offset.focusOutEvent) self.middle_left_layout.addWidget(label_z_offset, row, 0) self.middle_left_layout.addWidget(self.slider_z_offset, row, 1) self.middle_left_layout.addWidget(self.spinbox_z_offset, row, 2) row += 1 label_pen_up = QLabel('pen_up:') self.slider_pen_up = QSlider(QtCore.Qt.Horizontal) self.slider_pen_up.setMinimum(0) self.slider_pen_up.setMaximum(500) self.slider_pen_up.setValue(200) self.spinbox_pen_up = QDoubleSpinBox() self.spinbox_pen_up.setDecimals(1) self.spinbox_pen_up.setSingleStep(0.1) self.spinbox_pen_up.setMinimum(0.0) self.spinbox_pen_up.setMaximum(50.0) self.spinbox_pen_up.setValue(20.0) self.slider_pen_up.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_pen_up.mouseReleaseEvent) self.spinbox_pen_up.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_pen_up.focusOutEvent) self.slider_pen_up.setDisabled(True) self.spinbox_pen_up.setDisabled(True) self.middle_left_layout.addWidget(label_pen_up, row, 0) self.middle_left_layout.addWidget(self.slider_pen_up, row, 1) self.middle_left_layout.addWidget(self.spinbox_pen_up, row, 2) row = 0 self.checkbox_laser = QRadioButton('Laser') self.checkbox_pen = QRadioButton('Pen') self.checkbox_laser.toggle() self.isLaserMode = True self.middle_right_layout.addWidget(self.checkbox_laser, row, 0) self.middle_right_layout.addWidget(self.checkbox_pen, row, 1) row += 1 label_drawing_feedrate = QLabel('drawing_feedrate:') self.slider_drawing_feedrate = QSlider(QtCore.Qt.Horizontal) self.slider_drawing_feedrate.setMinimum(5) self.slider_drawing_feedrate.setMaximum(1000) self.slider_drawing_feedrate.setValue(100) self.spinbox_drawing_feedrate = QSpinBox() self.spinbox_drawing_feedrate.setMinimum(5) self.spinbox_drawing_feedrate.setMaximum(1000) self.spinbox_drawing_feedrate.setValue(100) self.slider_drawing_feedrate.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_drawing_feedrate.mouseReleaseEvent) self.spinbox_drawing_feedrate.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_drawing_feedrate.focusOutEvent) self.middle_right_layout.addWidget(label_drawing_feedrate, row, 0) self.middle_right_layout.addWidget(self.slider_drawing_feedrate, row, 1) self.middle_right_layout.addWidget(self.spinbox_drawing_feedrate, row, 2) row += 1 label_moving_feedrate = QLabel('moving_feedrate:') self.slider_moving_feedrate = QSlider(QtCore.Qt.Horizontal) self.slider_moving_feedrate.setMinimum(5) self.slider_moving_feedrate.setMaximum(20000) self.slider_moving_feedrate.setValue(100) self.spinbox_moving_feedrate = QSpinBox() self.spinbox_moving_feedrate.setMinimum(5) self.spinbox_moving_feedrate.setMaximum(20000) self.spinbox_moving_feedrate.setValue(100) self.slider_moving_feedrate.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_moving_feedrate.mouseReleaseEvent) self.spinbox_moving_feedrate.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_moving_feedrate.focusOutEvent) self.middle_right_layout.addWidget(label_moving_feedrate, row, 0) self.middle_right_layout.addWidget(self.slider_moving_feedrate, row, 1) self.middle_right_layout.addWidget(self.spinbox_moving_feedrate, row, 2) row += 1 label_scale = QLabel('scale:') self.slider_scale = QSlider(QtCore.Qt.Horizontal) self.slider_scale.setMinimum(1) self.slider_scale.setMaximum(100) self.slider_scale.setValue(10) self.spinbox_scale = QDoubleSpinBox() self.spinbox_scale.setDecimals(1) self.spinbox_scale.setSingleStep(0.1) self.spinbox_scale.setMinimum(0.1) self.spinbox_scale.setMaximum(10.0) self.spinbox_scale.setValue(1.0) # self.slider_scale.setDisabled(True) # self.spinbox_scale.setDisabled(True) self.slider_scale.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_scale.mouseReleaseEvent) self.spinbox_scale.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_scale.focusOutEvent) self.middle_right_layout.addWidget(label_scale, row, 0) self.middle_right_layout.addWidget(self.slider_scale, row, 1) self.middle_right_layout.addWidget(self.spinbox_scale, row, 2) row += 1 label_resolution = QLabel('resolution:') self.slider_resolution = QSlider(QtCore.Qt.Horizontal) self.slider_resolution.setMinimum(1) self.slider_resolution.setMaximum(100) self.slider_resolution.setValue(10) self.spinbox_resolution = QDoubleSpinBox() self.spinbox_resolution.setMinimum(0.1) self.spinbox_resolution.setMaximum(10.0) self.spinbox_resolution.setSingleStep(0.1) self.spinbox_resolution.setDecimals(1) self.spinbox_resolution.setValue(1.0) self.slider_resolution.setDisabled(True) self.spinbox_resolution.setDisabled(True) self.middle_right_layout.addWidget(label_resolution, row, 0) self.middle_right_layout.addWidget(self.slider_resolution, row, 1) self.middle_right_layout.addWidget(self.spinbox_resolution, row, 2) row += 1 self.btn_generate_gcode = QPushButton('Generate_Gcode') self.middle_right_layout.addWidget(self.btn_generate_gcode, row, 0) row += 1 self.label_x_min = QLabel('') self.label_x_max = QLabel('') self.middle_right_layout.addWidget(self.label_x_min, row, 0) self.middle_right_layout.addWidget(self.label_x_max, row, 1) row += 1 self.label_y_min = QLabel('') self.label_y_max = QLabel('') self.middle_right_layout.addWidget(self.label_y_min, row, 0) self.middle_right_layout.addWidget(self.label_y_max, row, 1) def _set_down_frame_ui(self): self.down_frame = QFrame() self.down_layout = QHBoxLayout(self.down_frame) self.layout.addWidget(self.down_frame) self.textEdit = QTextEdit() self.down_layout.addWidget(self.textEdit) # self.down_frame.hide() def select_engrave_mode(self, event): self.isOutlineMode = event # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode)) def select_end_type(self, event): self.isLaserMode = event self.slider_pen_up.setDisabled(self.isLaserMode) self.spinbox_pen_up.setDisabled(self.isLaserMode) self.generate_gcode() # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode)) def connect_slot(self): self.checkbox_outline.toggled.connect(self.select_engrave_mode) self.checkbox_laser.toggled.connect(self.select_end_type) self.btn_load_img.clicked.connect(self.load_image) self.slider_x_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_x_home, scale=.1)) self.spinbox_x_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_x_home, scale=10)) self.slider_y_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_y_home, scale=.1)) self.spinbox_y_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_y_home, scale=10)) self.slider_z_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_z_home, scale=.1)) self.spinbox_z_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_z_home, scale=10)) self.slider_x_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_x_offset, scale=.1)) self.spinbox_x_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_x_offset, scale=10)) self.slider_y_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_y_offset, scale=.1)) self.spinbox_y_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_y_offset, scale=10)) self.slider_z_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_z_offset, scale=.1)) self.spinbox_z_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_z_offset, scale=10)) self.slider_pen_up.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_pen_up, scale=.1)) self.spinbox_pen_up.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_pen_up, scale=10)) self.slider_scale.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_scale, scale=.1)) self.spinbox_scale.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_scale, scale=10)) self.slider_resolution.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_resolution, scale=.1)) self.spinbox_resolution.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_resolution, scale=10)) self.slider_drawing_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_drawing_feedrate, scale=1)) self.spinbox_drawing_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_drawing_feedrate, scale=1)) self.slider_moving_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_moving_feedrate, scale=1)) self.spinbox_moving_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_moving_feedrate, scale=1)) self.btn_generate_gcode.clicked.connect( functools.partial(self.generate_gcode, flag=True)) def slider_spinbox_related(self, value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def mouseReleaseEvent(self, event, source=None): try: self.generate_gcode() except Exception as e: print(e) source(event) def focusOutEvent(self, event, source=None): try: self.generate_gcode() except Exception as e: print(e) source(event) def generate_gcode(self, flag=False): if self.handler.template is None and flag: self.handler.svg_to_gcode() if self.handler.template: pen_up = self.spinbox_pen_up.value() if not self.isLaserMode else 0 config = { 'x_home': self.spinbox_x_home.value(), 'y_home': self.spinbox_y_home.value(), 'z_home': self.spinbox_z_home.value(), 'z_offset': self.spinbox_z_offset.value(), 'pen_up': pen_up, 'z_offset_pen_up': self.spinbox_z_offset.value() + pen_up, 'moving_feedrate': self.spinbox_moving_feedrate.value(), 'drawing_feedrate': self.spinbox_drawing_feedrate.value(), } self.gcode = self.handler.template.format(**config) self.change_gcode() # self.textEdit.setText(self.gcode) def change_gcode(self): if self.gcode: x_offset = self.spinbox_x_offset.value() y_offset = self.spinbox_y_offset.value() z_offset = self.spinbox_z_offset.value() moving_feedrate = self.spinbox_moving_feedrate.value() drawing_feedrate = self.spinbox_drawing_feedrate.value() scale = self.spinbox_scale.value() lines = self.gcode.split('\n') for i, line in enumerate(lines): List = line.strip().split(' ') line = '' for l in List: if l.startswith('F'): if line.startswith(('G01', 'G1')): l = 'F{}'.format(drawing_feedrate) elif line.startswith(('G00', 'G0')): l = 'F{}'.format(moving_feedrate) elif l.startswith('X'): x = float(l[1:]) * scale + x_offset l = 'X{0:.2f}'.format(x) elif l.startswith('Y'): y = float(l[1:]) * scale + y_offset l = 'Y{0:.2f}'.format(y) # elif l.startswith('Z'): # z = float(l[1:]) + z_offset # l = 'Z{0:.2f}'.format(z) line += l + ' ' line = line.strip() lines[i] = line self.calc_gcode(lines) gcode = '\n'.join(lines) self.textEdit.setText(gcode) def calc_gcode(self, lines): x_list = [] y_list = [] for i, line in enumerate(lines): if line.startswith(tuple(['G0', 'G1', 'G00', 'G01'])): List = line.strip().split(' ') for l in List: if l.startswith('X'): x = float(l[1:]) x_list.append(x) elif l.startswith('Y'): y = float(l[1:]) y_list.append(y) if len(x_list) > 0: x_min = np.min(x_list) x_max = np.max(x_list) self.label_x_min.setText('X(min): ' + str(x_min)) self.label_x_max.setText('X(max): ' + str(x_max)) # print('x_min: {}, x_max: {}, x_distance: {}'.format(x_min, x_max, x_max - x_min)) if len(y_list) > 0: y_min = np.min(y_list) y_max = np.max(y_list) self.label_y_min.setText('Y(min): ' + str(y_min)) self.label_y_max.setText('Y(max): ' + str(y_max)) # print('y_min: {}, y_max: {}, y_distance: {}'.format(y_min, y_max, y_max - y_min)) def load_image(self): fname = QFileDialog.getOpenFileName(self.main_ui.window, 'Open file', '', '*.svg') if fname and fname[0]: img = QImage() if img.load(fname[0]): self.label_img.setPixmap(QPixmap.fromImage(img)) with open(fname[0], 'rb') as f: self.handler.source = f.read() self.handler.template = None self.gcode = None self.up_frame.show()
class UArmUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(UArmUI, self).__init__() self.handler = UArmHandler(self) self.lang = self.main_ui.lang self.status = 0 self.set_ui() self.set_disable(True) def set_ui(self): self._set_common_top_ui() self._set_tab() self._set_common_down_ui() self.connect_slot() def _set_common_top_ui(self): top_frame = QFrame() top_frame.setMaximumHeight(60) top_layout = QVBoxLayout(top_frame) self.layout.addWidget(top_frame) common_top_frame = QFrame() common_top_frame.setMinimumHeight(50) common_top_frame.setMaximumHeight(50) common_top_layout = QHBoxLayout(common_top_frame) top_layout.addWidget(common_top_frame) common_top_layout.addStretch(0) label = QLabel(i18n[self.lang]['Type'] + ':') self.label_type = QLabel('') self.label_type.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_type) label = QLabel(i18n[self.lang]['Mode'] + ':') self.label_mode = QLabel('') self.label_mode.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_mode) label = QLabel(i18n[self.lang]['HardwareVersion'] + ':') self.label_hard_version = QLabel('') self.label_hard_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_hard_version) label = QLabel(i18n[self.lang]['FirmwareVersion'] + ':') self.label_firm_version = QLabel('') self.label_firm_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_firm_version) label_1 = QLabel(i18n[self.lang]['Connected'] + ':') self.label_connected = QLabel() img = QImage() self.label_connected.setMaximumHeight(20) self.label_connected.setMaximumWidth(20) self.label_connected.setScaledContents(True) if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.lnt_addr = QLineEdit('COM12') self.lnt_addr.setMaximumWidth(50) self.lnt_addr.setMinimumWidth(30) self.btn_connect = QPushButton(i18n[self.lang]['Connect']) # self.btn_connect.setMaximumWidth(50) # common_top_layout.addStretch(0) common_top_layout.setSpacing(10) common_top_layout.addWidget(label_1) common_top_layout.addWidget(self.label_connected) common_top_layout.addWidget(self.lnt_addr) common_top_layout.addWidget(self.btn_connect) def _set_common_down_ui(self): slider_frame = QFrame() slider_layout = QGridLayout(slider_frame) self.layout.addWidget(slider_frame) label = QLabel(i18n[self.lang]['Speed'] + ':') self.slider_speed = QSlider(Qt.Horizontal) self.spinbox_speed = QSpinBox() self.slider_speed.setMinimum(1) self.slider_speed.setMaximum(100000) self.slider_speed.setValue(10000) self.spinbox_speed.setSingleStep(1) self.spinbox_speed.setMinimum(1) self.spinbox_speed.setMaximum(100000) self.spinbox_speed.setValue(10000) slider_layout.addWidget(label, 0, 0) slider_layout.addWidget(self.slider_speed, 0, 1) slider_layout.addWidget(self.spinbox_speed, 0, 2) # label = QLabel(i18n[self.lang]['Acc'] + ':') # self.slider_acc = QSlider(Qt.Horizontal) # self.spinbox_acc = QSpinBox() # self.slider_acc.setMinimum(1) # self.slider_acc.setMaximum(100000) # self.slider_acc.setValue(5000) # self.spinbox_acc.setSingleStep(1) # self.spinbox_acc.setMinimum(1) # self.spinbox_acc.setMaximum(100000) # self.spinbox_acc.setValue(5000) # slider_layout.addWidget(label, 0, 3) # slider_layout.addWidget(self.slider_acc, 0, 4) # slider_layout.addWidget(self.spinbox_acc, 0, 5) btn_frame = QFrame() btn_layout = QGridLayout(btn_frame) self.layout.addWidget(btn_frame) self.btn_get_device_info = QPushButton(i18n[self.lang]['GetDeviceInfo']) self.btn_get_position = QPushButton(i18n[self.lang]['GetPosition']) self.btn_get_polar = QPushButton(i18n[self.lang]['GetPolar']) self.btn_get_servo_angle = QPushButton(i18n[self.lang]['GetServoAngle']) self.btn_get_mode = QPushButton(i18n[self.lang]['GetMode']) btn_layout.addWidget(self.btn_get_device_info, 0, 0) btn_layout.addWidget(self.btn_get_position, 0, 1) btn_layout.addWidget(self.btn_get_polar, 0, 2) btn_layout.addWidget(self.btn_get_servo_angle, 0, 3) btn_layout.addWidget(self.btn_get_mode, 0, 4) self.combobox_servo = QComboBox() self.combobox_servo.setStyleSheet('''color: blue;''') for item in ['axis-1', 'axis-2', 'axis-3', 'axis-all']: self.combobox_servo.addItem(item) self.combobox_servo.setCurrentIndex(0) btn_layout.addWidget(self.combobox_servo, 0, 0) self.btn_servo_attach = QPushButton(i18n[self.lang]['ServoAttach']) self.btn_servo_detach = QPushButton(i18n[self.lang]['ServoDetach']) self.combobox_mode = QComboBox() self.combobox_mode.setStyleSheet('''color: blue;''') for item in ['normal', 'laser', '3D', 'pen']: self.combobox_mode.addItem(item) self.combobox_mode.setCurrentIndex(0) self.btn_set_mode = QPushButton(i18n[self.lang]['SetMode']) btn_layout.addWidget(self.combobox_servo, 1, 0) btn_layout.addWidget(self.btn_servo_attach, 1, 1) btn_layout.addWidget(self.btn_servo_detach, 1, 2) btn_layout.addWidget(self.combobox_mode, 1, 3) btn_layout.addWidget(self.btn_set_mode, 1, 4) self.btn_reset = QPushButton(i18n[self.lang]['Reset']) self.btn_pump_on = QPushButton(i18n[self.lang]['PumpOn']) self.btn_pump_off = QPushButton(i18n[self.lang]['PumpOff']) self.btn_gripper_catch = QPushButton(i18n[self.lang]['GripperCatch']) self.btn_gripper_release = QPushButton(i18n[self.lang]['GripperRelease']) btn_layout.addWidget(self.btn_reset, 2, 0) btn_layout.addWidget(self.btn_pump_on, 2, 1) btn_layout.addWidget(self.btn_pump_off, 2, 2) btn_layout.addWidget(self.btn_gripper_catch, 2, 3) btn_layout.addWidget(self.btn_gripper_release, 2, 4) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def connect_slot(self): self.btn_connect.clicked.connect(self.connect) self.slider_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_speed, scale=1)) self.spinbox_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_speed, scale=1)) # self.slider_acc.valueChanged.connect( # functools.partial(self.slider_spinbox_related, slave=self.spinbox_acc, scale=1)) # self.spinbox_acc.valueChanged.connect( # functools.partial(self.slider_spinbox_related, slave=self.slider_acc, scale=1)) self.btn_get_device_info.clicked.connect(self.get_device_info) self.btn_get_position.clicked.connect(self.get_position) self.btn_get_polar.clicked.connect(self.get_polar) self.btn_get_servo_angle.clicked.connect(self.get_servo_angle) self.btn_get_mode.clicked.connect(self.get_mode) self.btn_servo_attach.clicked.connect(self.set_servo_attach) self.btn_servo_detach.clicked.connect(self.set_servo_detach) self.btn_set_mode.clicked.connect(self.set_mode) self.btn_reset.clicked.connect(self.reset) self.btn_pump_on.clicked.connect(self.pump_on) self.btn_pump_off.clicked.connect(self.pump_off) self.btn_gripper_catch.clicked.connect(self.gripper_catch) self.btn_gripper_release.clicked.connect(self.gripper_release) def reset_flag(self): self.cartesian_ui.reset_flag() self.axis_ui.reset_flag() def update_connect_status(self, item): try: img = QImage() if item and self.status != 1: self.status = 1 logger.info('connect to {} success'.format(self.handler.port)) if img.load(connect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Disconnect']) self.btn_connect.setStyleSheet('''color: red;font:bold;''') self.set_disable(False) elif not item and self.status != 0: self.status = 0 logger.info('disconnect from {0} or failed connect {0}'.format(self.handler.port)) self.handler.cmd_que.queue.clear() if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') self.set_disable(True) except Exception as e: print(e) def connect(self): try: if str(self.btn_connect.text()) == i18n[self.lang]['Connect']: addr = self.lnt_addr.text().strip() if addr == 'auto': addr = None self.btn_connect.setText('Connecting') self.status = 2 self.btn_connect.setStyleSheet('''color: orange;font:bold;''') self.handler.connect(addr) # if self.window.connect(addr, report_type=report_type): # self.btn_connect.setText(self.disconnect_label) # self.btn_connect.setStyleSheet('''color: red;font:bold;''') elif str(self.btn_connect.text()) == i18n[self.lang]['Disconnect']: self.handler.disconnect() self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def get_device_info(self, event): try: item = { 'cmd': 'get_device_info', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_mode(self, event): try: item = { 'cmd': 'get_mode', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_position(self, event): try: item = { 'cmd': 'get_position', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_polar(self, event): try: item = { 'cmd': 'get_polar', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_servo_angle(self, event): try: item = { 'cmd': 'get_servo_angle', } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_attach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = None else: servo_id = int(self.combobox_servo.currentIndex()) item = { 'cmd': 'set_servo_attach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_detach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = None else: servo_id = int(self.combobox_servo.currentIndex()) item = { 'cmd': 'set_servo_detach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def pump_on(self, event): try: item = { 'cmd': 'set_pump', 'kwargs': { 'on': True } } self.handler.put_cmd_que(item) except Exception as e: print(e) def pump_off(self, event): try: item = { 'cmd': 'set_pump', 'kwargs': { 'on': False } } self.handler.put_cmd_que(item) except Exception as e: print(e) def gripper_catch(self, event): try: item = { 'cmd': 'set_gripper', 'kwargs': { 'catch': True } } self.handler.put_cmd_que(item) except Exception as e: print(e) def gripper_release(self, event): try: item = { 'cmd': 'set_gripper', 'kwargs': { 'catch': False } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_mode(self, event): try: mode = self.combobox_mode.currentIndex() item = { 'cmd': 'set_mode', 'kwargs': { 'mode': int(mode) } } self.handler.put_cmd_que(item) except Exception as e: print(e) def reset(self, event): try: self.handler.cmd_que.queue.clear() item = { 'cmd': 'reset', 'kwargs': { 'speed': self.spinbox_speed.value(), 'wait': False, } } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def _set_tab(self): tab_widget = QTabWidget() tab_widget.setMaximumHeight(self.main_ui.window.geometry().height() // 2) self.layout.addWidget(tab_widget) toolBox1 = QToolBox() toolBox2 = QToolBox() groupBox1 = QGroupBox() groupBox2 = QGroupBox() toolBox1.addItem(groupBox1, "") toolBox2.addItem(groupBox2, "") tab_widget.addTab(toolBox1, i18n[self.lang]['Angle']) tab_widget.addTab(toolBox2, i18n[self.lang]['Coordinate']) joint_layout = QVBoxLayout(groupBox1) cartesian_layout = QVBoxLayout(groupBox2) self.cartesian_ui = CoordinateUI(self, cartesian_layout) self.axis_ui = AngleUI(self, joint_layout) def update_device_info(self, device_info): if device_info is not None: self.label_type.setText(str(device_info.get('device_type', None))) self.label_hard_version.setText(str(device_info.get('hardware_version', None))) self.label_firm_version.setText(str(device_info.get('firmware_version', None))) def update_mode(self, mode): if mode is not None: if mode == 0: mode_str = 'Normal' elif mode == 1: mode_str = 'Laser' elif mode == 2: mode_str = '3D' elif mode == 3: mode_str = 'Pen' else: mode_str = self.label_mode.text() self.label_mode.setText(mode_str) def set_disable(self, disable): try: self.btn_get_device_info.setDisabled(disable) self.btn_get_position.setDisabled(disable) self.btn_get_polar.setDisabled(disable) self.btn_get_servo_angle.setDisabled(disable) self.btn_get_mode.setDisabled(disable) self.combobox_servo.setDisabled(disable) self.combobox_mode.setDisabled(disable) self.btn_servo_attach.setDisabled(disable) self.btn_servo_detach.setDisabled(disable) self.btn_reset.setDisabled(disable) self.btn_pump_on.setDisabled(disable) self.btn_pump_off.setDisabled(disable) self.btn_gripper_catch.setDisabled(disable) self.btn_gripper_release.setDisabled(disable) self.slider_speed.setDisabled(disable) self.spinbox_speed.setDisabled(disable) # self.slider_acc.setDisabled(disable) # self.spinbox_acc.setDisabled(disable) self.axis_ui.set_disable(disable) self.cartesian_ui.set_disable(disable) except Exception as e: print(e)
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 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()
class ParameterBar(QHBoxLayout): def __init__(self, name, vmin, vmax, _type, tick): super().__init__() self._name = name self._vmin = vmin self._vmax = vmax self._type = _type self._tick = tick self._length = self._get_interval_length() self._label = None self._slider = None state.set('parm_outside', True) self._setup_ui() state.on_changed(self._name, self._update) state.set('parm_outside', False) def _setup_ui(self): self.setSpacing(12) self.setAlignment(Qt.AlignCenter) if 'BalanceRatio' in self._name: icon_path = 'wb' else: icon_path = self._name.lower() # icon label = QLabel() label.setToolTip(self._name) label.setPixmap(icons.get(icon_path)) label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) label.setFixedWidth(45) self.addWidget(label) # slider self._slider = QSlider(Qt.Horizontal) self._slider.setMinimum(0) self._slider.setMaximum(self._length) if icon_path == 'wb': self._slider.setObjectName(self._name) self._slider.valueChanged.connect(self._on_slider_changed) self.addWidget(self._slider) # value self._label = QLabel() self._label.setContentsMargins(0, 0, 0, 4) self._label.setFixedWidth(45) self.addWidget(self._label) self._update() def _get_interval_length(self): return int((self._vmax - self._vmin) / self._tick) + 1 def _on_slider_changed(self, value): if not state.get('parm_outside'): v = self._vmin + (self._vmax - self._vmin) * value / self._length state.cast('camera', 'change_parameter', self._name, v) def _update(self): value = state.get(self._name) if self._type == 'int': text = str(int(value)) elif value == 0: text = '0' else: text = f'{value:.02f}'.rstrip('0.') self._label.setText(text) if state.get('parm_outside'): v = (value - self._vmin) / (self._vmax - self._vmin) * self._length self._slider.setValue(int(v))
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)