class plotScroller: def update_val(self, proc): d=str(self.scl.value()) self.v.setText(d) if proc != None: proc(self.scl.value()) def __init__(self, master, text, geo, proc=None, lim=(0,100,1)): self.scl=QScrollBar(Qt.Horizontal, master) self.scl.resize(geo[2]-50,geo[3]) self.scl.move(geo[0]+50,geo[1]) self.scl.setMinimum(lim[0]) self.scl.setMaximum(lim[1]) self.scl.setSingleStep(lim[2]) self.scl.valueChanged.connect(lambda: self.update_val(proc)) q=QLabel(master) q.move(geo[0],geo[1]+10) q.resize(50,20) q.setText(text) self.v=QLabel(master) self.v.move(geo[2]+10,geo[1]+10) self.v.resize(50,20) self.v.setText(str(self.scl.value())) def setValue(self, v): self.scl.setValue(v)
class SlidersGroup(QGroupBox): valueChanged = pyqtSignal(int) def __init__(self, orientation, title, parent=None): super(SlidersGroup, self).__init__(title, parent) self.slider = QSlider(orientation) self.slider.setFocusPolicy(Qt.StrongFocus) self.slider.setTickPosition(QSlider.TicksBothSides) self.slider.setTickInterval(10) self.slider.setSingleStep(1) self.scrollBar = QScrollBar(orientation) self.scrollBar.setFocusPolicy(Qt.StrongFocus) self.dial = QDial() self.dial.setFocusPolicy(Qt.StrongFocus) self.slider.valueChanged.connect(self.scrollBar.setValue) self.scrollBar.valueChanged.connect(self.dial.setValue) self.dial.valueChanged.connect(self.slider.setValue) self.dial.valueChanged.connect(self.valueChanged) if orientation == Qt.Horizontal: direction = QBoxLayout.TopToBottom else: direction = QBoxLayout.LeftToRight slidersLayout = QBoxLayout(direction) slidersLayout.addWidget(self.slider) slidersLayout.addWidget(self.scrollBar) slidersLayout.addWidget(self.dial) self.setLayout(slidersLayout) def setValue(self, value): self.slider.setValue(value) def setMinimum(self, value): self.slider.setMinimum(value) self.scrollBar.setMinimum(value) self.dial.setMinimum(value) def setMaximum(self, value): self.slider.setMaximum(value) self.scrollBar.setMaximum(value) self.dial.setMaximum(value) def invertAppearance(self, invert): self.slider.setInvertedAppearance(invert) self.scrollBar.setInvertedAppearance(invert) self.dial.setInvertedAppearance(invert) def invertKeyBindings(self, invert): self.slider.setInvertedControls(invert) self.scrollBar.setInvertedControls(invert) self.dial.setInvertedControls(invert)
class ObjMotorWidgetUI(QWidget): # waveforms_generated = pyqtSignal(object, object, list, int) # SignalForContourScanning = pyqtSignal(int, int, int, np.ndarray, np.ndarray) # MessageBack = pyqtSignal(str) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # os.chdir('./')# Set directory to current folder. self.setFont(QFont("Arial")) # self.setMinimumSize(1350,900) self.setWindowTitle("ObjMotorWidget") self.layout = QGridLayout(self) self.connect_status = False #************************************************************************************************************************************** #-------------------------------------------------------------------------------------------------------------------------------------- #-----------------------------------------------------------GUI for Objective Motor---------------------------------------------------- #-------------------------------------------------------------------------------------------------------------------------------------- #************************************************************************************************************************************** # Movement based on relative positions. self.ObjMotorcontrolContainer = QGroupBox("Objective motor control") self.ObjMotorcontrolContainer.setStyleSheet("QGroupBox {\ font: bold;\ border: 1px solid silver;\ border-radius: 6px;\ margin-top: 12px;\ color:Navy; \ background-color: #FFFAFA}\ QGroupBox::title{subcontrol-origin: margin;\ left: 7px;\ padding: 5px 5px 5px 5px;}") self.ObjMotorcontrolLayout = QGridLayout() self.ObjMotor_connect = StylishQT.connectButton() self.ObjMotor_connect.setFixedWidth(70) self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_connect, 0, 0) self.ObjMotor_connect.clicked.connect(lambda: self.ConnectMotor()) self.ObjMotor_connect.setGraphicsEffect(QGraphicsDropShadowEffect(blurRadius=3, xOffset=2, yOffset=2)) self.ObjMotor_disconnect = StylishQT.disconnectButton() self.ObjMotor_disconnect.setFixedWidth(70) self.ObjMotor_disconnect.setGraphicsEffect(QGraphicsDropShadowEffect(blurRadius=3, xOffset=2, yOffset=2)) self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_disconnect, 0, 1) self.ObjMotor_disconnect.clicked.connect(lambda: self.DisconnectMotor()) self.ObjMotor_disconnect.setEnabled(False) self.ObjMotor_upwards = QPushButton("↑") self.ObjMotor_upwards.setStyleSheet("QPushButton {color:white;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}" "QPushButton:pressed {color:red;background-color: white; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}" "QPushButton:hover:!pressed {color:gray;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}") self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_upwards, 2, 2) self.ObjMotor_upwards.clicked.connect(lambda: self.MovingMotorThread("Motor_move_upwards")) # self.ObjMotor_upwards.setShortcut('w') self.ObjMotor_down = QPushButton("↓") self.ObjMotor_down.setStyleSheet("QPushButton {color:white;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}" "QPushButton:pressed {color:red;background-color: white; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}" "QPushButton:hover:!pressed {color:gray;background-color: teal; border-style: outset;border-radius: 10px;border-width: 2px;font: bold 14px;padding: 6px}") self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_down, 3, 2) self.ObjMotor_down.clicked.connect(lambda: self.MovingMotorThread("Motor_move_downwards")) # self.stage_down.setShortcut('s') self.ObjMotor_target = QDoubleSpinBox(self) self.ObjMotor_target.setMinimum(-10000) self.ObjMotor_target.setMaximum(10000) self.ObjMotor_target.setDecimals(6) # self.ObjMotor_target.setValue(3.45) self.ObjMotor_target.setSingleStep(0.001) self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_target, 1, 1) self.ObjMotorcontrolLayout.addWidget(QLabel("Target:"), 1, 0) self.ObjMotor_current_pos_Label = QLabel("Current position: ") self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_current_pos_Label, 2, 0, 1, 2) self.ObjMotor_goto = QPushButton() self.ObjMotor_goto.setIcon(QIcon('./Icons/move_coord.png')) self.ObjMotor_goto.setToolTip("Move to absolute position") self.ObjMotor_goto.setStyleSheet("QPushButton {color:white;background-color: #CCFFFF;}" "QPushButton:hover:!pressed {color:white;background-color: #FFE5CC;}") self.ObjMotor_goto.setFixedWidth(35) self.ObjMotor_goto.setFixedHeight(35) self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_goto, 1, 2) self.ObjMotor_goto.clicked.connect(lambda: self.MovingMotorThread("Motor_move_target")) self.ObjMotor_step = QDoubleSpinBox(self) self.ObjMotor_step.setMinimum(-10000) self.ObjMotor_step.setMaximum(10000) self.ObjMotor_step.setDecimals(6) self.ObjMotor_step.setValue(0.003) self.ObjMotor_step.setSingleStep(0.001) self.ObjMotorcontrolLayout.addWidget(self.ObjMotor_step, 3, 1) self.ObjMotorcontrolLayout.addWidget(QLabel("Step: "), 3, 0) self.FocusSlider = QScrollBar(Qt.Horizontal) self.FocusSlider.setMinimum(2500000) self.FocusSlider.setMaximum(4500000) # self.FocusSlider.setTickPosition(QSlider.TicksBothSides) # self.FocusSlider.setTickInterval(1000000) self.FocusSlider.setStyleSheet('color:white; background: lightblue') self.FocusSlider.setSingleStep(10000) # self.line640 = QLineEdit(self) # self.line640.setFixedWidth(60) # self.FocusSlider.sliderReleased.connect(lambda:self.updatelinevalue(640)) self.FocusSlider.valueChanged.connect(lambda:self.MovingMotorThread("Motor_move_slider")) self.FocusSlider.setTracking(False) # self.line640.returnPressed.connect(lambda:self.updatesider(640)) self.ObjMotorcontrolLayout.addWidget(self.FocusSlider, 4, 0, 1, 3) self.ObjMotorcontrolContainer.setLayout(self.ObjMotorcontrolLayout) self.ObjMotorcontrolContainer.setMaximumHeight(300) self.layout.addWidget(self.ObjMotorcontrolContainer, 4, 0) #************************************************************************************************************************************** #-------------------------------------------------------------------------------------------------------------------------------------- #-----------------------------------------------------------Fucs for Motor movement---------------------------------------------------- #-------------------------------------------------------------------------------------------------------------------------------------- #************************************************************************************************************************************** def ConnectMotor(self): self.ObjMotorcontrolContainer.setEnabled(False) self.ObjMotor_disconnect.setEnabled(True) self.ObjMotor_connect.setEnabled(False) self.device_instance = ConnectObj_Thread() self.device_instance.start() self.device_instance.finished.connect(self.getmotorhandle) def getmotorhandle(self): self.pi_device_instance = self.device_instance.getInstance() print('Objective motor connected.') self.connect_status = True # self.normalOutputWritten('Objective motor connected.'+'\n') self.ObjCurrentPos = self.pi_device_instance.pidevice.qPOS(self.pi_device_instance.pidevice.axes) self.ObjMotor_current_pos_Label.setText("Current position: {:.4f}".format(self.ObjCurrentPos['1'])) # Axis here is a string. self.ObjMotor_target.setValue(self.ObjCurrentPos['1']) decimal_places = len(str(self.ObjCurrentPos['1']).split('.')[1]) print(int(self.ObjCurrentPos['1']*(10**decimal_places))) self.FocusSlider.setValue(int(self.ObjCurrentPos['1']*(10**6))) self.ObjMotorcontrolContainer.setEnabled(True) def MovingMotorThread(self, target): if target == "Motor_move_target": MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('Target',)) MoveMotorThread.start() elif target == "Motor_move_upwards": MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('UP',)) MoveMotorThread.start() elif target == "Motor_move_downwards": MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('DOWN',)) MoveMotorThread.start() elif target == "Motor_move_slider": MoveMotorThread = threading.Thread(target = self.MoveMotor, args=('Slider',)) MoveMotorThread.start() def MoveMotor(self, direction): if direction == "Target": pos = PIMotor.move(self.pi_device_instance.pidevice, self.ObjMotor_target.value()) elif direction == "UP": self.MotorStep = self.ObjMotor_step.value() pos = PIMotor.move(self.pi_device_instance.pidevice, (self.ObjCurrentPos['1'] + self.MotorStep)) elif direction == "DOWN": self.MotorStep = self.ObjMotor_step.value() pos = PIMotor.move(self.pi_device_instance.pidevice, (self.ObjCurrentPos['1'] - self.MotorStep)) elif direction == "Slider": pos = PIMotor.move(self.pi_device_instance.pidevice, self.FocusSlider.value()/1000000) self.ObjCurrentPos = self.pi_device_instance.pidevice.qPOS(self.pi_device_instance.pidevice.axes) self.ObjMotor_current_pos_Label.setText("Current position: {:.4f}".format(self.ObjCurrentPos['1'])) # Axis here is a string. self.ObjMotor_target.setValue(self.ObjCurrentPos['1']) # decimal_places = len(str(self.ObjCurrentPos['1']).split('.')[1]) self.FocusSlider.setValue(int(self.ObjCurrentPos['1']*(10**6))) def DisconnectMotor(self): self.ObjMotor_connect.setEnabled(True) self.ObjMotor_disconnect.setEnabled(False) PIMotor.CloseMotorConnection(self.pi_device_instance.pidevice) print('Disconnected') self.connect_status = False # self.normalOutputWritten('Objective motor disconnected.'+'\n') def closeEvent(self, event): # ## Because the software combines both PyQt and PyQtGraph, using the # ## closeEvent() from PyQt will cause a segmentation fault. Calling # ## also the exit() from PyQtGraph solves this problem. # pg.exit() if self.connect_status == True: self.DisconnectMotor() QtWidgets.QApplication.quit() event.accept()
class VanillaWindow(QMainWindow): SHIFT = 100 MAX_BRUSH_SIZE = 500 TOOLBAR_HEIGHT = 791 TOOLBAR_WIDTH = 389 BUTTON_SIZE = 64 MENU_BAR_HEIGHT = 30 BUTTON_SHIFT = 20 MINIMUM_CANVAS_LEFT_SHIFT = 250 def __init__(self): super().__init__() self.to_draw_canvas = False self.to_draw_line = False self.to_draw_rectangle = False self.to_draw_triangle = False self.to_draw_ellipse = False self.to_draw_selection = False self.cursor_on_canvas = False self.shape_start = None self.selection_left = 0 self.selection_right = 0 self.selection_up = 0 self.selection_down = 0 self.selection_width = 0 self.selection_height = 0 self.mouse_pressed = False self.picture_name = None self.canvas = Canvas() self.button_images = {} self.buttons = {} self.layer_tables = [] self.init_ui() def init_ui(self): self.setWindowTitle('Vanilla') self.setWindowIcon(QIcon('images/icon.png')) self.showMaximized() self.setStyleSheet('QMainWindow{background: Gray;}' 'QMenuBar::item:selected{background: #202020;}' 'QMenu::item:disabled{color: #505050;}' 'QToolTip{background : black; font-size: 16px; color: white; ' 'border: black solid 1px}') self.setMouseTracking(True) self.create_menu_bar() self.color_picker = QPushButton('', self) color_picker_height = 100 self.color_picker.setGeometry(50, self.TOOLBAR_HEIGHT + self.MENU_BAR_HEIGHT - color_picker_height - 50, 100, color_picker_height) red = Canvas().current_color.r green = Canvas().current_color.g blue = Canvas().current_color.b self.color_picker.setStyleSheet(f'background: Color({red}, {green}, {blue})') self.color_picker.clicked.connect(self.pick_color) self.color_picker.show() self.size_slider = QSlider(Qt.Horizontal, self) slider_height = 20 self.size_slider.setGeometry(10, self.color_picker.y() - slider_height - 60, 145, slider_height) self.size_slider.setMinimum(1) self.size_slider.setMaximum(self.MAX_BRUSH_SIZE) self.size_slider.valueChanged[int].connect(self.size_changed) self.size_slider.show() validator = QIntValidator(1, self.MAX_BRUSH_SIZE) self.size_edit = QLineEdit('1', self) self.size_edit.setGeometry(self.size_slider.x() + self.size_slider.width() + 5, self.size_slider.y(), 35, 20) self.size_edit.setFont(QFont('Arial', 10)) self.size_edit.setAlignment(Qt.AlignCenter) self.size_edit.setValidator(validator) self.size_edit.textChanged[str].connect(self.size_edited) self.size_edit.show() self.size_label = QLabel('Brush Size:', self) self.size_label.setFont(QFont('Arial', 16)) self.size_label.setStyleSheet('color: lightGray;') self.size_label.setGeometry(self.size_slider.x(), self.size_slider.y() - self.size_slider.height() - 10, self.size_slider.width() + self.size_edit.width() + 5, 30) self.size_label.show() self.create_buttons() width = QDesktopWidget().width() height = QDesktopWidget().height() - 64 size = 20 self.layer_button_left = width - 220 self.add_layer_button = QPushButton('Add Layer', self) self.add_layer_button.setGeometry(self.layer_button_left + 24, self.TOOLBAR_HEIGHT - 15, 150, 30) self.add_layer_button.clicked.connect(self.add_layer) self.add_layer_button.setFont(QFont('Arial', 14)) self.add_layer_button.show() self.layers_label = QLabel('Layers', self) self.layers_label.setFont(QFont('Arial', 20)) self.layers_label.setStyleSheet('color: lightGray;') self.layers_label.setGeometry(self.layer_button_left, 25, 197, 60) self.layers_label.setAlignment(Qt.AlignCenter) self.layers_label.show() self.vertical_scrollbar = QScrollBar(self) self.vertical_scrollbar.setGeometry(width - size, 0, size, height - size) self.vertical_scrollbar.valueChanged[int].connect(self.vertical_scrollbar_value_changed) self.horizontal_scrollbar = QScrollBar(Qt.Horizontal, self) self.horizontal_scrollbar.setGeometry(0, height - size, width - size, size) self.horizontal_scrollbar.valueChanged[int].connect(self.horizontal_scrollbar_value_changed) self.show() def create_buttons(self): left = 25 brush_button = self.create_button(left, self.MENU_BAR_HEIGHT + 20, 'Brush', 'B', self.brush_button_clicked) self.buttons[Tools.BRUSH] = brush_button right = brush_button.x() + brush_button.width() + self.BUTTON_SHIFT eraser_button = self.create_button(right, brush_button.y(), 'Eraser', 'E', self.eraser_button_clicked) self.buttons[Tools.ERASER] = eraser_button fill_button = self.create_button(left, self.get_button_shift(brush_button), 'Fill', 'F', self.fill_button_pressed) self.buttons[Tools.FILL] = fill_button selection_button = self.create_button(right, fill_button.y(), 'Selection', 'S', self.selection_button_clicked) self.buttons[Tools.SELECTION] = selection_button line_button = self.create_button(left, self.get_button_shift(fill_button), 'Line', 'L', self.line_button_clicked) self.buttons[Tools.LINE] = line_button rectangle_button = self.create_button(right, line_button.y(), 'Rectangle', 'R', self.rectangle_button_clicked) self.buttons[Tools.SQUARE] = rectangle_button ellipse_button = self.create_button(left, self.get_button_shift(line_button), 'Ellipse', 'C', self.ellipse_button_clicked) self.buttons[Tools.CIRCLE] = ellipse_button triangle_button = self.create_button(right, ellipse_button.y(), 'Triangle', 'T', self.triangle_button_clicked) self.buttons[Tools.TRIANGLE] = triangle_button right_turn_button = self.create_button(left, self.get_button_shift(ellipse_button), 'Turn Right', 'Ctrl+R', self.turn_selection_right) left_turn_button = self.create_button(right, right_turn_button.y(), 'Turn Left', 'Ctrl+L', self.turn_selection_left) flip_horizontally_button = self.create_button(left, self.get_button_shift(right_turn_button), 'Flip Horizontally', 'Ctrl+H', self.flip_horizontally) flip_vertically_button = self.create_button(right, flip_horizontally_button.y(), 'Flip Vertically', 'Ctrl+F', self.flip_vertically) def create_menu_bar(self): self.menu_bar = self.menuBar() self.menu_bar.setStyleSheet('selection-background-color: #202020; background: #393939; color: lightGray;') file_menu = self.menu_bar.addMenu('&File') new_action = QAction('&New', self) new_action.setShortcut('Ctrl+N') new_action.triggered.connect(self.ask_size) file_menu.addAction(new_action) open_action = QAction('&Open', self) open_action.setShortcut('Ctrl+O') open_action.triggered.connect(self.open) file_menu.addAction(open_action) file_menu.addSeparator() self.save_action = QAction('&Save', self) self.save_action.setShortcut('Ctrl+S') self.save_action.triggered.connect(self.save) self.save_action.setDisabled(True) file_menu.addAction(self.save_action) self.save_as_action = QAction('Save as', self) self.save_as_action.setShortcut('Ctrl+Shift+S') self.save_as_action.triggered.connect(self.save_as) self.save_as_action.setDisabled(True) file_menu.addAction(self.save_as_action) image_menu = self.menu_bar.addMenu('&Image') self.greyscale_action = QAction('Greyscale', self) self.greyscale_action.setShortcut('Ctrl+G') self.greyscale_action.triggered.connect(self.change_greyscale) self.greyscale_action.setDisabled(True) image_menu.addAction(self.greyscale_action) self.brightness_action = QAction('Brightness', self) self.brightness_action.setShortcut('Ctrl+B') self.brightness_action.triggered.connect(self.brightness) self.brightness_action.setDisabled(True) image_menu.addAction(self.brightness_action) selection_menu = self.menu_bar.addMenu('&Selection') self.deselect_action = QAction('Deselect', self) self.deselect_action.setShortcut('Ctrl+D') self.deselect_action.triggered.connect(self.deselect) self.deselect_action.setDisabled(True) selection_menu.addAction(self.deselect_action) self.select_all_action = QAction('Select All', self) self.select_all_action.setShortcut('Ctrl+A') self.select_all_action.triggered.connect(self.select_all) self.select_all_action.setDisabled(True) selection_menu.addAction(self.select_all_action) selection_menu.addSeparator() self.delete_selection_action = QAction('Delete', self) self.delete_selection_action.setShortcut('Delete') self.delete_selection_action.triggered.connect(self.delete_in_selection) self.delete_selection_action.setDisabled(True) selection_menu.addAction(self.delete_selection_action) def create_button(self, x, y, image, shortcut='', action=lambda: None): button = QPushButton('', self) button.setGeometry(x, y, self.BUTTON_SIZE, self.BUTTON_SIZE) button.setStyleSheet('background: transparent;') button.setShortcut(shortcut) button.setToolTip(f'{image} ({shortcut})') button.clicked.connect(action) self.button_images[button] = QImage(f'images/{image}.png') button.show() return button def flip(self, flip_function): if not self.canvas.selection_is_on: return flip_function() self.to_draw_selection = False self.update_canvas() self.update() def flip_horizontally(self): self.flip(self.canvas.flip_horizontally) def flip_vertically(self): self.flip(self.canvas.flip_vertically) def get_button_shift(self, upper_button): return upper_button.y() + upper_button.height() + self.BUTTON_SHIFT def turn_selection_right(self): self.turn_selection(self.canvas.turn_selection_right) def turn_selection_left(self): self.turn_selection(self.canvas.turn_selection_left) def turn_selection(self, turn_function): if not self.canvas.selection_is_on: return turn_function() self.to_draw_selection = False self.update_canvas() self.update() def create_layer_button(self, x, y, layer_number): button = QPushButton('', self) button.setGeometry(x, y, 187, 100) button.setStyleSheet('background: transparent;') button.clicked.connect(lambda: self.change_layer(layer_number)) button.show() return button def change_layer(self, number): self.canvas.change_layer(number) self.update_color_button() self.update() def delete_layer(self, layer_table): self.canvas.delete_layer(layer_table.layer) self.layer_tables.remove(layer_table) self.update_canvas() self.update_layers_buttons() if len(self.canvas.layers) == 5: self.add_layer_button.setDisabled(False) self.update() def update_layers_buttons(self): for table in self.layer_tables: table.close() self.layer_tables = [] x = self.layer_button_left + 5 for i in range(len(self.canvas.layers)): layer = self.canvas.layers[i] btn = self.create_layer_button(x, 90 + i * 105, i) self.layer_tables.append(LayerTable(x, 90 + i * 105, layer, btn, self)) def add_layer(self): self.canvas.add_layer() if len(self.canvas.layers) == 6: self.add_layer_button.setDisabled(True) self.update_layers_buttons() self.update() def eraser_button_clicked(self): self.canvas.choose_eraser() self.update() def brush_button_clicked(self): self.canvas.choose_brush() self.update() def line_button_clicked(self): self.canvas.choose_line() self.update() def rectangle_button_clicked(self): self.canvas.choose_rectangle() self.update() def triangle_button_clicked(self): self.canvas.choose_triangle() self.update() def ellipse_button_clicked(self): self.canvas.choose_ellipse() self.update() def fill_button_pressed(self): self.canvas.choose_fill() self.update() def selection_button_clicked(self): self.canvas.choose_selection() self.update() def horizontal_scrollbar_value_changed(self, value): self.update() def vertical_scrollbar_value_changed(self, value): self.update() def change_greyscale(self): if self.canvas.active_layer.greyscale: self.canvas.turn_greyscale_off() else: self.canvas.turn_greyscale_on() self.update_canvas() self.update_color_button() self.update() def deselect(self): self.canvas.deselect() self.deselect_action.setDisabled(True) self.delete_selection_action.setDisabled(True) self.to_draw_selection = False self.update() def select_all(self): self.canvas.deselect() self.shape_start = 0, 0 self.cursor_position = self.canvas.width - 1, self.canvas.height - 1 self.update_selection_position() self.canvas.select(*self.shape_start, *self.cursor_position) self.to_draw_selection = True self.deselect_action.setDisabled(False) self.delete_selection_action.setDisabled(False) self.update() def change_brightness(self, brightness): self.canvas.change_brightness(brightness) self.update_canvas() self.update() def brightness(self): success, brightness = BrightnessDialog.get_brightness(self, self.canvas.active_layer.brightness) if success: self.change_brightness(brightness) def delete_in_selection(self): if not self.canvas.selection_is_on: return self.canvas.delete_selection() self.update_canvas() self.update() @property def canvas_left_side(self): return self.canvas_left_edge - self.horizontal_scrollbar.value() @property def canvas_upper_side(self): return self.canvas_upper_edge - self.vertical_scrollbar.value() def size_edited(self, size): if size == '': value = 1 else: value = int(size) if value == 0: self.size_edit.setText('1') else: self.size_slider.setValue(value) def size_changed(self, value): if value == 0: self.canvas.brush_size = 1 else: self.canvas.brush_size = value if self.to_draw_canvas: self.change_cursor() self.size_edit.setText(f'{self.canvas.brush_size}') def pick_color(self): color = QColorDialog.getColor() if color.isValid(): self.canvas.change_color(color.red(), color.green(), color.blue(), color.alpha()) self.update_color_button() def update_color_button(self): cur_color = self.canvas.current_color color = QColor(cur_color.r, cur_color.g, cur_color.b) self.color_picker.setStyleSheet(f'background: {color.name()}') def ask_size(self): success, width, height = SizeDialog.get_size(self) if success: self.create_canvas(width, height) def create_canvas(self, width, height): old_canvas = self.canvas self.canvas = Canvas(width, height) self.canvas.current_color_rgb = old_canvas.current_color_rgb self.canvas.brush_size = old_canvas.brush_size self.canvas.current_tool = old_canvas.current_tool max_size = self.height() - self.SHIFT * 2 proportion = width / height if proportion > 1: self.canvas_width = max_size self.canvas_height = max_size / proportion else: self.canvas_width = max_size * proportion self.canvas_height = max_size self.pixel_size = self.canvas_width / self.canvas.width self.canvas_left_edge = (self.width() - self.canvas_width) / 2 self.canvas_upper_edge = (self.height() - self.canvas_height) / 2 self.canvas_as_image = self.convert_to_image() self.to_draw_canvas = True self.enable_actions() self.update_layers_buttons() def enable_actions(self): self.save_action.setDisabled(False) self.save_as_action.setDisabled(False) self.greyscale_action.setDisabled(False) self.brightness_action.setDisabled(False) self.select_all_action.setDisabled(False) def convert_to_image(self): image = QImage(self.canvas.width, self.canvas.height, QImage.Format_ARGB32) x = 0 y = 0 for layer in self.canvas.layers: for column in layer.pixels: for pixel in column: image.setPixelColor(x, y, QColor(pixel.r, pixel.g, pixel.b, pixel.a)) y += 1 x += 1 y = 0 return image def open(self): load_file_name = QFileDialog.getOpenFileName(self, 'Chose Image File', '', 'PNG Files (*.png);;JPG Files (*.jpg);;BMP Files (*.bmp)')[0] if load_file_name == '': return False self.picture_name = load_file_name image = QImage(load_file_name) self.create_canvas(image.width(), image.height()) for x in range(self.canvas.width): for y in range(self.canvas.height): color = image.pixelColor(x, y) self.canvas.pixels[x][y] = Color(color.red(), color.green(), color.blue(), color.alpha()) self.update_canvas() self.to_draw_canvas = True self.update() def save(self): if self.picture_name is None: self.save_as() else: self.canvas_as_image.save(self.picture_name) def save_as(self): name = QFileDialog.getSaveFileName(self, 'Save', '', 'PNG Files (*.png);;JPG Files (*.jpg);;BMP Files (*.bmp)')[0] if name == '': return False self.picture_name = name self.save() def change_cursor(self): if self.canvas.current_tool == Tools.BRUSH: self.setCursor(self.get_brush_cursor()) elif self.canvas.current_tool == Tools.ERASER: self.setCursor(self.get_eraser_cursor()) elif self.canvas.current_tool == Tools.FILL: self.setCursor(self.get_fill_cursor()) def get_brush_cursor(self): size = (2 * self.canvas.brush_size - 1) * self.pixel_size cursor = QPixmap(size, size) cursor.fill(Qt.transparent) painter = QPainter() painter.begin(cursor) painter.setPen(QColor(self.canvas.current_color.r, self.canvas.current_color.g, self.canvas.current_color.b)) painter.drawEllipse(0, 0, size - 1, size - 1) painter.drawLine(size / 2, size / 4, size / 2, size / 4 * 3) painter.drawLine(size / 4, size / 2, size / 4 * 3, size / 2) painter.end() return QCursor(cursor) def get_eraser_cursor(self): size = (2 * self.canvas.brush_size - 1) * self.pixel_size cursor = QPixmap(size, size) cursor.fill(Qt.transparent) painter = QPainter() painter.begin(cursor) painter.setBrush(QBrush(QColor(255, 255, 255))) painter.drawEllipse(0, 0, size - 1, size - 1) painter.end() return QCursor(cursor) def get_fill_cursor(self): fill = QImage('images/FillCursor.png') cursor = QPixmap(fill.width(), fill.height()) cursor.fill(Qt.transparent) painter = QPainter() painter.begin(cursor) painter.setBrush(QColor(self.canvas.current_color.r, self.canvas.current_color.g, self.canvas.current_color.b)) painter.drawRect(10, 10, 10, 4) painter.drawImage(0, 0, fill) painter.end() return QCursor(cursor) def mouseMoveEvent(self, event): if not self.to_draw_canvas: return x = math.floor((event.pos().x() - self.canvas_left_side) / self.pixel_size) y = math.floor((event.pos().y() - self.canvas_upper_side) / self.pixel_size) if 0 <= x < self.canvas.width and 0 <= y < self.canvas.height: self.cursor_position = (x, y) self.change_cursor() self.cursor_on_canvas = True else: if not self.mouse_pressed: self.shape_start = None self.cursor_on_canvas = False self.setCursor(Qt.ArrowCursor) if self.mouse_pressed: self.move_tools() self.update_canvas() self.update() def move_tools(self): if self.canvas.current_tool in [Tools.BRUSH, Tools.ERASER]: self.canvas.paint(*self.cursor_position) if self.cursor_on_canvas and self.canvas.current_tool == Tools.SELECTION: self.update_selection_position() def update_canvas(self): if not self.to_draw_canvas: return while len(self.canvas.changed_pixels) > 0: x, y = self.canvas.changed_pixels.pop() layer = len(self.canvas.layers) - 1 pixel = self.canvas.get_pixel(x, y, layer) while layer > 0 and pixel.a == 0: layer -= 1 pixel = self.canvas.get_pixel(x, y, layer) self.canvas_as_image.setPixelColor(x, y, QColor(pixel.r, pixel.g, pixel.b, pixel.a)) def mousePressEvent(self, event): if self.cursor_on_canvas and event.button() == Qt.LeftButton: self.mouse_pressed = True self.press_tools() def press_tools(self): if self.canvas.current_tool in [Tools.LINE, Tools.SQUARE, Tools.TRIANGLE, Tools.CIRCLE, Tools.SELECTION]: self.shape_start = self.cursor_position if self.canvas.current_tool in [Tools.BRUSH, Tools.ERASER]: self.canvas.paint(*self.cursor_position) elif self.canvas.current_tool == Tools.LINE: self.to_draw_line = True elif self.canvas.current_tool == Tools.SQUARE: self.to_draw_rectangle = True elif self.canvas.current_tool == Tools.TRIANGLE: self.to_draw_triangle = True elif self.canvas.current_tool == Tools.CIRCLE: self.to_draw_ellipse = True elif self.canvas.current_tool == Tools.FILL: self.canvas.fill(*self.cursor_position) elif self.canvas.current_tool == Tools.SELECTION: self.deselect() self.deselect_action.setDisabled(False) self.delete_selection_action.setDisabled(False) self.to_draw_selection = True def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton and self.to_draw_canvas: self.release_tools() self.update_canvas() self.update() self.mouse_pressed = False def release_tools(self): if self.shape_start is None: return if self.canvas.current_tool == Tools.SELECTION: self.canvas.select(*self.shape_start, *self.cursor_position) if self.canvas.current_tool == Tools.LINE: self.to_draw_line = False self.canvas.draw_line(*self.shape_start, *self.cursor_position) elif self.canvas.current_tool == Tools.SQUARE: self.to_draw_rectangle = False self.canvas.draw_rectangle(*self.shape_start, *self.cursor_position) elif self.canvas.current_tool == Tools.TRIANGLE: self.to_draw_triangle = False self.canvas.draw_triangle(*self.shape_start, *self.cursor_position) elif self.canvas.current_tool == Tools.CIRCLE: self.to_draw_ellipse = False self.canvas.draw_ellipse(*self.shape_start, *self.cursor_position) def wheelEvent(self, event): if not self.to_draw_canvas: return delta = event.angleDelta().y() / 120 old_width = self.canvas_width old_height = self.canvas_height if self.canvas.width * (self.pixel_size + delta) > 0 and self.canvas.height * (self.pixel_size + delta) > 0: self.pixel_size += delta self.canvas_width = self.canvas.width * self.pixel_size self.canvas_height = self.canvas.height * self.pixel_size self.canvas_left_edge += (old_width - self.canvas_width) / 2 self.canvas_upper_edge += (old_height - self.canvas_height) / 2 self.change_cursor() self.update() if self.canvas_left_edge < self.MINIMUM_CANVAS_LEFT_SHIFT: max = self.MINIMUM_CANVAS_LEFT_SHIFT - self.canvas_left_edge self.horizontal_scrollbar.setMaximum(max) self.horizontal_scrollbar.setMinimum(-max) self.horizontal_scrollbar.show() else: self.horizontal_scrollbar.hide() if self.canvas_upper_edge < self.MENU_BAR_HEIGHT: max = self.MENU_BAR_HEIGHT - self.canvas_upper_edge self.vertical_scrollbar.setMinimum(-max) self.vertical_scrollbar.setMaximum(max) self.vertical_scrollbar.show() else: self.vertical_scrollbar.hide() def paintEvent(self, event): painter = QPainter() painter.begin(self) if self.to_draw_canvas: self.draw_pixels(painter) painter.setPen(QColor(self.canvas.current_color.r, self.canvas.current_color.g, self.canvas.current_color.b)) if self.to_draw_line: self.draw_line(painter) if self.to_draw_rectangle: self.draw_rectangle(painter) if self.to_draw_triangle: self.draw_triangle(painter) if self.to_draw_ellipse: self.draw_ellipse(painter) if self.to_draw_selection: self.draw_selection(painter) self.draw_edges(painter) self.draw_layers(painter) painter.drawImage(0, self.menu_bar.height(), QImage('images/ToolBar.png')) self.highlight_current_button(painter) self.draw_buttons(painter) painter.end() def draw_layers(self, painter): painter.drawImage(self.width() - self.TOOLBAR_WIDTH, self.menu_bar.height(), QImage('images/LayersBar.png')) self.draw_current_layer(painter) for table in self.layer_tables: table.draw(painter) def highlight_current_button(self, painter): painter.setBrush(QColor(255, 255, 255)) painter.setPen(Qt.transparent) button = self.buttons[self.canvas.current_tool] painter.drawRect(button.x(), button.y(), self.BUTTON_SIZE, self.BUTTON_SIZE) def get_start_end_position(self): start_x, start_y = self.shape_start end_x, end_y = self.cursor_position start_x = start_x * self.pixel_size + self.canvas_left_side + self.pixel_size / 2 start_y = start_y * self.pixel_size + self.canvas_upper_side + self.pixel_size / 2 end_x = end_x * self.pixel_size + self.canvas_left_side + self.pixel_size / 2 end_y = end_y * self.pixel_size + self.canvas_upper_side + self.pixel_size / 2 return start_x, start_y, end_x, end_y def draw_line(self, painter): start_x, start_y, end_x, end_y = self.get_start_end_position() painter.drawLine(start_x, start_y, end_x, end_y) def draw_rectangle(self, painter): start_x, start_y, end_x, end_y = self.get_start_end_position() left = min(start_x, end_x) up = min(start_y, end_y) painter.drawRect(left, up, abs(end_x - start_x), abs(end_y - start_y)) def draw_triangle(self, painter): start_x, start_y, end_x, end_y = self.get_start_end_position() left = min(start_x, end_x) right = max(start_x, end_x) up = min(start_y, end_y) down = max(start_y, end_y) width = right - left left_up = left + width // 2 right_up = left_up + (width % 2) painter.drawLine(left_up, up, left, down) painter.drawLine(right_up, up, right, down) painter.drawLine(left, down, right, down) def draw_ellipse(self, painter): start_x, start_y, end_x, end_y = self.get_start_end_position() left = min(start_x, end_x) up = min(start_y, end_y) painter.drawEllipse(left, up, abs(end_x - start_x), abs(end_y - start_y)) def update_selection_position(self): start_x = self.shape_start[0] * self.pixel_size + self.canvas_left_side start_y = self.shape_start[1] * self.pixel_size + self.canvas_upper_side end_x = self.cursor_position[0] * self.pixel_size + self.canvas_left_side end_y = self.cursor_position[1] * self.pixel_size + self.canvas_upper_side self.selection_left = min(start_x, end_x) self.selection_right = max(start_x, end_x) + self.pixel_size self.selection_up = min(start_y, end_y) self.selection_down = max(start_y, end_y) + self.pixel_size self.selection_width = abs(self.cursor_position[0] - self.shape_start[0]) + 1 self.selection_height = abs(self.cursor_position[1] - self.shape_start[1]) + 1 def draw_selection(self, painter): width = self.pixel_size / 4 black_pen = QPen(QColor(0, 0, 0)) black_pen.setWidth(3) white_pen = QPen(QColor(255, 255, 255)) white_pen.setWidth(3) painter.setPen(black_pen) for x in range(self.selection_width): painter.drawLine(self.selection_left + x * self.pixel_size, self.selection_up, self.selection_left + x * self.pixel_size + width, self.selection_up) painter.drawLine(self.selection_left + x * self.pixel_size, self.selection_down, self.selection_left + x * self.pixel_size + width, self.selection_down) painter.setPen(white_pen) painter.drawLine(self.selection_left + x * self.pixel_size + width, self.selection_up, self.selection_left + x * self.pixel_size + width * 3, self.selection_up) painter.drawLine(self.selection_left + x * self.pixel_size + width, self.selection_down, self.selection_left + x * self.pixel_size + width * 3, self.selection_down) painter.setPen(black_pen) painter.drawLine(self.selection_left + x * self.pixel_size + width * 3, self.selection_up, self.selection_left + x * self.pixel_size + width * 4, self.selection_up) painter.drawLine(self.selection_left + x * self.pixel_size + width * 3, self.selection_down, self.selection_left + x * self.pixel_size + width * 4, self.selection_down) for y in range(self.selection_height): painter.drawLine(self.selection_left, self.selection_up + y * self.pixel_size, self.selection_left, self.selection_up + y * self.pixel_size + width) painter.drawLine(self.selection_right, self.selection_up + y * self.pixel_size, self.selection_right, self.selection_up + y * self.pixel_size + width) painter.setPen(white_pen) painter.drawLine(self.selection_left, self.selection_up + y * self.pixel_size + width, self.selection_left, self.selection_up + y * self.pixel_size + width * 3) painter.drawLine(self.selection_right, self.selection_up + y * self.pixel_size + width, self.selection_right, self.selection_up + y * self.pixel_size + width * 3) painter.setPen(black_pen) painter.drawLine(self.selection_left, self.selection_up + y * self.pixel_size + width * 3, self.selection_left, self.selection_up + y * self.pixel_size + width * 4) painter.drawLine(self.selection_right, self.selection_up + y * self.pixel_size + width * 3, self.selection_right, self.selection_up + y * self.pixel_size + width * 4) def draw_pixels(self, painter): painter.drawImage(self.canvas_left_side, self.canvas_upper_side, self.canvas_as_image.scaled(self.canvas_width, self.canvas_height)) painter.setBrush(Qt.transparent) black_pen = QPen(QColor(0, 0, 0)) black_pen.setWidth(3) painter.setPen(black_pen) painter.drawRect(self.canvas_left_side, self.canvas_upper_side, self.canvas_width, self.canvas_height) painter.setPen(Qt.black) self.draw_grid(painter) def draw_grid(self, painter): if self.pixel_size > 10: for i in range(self.canvas.width + 1): x = self.canvas_left_side + i * self.pixel_size painter.drawLine(x, self.canvas_upper_side, x, self.canvas_upper_side + self.canvas_height) for i in range(self.canvas.height + 1): y = self.canvas_upper_side + i * self.pixel_size painter.drawLine(self.canvas_left_side, y, self.canvas_left_side + self.canvas_width, y) def draw_edges(self, painter): painter.setPen(Qt.transparent) painter.setBrush(QColor('#393939')) painter.drawRect(self.vertical_scrollbar.x(), self.vertical_scrollbar.y(), self.vertical_scrollbar.width(), self.vertical_scrollbar.height() + self.horizontal_scrollbar.height() + 1) painter.drawRect(self.horizontal_scrollbar.x(), self.horizontal_scrollbar.y(), self.horizontal_scrollbar.width(), self.horizontal_scrollbar.height() + 1) def draw_current_layer(self, painter): if not self.to_draw_canvas: return painter.setBrush(Qt.white) table = self.layer_tables[self.canvas.current_layer] painter.drawRect(table.x - 1, table.y - 1, LayerTable.WIDTH + 2, LayerTable.HEIGHT + 2) def draw_buttons(self, painter): painter.setPen(Qt.transparent) painter.setBrush(QColor(self.canvas.current_color.r, self.canvas.current_color.g, self.canvas.current_color.b)) for button, image in self.button_images.items(): painter.drawRect(button.x() + 3, button.y() + 3, self.BUTTON_SIZE - 6, self.BUTTON_SIZE - 6) painter.drawImage(button.x(), button.y(), image.scaled(self.BUTTON_SIZE, self.BUTTON_SIZE))
class DollWidget(QWidget): def __init__(self, usbcom=None, target='0.0.0.0', port=0, name='Uno_Doll'): super(DollWidget, self).__init__() self.name = name self.usbcom = usbcom self.target = target self.port = port self.initUI() def setName(self, name): self.name = name def setValue(self, value): self.timeline.setValue(value) self.eyebrowLine.setValue(value) self.eyeLine.setValue(value) self.earLine.setValue(value) self.mouseLine.setValue(value) def setSlider(self, value): if value > 0.8 * self.relativeMaximum: self.relativeMaximum = 1.2 * self.relativeMaximum self.slider.setValue(int(100 * value / self.relativeMaximum)) def initUI(self): self.mode = 0 self.time = 0 self.eyebrowEmotion = open('eyebrow.dqbe', 'w+') self.eyebrowEmotion.seek(0) self.eyeEmotion = open('eye.dqbe', 'w+') self.eyeEmotion.seek(0) self.earEmotion = open('ear.dqbe', 'w+') self.earEmotion.seek(0) self.mouseEmotion = open('mouse.dqbe', 'w+') self.mouseEmotion.seek(0) self.file = open('emoji.dqpe', 'a+') self.file.seek(0) '''mode 1 as play. mode 2 as record. mode 3 as stop. mode 4 as save.''' self.thisDoll = QCheckBox(self.name, self) self.eyebrow = QCheckBox('eyebrow', self) self.eye = QCheckBox('eye', self) self.ear = QCheckBox('ear', self) self.mouse = QCheckBox('mouse', self) self.playBtn = QPushButton('Play', self) self.recordBtn = QPushButton('Record', self) self.stopBtn = QPushButton('Stop', self) self.saveBtn = QPushButton('Save', self) self.timeline = TimeLine(scale=True) self.eyebrowLine = TimeLine(scale=False, emotionPool=self.eyebrowEmotion, types='eyebrow') self.eyeLine = TimeLine(scale=False, emotionPool=self.eyeEmotion, types='eye') self.earLine = TimeLine(scale=False, emotionPool=self.earEmotion, types='ear') self.mouseLine = TimeLine(scale=False, emotionPool=self.mouseEmotion, types='mouse') self.slider = QScrollBar(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(100) self.relativeMaximum = 15 self.slider.setValue(0) self.slider.valueChanged.connect(self.valueChange) self.playBtn.clicked.connect(self.handlePlayBtn) self.stopBtn.clicked.connect(self.handleStopBtn) self.recordBtn.clicked.connect(self.handleRecordBtn) self.saveBtn.clicked.connect(self.handleSaveBtn) self.thisDoll.stateChanged.connect( lambda: self.handleCheck(self.thisDoll)) dollcmd.setComPort(self.usbcom) #UI layout = QGridLayout(self) layout.addWidget(self.playBtn, 0, 0, 1, 1) layout.addWidget(self.recordBtn, 0, 1, 1, 1) layout.addWidget(self.stopBtn, 0, 2, 1, 1) layout.addWidget(self.saveBtn, 0, 3, 1, 1) layout.addWidget(self.thisDoll, 1, 0, 1, 1) layout.addWidget(self.eyebrow, 2, 1, 1, 1) layout.addWidget(self.eye, 3, 1, 1, 1) layout.addWidget(self.ear, 4, 1, 1, 1) layout.addWidget(self.mouse, 5, 1, 1, 1) scroll = QScrollArea() scroll.setWidgetResizable(True) self.scrollContent = QWidget(scroll) scrollLayout = QVBoxLayout(self.scrollContent) self.scrollContent.setLayout(scrollLayout) scrollLayout.addWidget(self.timeline) scrollLayout.addWidget(self.eyebrowLine) scrollLayout.addWidget(self.eyeLine) scrollLayout.addWidget(self.earLine) scrollLayout.addWidget(self.mouseLine) scroll.setWidget(self.scrollContent) layout.addWidget(self.slider, 0, 4, 1, 7) layout.addWidget(self.scrollContent, 1, 4, 5, 7) self.show() def valueChange(self): s = self.slider.value() value = (s * self.relativeMaximum * 0.01) self.setValue(value) if self.mode != 1 and self.mode != 2 and self.mode != 4: self.time = value * 20 def handleCheck(self, this): if this.isChecked(): state = Qt.Checked else: state = Qt.Unchecked self.eye.setCheckState(state) self.eyebrow.setCheckState(state) self.ear.setCheckState(state) self.mouse.setCheckState(state) def handlePlayBtn(self): self.mode = 1 self.handleIO() def handleStopBtn(self): self.mode = 3 def handleRecordBtn(self): self.mode = 2 self.handleIO() def handleSaveBtn(self): self.mode = 4 self.handleIO() ''' eyebrow and eye jd1[0] 1023 = left, 0 = right jd1[1] 1023 = up. , 0 = down ear 1023. = up, 0 = down ''' def handleIO(self): if self.mode == 1: data = self.file.readline() #dollcmd.sendUDP() self.time += 1 self.setValue(self.time * 0.05) self.setSlider(self.time * 0.05) QTimer.singleShot(50, self.handleIO) if self.mode == 2: data = dollcmd.handleIOData() self.file.write(data) #dollcmd.sendUDP(data) if '\n' in data: self.eyebrowEmotion.seek(self.time * 12) self.eyeEmotion.seek(self.time * 12) self.earEmotion.seek(self.time * 12) self.mouseEmotion.seek(self.time * 12) lists = data.replace('\n', '').split(',') #ear if int(lists[0]) > 512: i = 0 else: i = 1 i *= 3 if int(lists[1]) > 512: i += 0 else: i += 1 self.earEmotion.write('{}@{}\n'.format( str(self.time).zfill(8), str(i))) #ear #eyebrow if int(lists[2]) > 682: i = 0 elif int(lists[2]) > 341: i = 1 else: i = 2 i *= 3 if int(lists[3]) > 682: i += 0 elif int(lists[3]) > 341: i += 1 else: i += 2 self.eyebrowEmotion.write('{}@{}\n'.format( str(self.time).zfill(8), str(i))) #eyebrow #eye if int(lists[6]) > 682: i = 0 elif int(lists[6]) > 341: i = 1 else: i = 2 i *= 3 if int(lists[7]) > 682: i += 0 elif int(lists[7]) > 341: i += 1 else: i += 2 self.eyeEmotion.write('{}@{}\n'.format( str(self.time).zfill(8), str(i))) #eye #mouse if int(lists[10]) > 682: i = 0 elif int(lists[10]) > 341: i = 1 else: i = 2 i *= 3 if int(lists[11]) > 682: i += 0 elif int(lists[11]) > 341: i += 1 else: i += 2 self.mouseEmotion.write('{}@{}\n'.format( str(self.time).zfill(8), str(i))) #mouse self.time += 1 self.setValue(self.time * 0.05) self.setSlider(self.time * 0.05) QTimer.singleShot(50, self.handleIO) if self.mode == 3: pass if self.mode == 4: pass def mousePressEvent(self, event): pass def mouseMoveEvent(self, event): pass
class dicomImage2DdisplayWidget(QWidget): addSeedsSignal = pyqtSignal(bool) def __init__(self, **kwargs): super(dicomImage2DdisplayWidget, self).__init__() self._face = kwargs.get('face', 0) self._datas = kwargs.get('datas', 0) self._Spacing = kwargs.get('spacing', None) self._low_hu = kwargs.get("low_hu", -1150) self._high_hu = kwargs.get("high_hu", 3250) self._axis = 0 #===============Seeds information============================ self.seedsColors = [] self.baseImageSize = 512 self.regionDrawMod = 0 self.drawLayer = [] #===============Regioin draw tool parmeter=================== self.drawPanterbegin = QPoint() self.drawPanterEnd = QPoint() self.posX = 0 self.posY = 0 #===============Init UI====================================== self.initUI() def initUI(self): self.setGeometry(0, 0, self.baseImageSize, self.baseImageSize) self.viewLayout = None self.imLable = QLabel(self) self.imLable.setScaledContents(True) self.imData = None self.topLable = QLabel(self) self.downLable = QLabel(self) self.imLable.resize(self.width(), self.height()) self.initDicomParameter() pass def initDicomParameter(self): #============================SetDataParameter=========================== self._color_table = [qRgb(i, i, i) for i in range(64)] self.datas = self._datas.copy() self.faceWindowV = self.faceWindowH = max(self.datas.shape) #============================ChangeFaceSize============================= self.xSpacing, self.ySpacing, self.zSpacing = self._Spacing #============================OperationMod=============================== self.OperationMod = 0 self.facePlane = ['mainFaceplane', 'leftFaceplane', 'frontFaceplane'] self.idxSlice = 100 self.currentFace = self.facePlane[self._face] #============================RegionGrowingParameter===================== self.PosXY = [150, 75] # self.seedList = [(self.PosXY[0], self.PosXY[1])] self.seedList = [] self.seedSelectNum = 0 self.LowAndUpper = [10, 3000] self.regionArea = [] self.regionDrawSize = 5 self.idxSlicelimt = self.datas.shape[0] # print(self.datas.shape[0]) #======================================================================= self.initOperationButton() self.initDisplayfacePlane() self.choiceOpreationMod() pass def initOperationButton(self): self.facePlanes = QComboBox(self) self.facePlanes.addItem(self.facePlane[0]) self.facePlanes.addItem(self.facePlane[1]) self.facePlanes.addItem(self.facePlane[2]) self.facePlanes.setCurrentIndex(self._face) # self.facePlanes.activated[str].connect(self.faceItem_Choice) self.facePlanes.currentTextChanged.connect(self.faceItem_Choice) self.facePlanes.keyPressEvent = self.customComboxKeyEvent self.facePlanes.move((self.width() - self.facePlanes.width()), 0) #==================================Active keyBoard event without combobox======================= # shorcut = QShortcut(QKeySequence(Qt.Key_F), self.facePlanes, activated=self.useforTestKeyEvent) #=============================================================================================== #================================== Contrul region seed up and low range ======================= regionWide = QRangeSlider(self) regionWide.setMax(255) regionWide.setMin(0) regionWide.setStart(150) regionWide.setEnd(255) regionWide.setRange(0, 255) regionWide.setDrawValues(True) regionWide.setBackgroundStyle('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #222, stop:1 #333);') regionWide.handle.setStyleSheet('background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #8EE5EE, stop:1 #393);') regionWide.startValueChanged.connect(self.rangeSliderStartVolue) regionWide.endValueChanged.connect(self.rangeSliderEndVolue) #=============================================================================================== self.modCombox = QComboBox(self) self.modCombox.addItem('Normal') self.modCombox.addItem('Region') self.modCombox.setCurrentIndex(self.OperationMod) # self.modCombox.activated[str].connect(self.mod_Choice) self.modCombox.currentTextChanged.connect(self.mod_Choice) self.modCombox.keyPressEvent = self.customComboxKeyEvent self.modCombox.move((self.width() - self.facePlanes.width() - self.modCombox.width()), 0) self.layerScrollBar = QScrollBar(Qt.Horizontal, self) self.layerScrollBar.setGeometry(0, 0, 128, 5) self.layerScrollBar.setMinimum(0) self.layerScrollBar.setMaximum(min(self.datas.shape)) self.layerScrollBar.setValue(0) self.layerScrollBar.sliderMoved.connect(self.selectLayer) self.BaseBoxLayout = QBoxLayout(QBoxLayout.TopToBottom) self.BaseBoxLayout.addWidget(self.layerScrollBar, 0) self.BaseBoxLayout.addWidget(regionWide, 1) self.BaseBoxLayout.setAlignment(Qt.AlignTop) self.secondBoxLayout = QBoxLayout(QBoxLayout.LeftToRight) self.secondBoxLayout.addLayout(self.BaseBoxLayout) self.secondBoxLayout.addWidget(self.modCombox) self.secondBoxLayout.addWidget(self.facePlanes) self.secondBoxLayout.setAlignment(Qt.AlignTop) self.groupbox = QGroupBox(self) self.groupbox.setGeometry(28, -64, 512, 64) self.groupbox.setLayout(self.secondBoxLayout) self.showButton = QPushButton(self) self.showButton.setGeometry(0, 0, 16, 16) self.showButton.clicked.connect(self.playAnimation) self.initAnimation() pass def setGroup_pos(self, apos): self.groupbox.move(apos.x(), apos.y()) pass def setSeedsColor(self, lists): # self.seedList.clear() # self.seedsColors.clear() # for i in range(0, len(colorList)): # self.seedsColors.append(colorList[i][0]) # self.seedList.append(colorList[i][1]) self.seedsColors.append(lists[0]) self.seedList.append(lists[1]) print('seedList:', self.seedList) pass def selectSeedinList(self, num): # tmpS = self.seedList[num] # tmpC = self.seedsColors[num] self.seedSelectNum = num # print(self.seedsColors) # print(self.seedList) # print('number is :', num) # print(tmpC, tmpS) pass def removeSeedinList(self, num): self.seedList.remove(self.seedList[num]) self.choiceDisplayMod() pass def rangeSliderStartVolue(self, event): self.LowAndUpper[0] = event self.choiceDisplayMod() pass def rangeSliderEndVolue(self, event): self.LowAndUpper[1] = event self.choiceDisplayMod() pass def viewSeedinList(self, event): if event[0] == True: print('Open eye is:', event[1]) elif event[0] == False: print('Close eye is:', event[1]) else: print('viewSeedinList error.....') pass def initAnimation(self): self.isBoardshow = False xAxis = self.groupbox.pos().x() yAxis = self.groupbox.height() self.groupBoxAnim = QPropertyAnimation(self, b'pos') self.groupBoxAnim.setDuration(200) self.groupBoxAnim.setStartValue(QPointF(xAxis, -yAxis)) # self.anim.setKeyValueAt(0.5, QPointF(0, 10)) # self.anim.setKeyValueAt(0.8, QPointF(0, 80)) self.groupBoxAnim.setEndValue(QPointF(xAxis, 0)) self.reverGroupBoxAnim = QPropertyAnimation(self, b'pos') self.reverGroupBoxAnim.setDuration(200) self.reverGroupBoxAnim.setStartValue(QPointF(xAxis, 0)) self.reverGroupBoxAnim.setEndValue(QPointF(xAxis, -yAxis)) pass def playAnimation(self): print('-----PlayAnimation-----') if self.isBoardshow == False: self.reverGroupBoxAnim.stop() self.groupBoxAnim.start() self.isBoardshow = True elif self.isBoardshow == True: self.groupBoxAnim.stop() self.reverGroupBoxAnim.start() self.isBoardshow = False pass pos = pyqtProperty(QPointF, fset=setGroup_pos) def selectLayer(self, event): self.idxSlice = self.layerScrollBar.value() self.choiceDisplayMod() pass def sliderval(self): self._low_hu = self.lowHusBar.value() self._high_hu = self.heighHusBar.value() self.choiceDisplayMod() pass def mod_Choice(self, event): if event == 'Normal': self.OperationMod = 0 elif event == 'Region': self.OperationMod = 1 self.choiceOpreationMod() pass def initDisplayfacePlane(self): if self._face == 0: self.topfaceView() elif self._face == 1: self.leftfaceView() elif self._face == 2: self.frontfaceView() pass def faceItem_Choice(self, faceEvent): if faceEvent == self.facePlane[0]: self.topfaceView() self.currentFace = self.facePlane[0] print('main view') elif faceEvent == self.facePlane[1]: self.leftfaceView() self.currentFace = self.facePlane[1] print('left view') elif faceEvent == self.facePlane[2]: self.frontfaceView() self.currentFace = self.facePlane[2] print('front view') self.choiceOpreationMod() self.getResizeEvent(self.width(), self.height()) pass #==========================MakeSureDisplayMod============================= def choiceDisplayMod(self): if self.OperationMod == 0: self.drawNomralArea() elif self.OperationMod == 1: self.drawGrowingArea() pass #========================================================================= def choiceOpreationMod(self): if self.OperationMod == 0: self.imLable.mouseMoveEvent = self.normalModMouseMoveEvent elif self.OperationMod == 1: self.imLable.mouseMoveEvent = self.regionModMouseMoveEvent self.imLable.mousePressEvent = self.regionModMousePressEvent self.imLable.mouseReleaseEvent = self.regionModMouseReleasedEvent self.imLable.wheelEvent = self.regionGrowingWheelEvent self.choiceDisplayMod() pass def topfaceView(self): self.datas = self._datas.copy() self.idxSlicelimt = self.datas.shape[0] self.faceWindowH = self.faceWindowV = self.width() tmpPalete = QPalette() tmpPalete.setColor(QPalette.Background, QColor(0, 0, 0)) self.setPalette(tmpPalete) #=======================Init drawLayer=================== self.drawLayer = np.full(self.datas.shape, 0) print('topfaceView:', self.drawLayer.shape) pass def leftfaceView(self): self.datas = self._datas.copy() self.datas = np.rot90(self.datas, -1) self.datas = np.rot90(self.datas, axes=(0, 2)) self.idxSlicelimt = self.datas.shape[0] self.setScaleSize(max(self.datas.shape), min(self.datas.shape)) tmpPalete = QPalette() tmpPalete.setColor(QPalette.Background, QColor(0, 0, 0)) self.setPalette(tmpPalete) #=======================Init drawLayer=================== self.drawLayer = np.full(self.datas.shape, 0) print('leftfaceView:', self.drawLayer.shape) pass def frontfaceView(self): self.datas = self._datas.copy() self.datas = np.rot90(self.datas, -1) self.idxSlicelimt = self.datas.shape[0] width = self.datas.shape[0] height = self.datas.shape[1] depth = self.datas.shape[2] self.setScaleSize(max(width, height, depth), min(width, height, depth)) tmpPalete = QPalette() tmpPalete.setColor(QPalette.Background, QColor(0, 0, 0)) self.setPalette(tmpPalete) #=======================Init drawLayer=================== self.drawLayer = np.full(self.datas.shape, 0) print('frontfaceView:', self.drawLayer.shape) pass def drawNomralArea(self): self.idxSlice = np.clip(self.idxSlice, 0, self.idxSlicelimt -1) self.imData = self.datas[self.idxSlice] self.displayDicomImage() pass def drawGrowingArea(self): self.imgOriginal = SimpleITK.GetImageFromArray(self.datas[self.idxSlice]) self.imgWhiteMatter = SimpleITK.ConnectedThreshold(image1=self.imgOriginal, seedList=self.seedList, lower=self.LowAndUpper[0], upper=self.LowAndUpper[1], replaceValue=1, ) self.regionArea = SimpleITK.GetArrayFromImage(self.imgWhiteMatter) #================if use draw or eraser==================== if np.sum(self.drawLayer[self.idxSlice] != 0) != 0: self.regionDrawLayerCombinEvent() self.drawGrowingAreaContour() pass def drawGrowingAreaContour(self): foreColorvalue = 1 self.imgWhiteMatter = SimpleITK.GetImageFromArray(self.regionArea) self.imgWhiteMatterNoHoles = SimpleITK.VotingBinaryHoleFilling(image1=self.imgWhiteMatter, radius=[2] * 3, majorityThreshold=50, backgroundValue=0, foregroundValue=foreColorvalue) regionContour = SimpleITK.LabelContour(self.imgWhiteMatterNoHoles) # tmpWmatter = self.imgWhiteMatter # regionContour = tmpWmatter | regionContour tmpImage = SimpleITK.LabelOverlay(self.imgOriginal, regionContour) regionContourArray = SimpleITK.GetArrayFromImage(tmpImage) self.imData = regionContourArray self.displayDicomImage() pass #==============================Key board event ============================================ def customComboxKeyEvent(self, event): print('ComboxKeyEvent') pass def useforTestKeyEvent(self): print('just test combobox key event') # self.displayDicomImage() pass #==============================Use for display dicom image================================= def displayDicomImage(self): if self.imData is not None: raw_data = self.imData shape = self.imData.shape # maxNum = max(shape) # minNum = min(shape) raw_data[raw_data < 0] = 0 raw_data[raw_data > 255] = 255 if len(shape) >= 3: data = raw_data #=================用于调节对比度的方法======================= # data = (raw_data - self._low_hu) / self.window_width * 256 # print('---------Update3d--------') #=========================================================== data = data.astype(np.int8) tmpImage = QImage(data, shape[1], shape[0], shape[1] * shape[2], QImage.Format_RGB888) pixmap = QPixmap.fromImage(tmpImage) # pixmap = pixmap.scaled(self.faceWindowH , self.faceWindowV ) # pixmap = pixmap.scaled(self.xSpacing, self.zSpacing) # pixmap = pixmap.scaled(1024, 128) self.imLable.setPixmap(pixmap) elif len(shape) < 3: data = raw_data # data = (raw_data - self._low_hu) / self.window_width * 256 # print('---------Update2d---------') data = data.astype(np.int8) tmpImage = QImage(data, shape[1], shape[0], QImage.Format_Grayscale8) tmpImage.setColorTable(self._color_table) pixmap = QPixmap.fromImage(tmpImage) # pixmap = pixmap.scaled(self.faceWindowH, self.faceWindowV) # pixmap = pixmap.scaled(self.xSpacing, self.zSpacing) # pixmap = pixmap.scaled(1024, 128) self.imLable.setPixmap(pixmap) pass def normalModMouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton: xAxis = event.pos().x() yAxis = event.pos().y() self.choiceDisplayMod() pass #=============================Region draw layer operation========================================== def regionDrawLayerEvent(self, x, y, value): self.regionArea[y - self.regionDrawSize:y + self.regionDrawSize, x - self.regionDrawSize:x + self.regionDrawSize] = value self.drawLayer[self.idxSlice] = self.regionArea pass def regionDrawLayerCombinEvent(self): self.regionArea = self.drawLayer[self.idxSlice].astype(np.uint8) pass #=============================Region mod mouse Press and released event============================ def regionModMousePressEvent(self, event): if event.buttons() == Qt.LeftButton and self.regionDrawMod != 0: xAxis = event.pos().x() yAxis = event.pos().y() if xAxis >= 0 and yAxis >= 0: tmpX = math.floor(xAxis * (self.baseImageSize / self.imLable.width())) tmpY = math.floor(yAxis * (self.baseImageSize / self.imLable.height())) if self.regionDrawMod == 1: self.regionDrawLayerEvent(tmpX, tmpY, 1) elif self.regionDrawMod == 2: self.regionDrawLayerEvent(tmpX, tmpY, 0) self.drawGrowingAreaContour() pass def regionModMouseReleasedEvent(self, Event): if Event.buttons() == Qt.RightButton: print('Right button released') pass #================================================================================================== #=====================================Region mod mouse move event================================== def regionModMouseMoveEvent(self, event): self.posX = event.pos().x() self.posY = event.pos().y() if event.buttons() == Qt.LeftButton and self.regionDrawMod == 0: if self.regionDrawMod == 0: xAxis = event.pos().x() yAxis = event.pos().y() if xAxis >= 0 and yAxis >= 0: self.PosXY[0] = math.floor(xAxis * (self.baseImageSize / self.imLable.width())) self.PosXY[1] = math.floor(yAxis * (self.baseImageSize / self.imLable.height())) self.seedList[self.seedSelectNum] = (self.PosXY[0], self.PosXY[1]) else: print('Region Mod has Nagtive number') elif event.buttons() == Qt.LeftButton and self.regionDrawMod != 0: xAxis = event.pos().x() yAxis = event.pos().y() if xAxis >= 0 and yAxis >= 0: tmpX = math.floor(xAxis * (self.baseImageSize / self.imLable.width())) tmpY = math.floor(yAxis * (self.baseImageSize / self.imLable.height())) if self.regionDrawMod == 1: self.regionDrawLayerEvent(tmpX, tmpY, 1) elif self.regionDrawMod == 2: self.regionDrawLayerEvent(tmpX, tmpY, 0) else: print('regionModMouseMoveEvent regionDrawMod error......') return self.drawGrowingAreaContour() return else: print('regionModMouseMoveEvent error......') self.choiceDisplayMod() pass #=================================SetWindowSizeEvent========================================== def setScaleSize(self, maxnum, minnum): self.faceWindowH = maxnum self.faceWindowV = minnum * (max(self.xSpacing, self.ySpacing, self.zSpacing) / min(self.xSpacing, self.ySpacing, self.zSpacing)) pass def getResizeEvent(self, sizeX, sizeY): if self.currentFace == self.facePlane[0]: tmpSize = min(sizeX, sizeY) self.imLable.resize(tmpSize, tmpSize) elif self.currentFace == self.facePlane[1]: #==================Resize Lable=================== self.setScaleSize(min(sizeX, sizeY), min(sizeX, sizeY) * (min(self.datas.shape)/max(self.datas.shape))) self.imLable.resize(self.faceWindowH, self.faceWindowV) elif self.currentFace == self.facePlane[2]: self.setScaleSize(min(sizeX, sizeY), min(sizeX, sizeY) * (min(self.datas.shape) / max(self.datas.shape))) self.imLable.resize(self.faceWindowH, self.faceWindowV) #==================Move Lable===================== maxPosY = max(sizeY, self.imLable.height()) minPoxY = min(sizeY, self.imLable.height()) tmpPosX = np.clip((sizeX - sizeY), 0, max(sizeX, sizeY)) / 2 tmpPosY = (maxPosY - minPoxY) / 2 self.imLable.move(tmpPosX, tmpPosY) pass #===========================mousewheelEvent================================== def regionGrowingWheelEvent(self, event): angle = event.angleDelta() / 8 angleX = angle.x() angleY = angle.y() if angleY > 0: self.regionDrawSize -= 1 elif angleY < 0: self.regionDrawSize += 1 pass #==========================RegionDrawMod===================== def setRegionDrawMod(self, event): if event == 0: self.regionDrawMod = 0 elif event == 1: self.regionDrawMod = 1 elif event == 2: self.regionDrawMod = 2 else: print('setRegionDrawMod error....') pass #====================Use for paint or eraser==================== def paintEvent(self, QPaintEvent): pen1 = QPen(Qt.blue, 1) q = QPainter(self) q.setPen(pen1) q.drawRect(self.posX - 25, self.posY - 25, 50, 50) # print('paintEvent') pass @property def window_width(self): return self._high_hu - self._low_hu #======================================================================================================================= # pathDicom = "D:/Dicomfile/MT_07/" # idxSlice = 50 # reader = SimpleITK.ImageSeriesReader() # filenamesDICOM = reader.GetGDCMSeriesFileNames(pathDicom) # # reader.SetFileNames(filenamesDICOM) # imgOriginals = reader.Execute() # datas = SimpleITK.GetArrayFromImage(imgOriginals) # Spacing = imgOriginals.GetSpacing() # # if __name__ == '__main__': # app = QApplication(sys.argv) # win = dicomImage2DdisplayWidget(face=0, datas= datas, spacing=Spacing) # win.show() # sys.exit(app.exec_())
class MainUi(QMainWindow): obj_num = 0 container = {} def __init__(self, info): super(MainUi, self).__init__() self.icon = [ico for ico in info] self.column = len(self.icon) self.num = 10 # 界面头部展示模块数量 self.init_ui() def init_ui(self): self.setWindowIcon(QIcon('index.ico')) self.setWindowTitle("工具") self.resize(960, 600) self.statusBar().show() self._center() self.main_widget = QWidget() # 创建窗口主部件 self.main_layout = QGridLayout() # 创建主部件的网格布局 self.main_widget.setLayout(self.main_layout) # 设置窗口主部件布局为网格布局 # 创建上侧部件 self.up_widget = QWidget() self.up_widget.setObjectName('up_widget') self.up_widget.setFixedHeight(80) self.up_layout = QGridLayout() self.up_widget.setLayout(self.up_layout) # 创建滚动条 self.slide = QScrollBar(True) self.slide.setObjectName('slide_roll_bar') self.slide.setFixedHeight(const.SLIDE_HEIGHT) self.slide.setMaximum(self.column) self.slide.setMinimum(self.num) self.slide.valueChanged.connect(self._value_change) # 创建日志记录 # ************************************************## name = "Analysis" self.notice_btn = QPushButton(name) self.notice_btn.setObjectName(name) self.container["selectedNoticeName"] = name self.notice_btn.setFixedSize(const.NOTICE_WIDTH, const.BTN_HEIGHT) self.notice_btn.clicked.connect(self._clicked) self.notice_close_btn = QPushButton("✘") self.notice_close_btn.setObjectName("close_btn") self.notice_close_btn.setFixedSize(30, 30) self.notice_close_btn.setStyleSheet( """#close_btn{ background:red; border:none; margin-bottom: 20px; margin-left: 20px; } #close_btn:hover{ background:white; } """ ) self.notice_btn.setStyleSheet(""" #Analysis:hover#close_btn { background:red; } """) self.close_layout = QGridLayout() self.close_layout.addWidget(self.notice_close_btn) self.close_layout.setAlignment(Qt.AlignAbsolute|Qt.AlignRight) self.close_layout.setSpacing(0) self.notice_btn.setLayout(self.close_layout) # self.notice_btn.set(self.notice_close_btn) # ************************************************## # 创建中侧部件 self.mid_widget = QWidget() self.mid_widget.setObjectName('mid_widget') # self.mid_widget.setFixedHeight(400) self.mid_layout = QGridLayout() self.mid_widget.setLayout(self.mid_layout) # 创建下侧部件 self.down_widget = QWidget() self.down_widget.setObjectName('down_widget') self.down_widget.setFixedHeight(60) self.down_layout = QGridLayout() self.down_widget.setLayout(self.down_layout) self.main_layout.addWidget(self.up_widget, 0, 0, 1, self.column) self.main_layout.addWidget(self.slide, 1, 0, 1, self.column) self.main_layout.addWidget(self.notice_btn, 2, 0, 1, 1) self.main_layout.addWidget(self.mid_widget, 3, 1, 1, self.column - 1) self.main_layout.addWidget(self.down_widget, 4, self.column - 1, 1, 1) self.setCentralWidget(self.main_widget) # 生成analysis analysis = Analysis(self, name) self.container[name] = {"noticeName": name, "modelObj": analysis, "index": self.obj_num} self.container["selectedModelName"] = name # 创建头部(head) self.head_widget = QWidget() self.head_layout = QGridLayout() self.head_widget.setLayout(self.head_layout) self.load_model_ico(0, self.num) if self.num < self.column else self.load_model_ico(0, self.column) self.up_layout.addWidget(self.head_widget, 0, 0, 0, 0) # 创建中部 # 创建尾部 按钮 self.tail_btn = QPushButton("Execute") self.tail_btn.setObjectName('execute') self.tail_btn.setFixedSize(const.TAIL_HEIGHT, const.BTN_HEIGHT) self.tail_btn.clicked.connect(self.run) self.down_layout.addWidget(self.tail_btn, 0, 0, 0, 0) self.down_layout.setAlignment(Qt.AlignRight) # 展示进度条 self.progressBar = QProgressBar() self.progressBar.setFixedHeight(10) self.progressBar.setMaximum(const.HUNDRED) label = QLabel() label.setText("运行进度:") self.statusBar().addPermanentWidget(label) self.statusBar().addPermanentWidget(self.progressBar) self.main_layout.setSpacing(const.ZERO) set_style(self) # self.setWindowFlag(Qt.FramelessWindowHint) # 隐藏边框 # self.setWindowOpacity(0.9) # 设置窗口透明度 # self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明 def run(self): mode_name = self.container.get("selectedModelName", "") mode_info = self.container.get(mode_name, {}) mode = mode_info.get("modelObj") if not mode: print("error %s" % mode) return try: mode.run() except: self.set_progress() traceback.print_exc() def set_progress(self): self.tail_btn.setEnabled(True) def load_model_ico(self, start, end): for i in range(start, end): self.tool_btn = QToolButton() self.tool_btn.setText(f"{self.icon[i]}") # 设置按钮文本 self.tool_btn.setObjectName(f"{self.icon[i]}") # 设置按钮文本 self.tool_btn.setFixedSize(85, 52) # self.tool_btn.setFixedHeight(85) self.tool_btn.setIcon(qtawesome.icon(f'fa.{self.icon[i]}', color='white')) # 设置按钮图标 self.tool_btn.setIconSize(QSize(const.ICO_SIZE, const.ICO_SIZE)) # 设置图标大小 self.tool_btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.tool_btn.clicked.connect(self._clicked) self.head_layout.addWidget(self.tool_btn, 0, i, 1, 1) def info_btn(self, name): notice_btn = QPushButton(name) notice_btn.setObjectName(f"{name}_{self.obj_num}") notice_btn.setFixedSize(const.NOTICE_WIDTH, const.BTN_HEIGHT) self.container[name]["noticeName"] = f"{name}_{self.obj_num}" notice_btn.clicked.connect(self._clicked) self.main_layout.addWidget(notice_btn, 2, self.obj_num, 1, 1) def _clicked(self): model_name = self.sender().text() if model_name == self.container.get("selectedModelName"): self.show_widget(model_name) return # message.info() self.statusBar().showMessage(f'Current Value is {model_name}') model_info = self.container.get(model_name, {}) if not model_info: mode = None try: mode = ObjFactory.create(self, model_name) except: traceback.print_exc() # return # message.info() if mode is None: set_mid_widget_background_style(self.mid_widget, False) self.show_widget(model_name) print("failed") return # message.info() model_info["modelObj"] = mode self.obj_num += 1 model_info["index"] = self.obj_num self.container[model_name] = model_info self.info_btn(model_name) self.show_widget(model_name) self.show() @staticmethod def del_layout(layout): for i in range(layout.count()): layout.itemAt(i).widget().deleteLater() def show_widget(self, curr_mode_name): previous_name = self.container.get("selectedModelName") if previous_name is not None: index = self.container.get(previous_name).get("index") if index is not None: self.mid_layout.itemAt(index).widget().close() index = self.container.get(curr_mode_name, {}).get("index") if index is None: set_ico_style(self.head_widget, curr_mode_name) self.show_notice_widget(curr_mode_name) return self.mid_layout.itemAt(index).widget().show() self.show_notice_widget(curr_mode_name) set_mid_widget_background_style(self.mid_widget) set_ico_style(self.head_widget, curr_mode_name) self.container["selectedModelName"] = curr_mode_name print(f"当前Container:{self.container}") print(f"当前选中模块:{curr_mode_name}") def show_notice_widget(self, model_name): curr_notice_name = self.container.get(model_name, {}).get("noticeName", "failed-model") args = [] for key, item in self.container.items(): if not isinstance(item, dict): continue elif key == model_name: continue else: args.append(item.get("noticeName")) args.append(curr_notice_name) set_notice_style(self.main_widget, tuple(args)) self.container["selectedNoticeName"] = curr_notice_name def _value_change(self): value = self.slide.value() start = value - self.num self.statusBar().showMessage(f'Current Value is {value}') self.del_layout(self.head_layout) self.load_model_ico(start, value) def paintEvent(self, event): # 设置背景颜色 painter = QPainter(self) background_color = QColor() background_color.setNamedColor('#006CAB') painter.setBrush(background_color) painter.drawRect(self.rect()) def _center(self): # 窗口居中 screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
class MainUi(QMainWindow): def __init__(self): super(MainUi, self).__init__() self.icon = [ 'forward', 'sellsy', 'film', 'home', 'download', 'heart', 'comment', 'star', 'question', 'music', 'pause', 'backward' ] self.column = len(self.icon) self.num = 10 # 界面头部展示模块数量 self.row = 5 self.init_ui() def init_ui(self): self.setWindowIcon(QIcon('./img/index.ico')) self.setWindowTitle("工具") # self.setFixedSize(960, 700) self.resize(960, 700) # self._center() self.main_widget = QWidget() # 创建窗口主部件 self.main_layout = QGridLayout() # 创建主部件的网格布局 self.main_widget.setLayout(self.main_layout) # 设置窗口主部件布局为网格布局 # 创建上侧部件 self.up_widget = QWidget() self.up_widget.setObjectName('up_widget') self.up_widget.setFixedHeight(80) self.up_layout = QGridLayout() self.up_widget.setLayout(self.up_layout) # 创建滚动条 self.slide = QScrollBar(True) self.slide.setObjectName('slide_roll_bar') self.slide.setMaximum(self.column) self.slide.setMinimum(self.num) self.slide.valueChanged.connect(self._value_change) # 创建中侧部件 self.mid_widget = QWidget() self.mid_widget.setObjectName('mid_widget') self.mid_layout = QGridLayout() self.mid_widget.setLayout(self.mid_layout) # 创建下侧部件 self.down_widget = QWidget() self.down_widget.setObjectName('down_widget') self.down_layout = QGridLayout() self.down_widget.setLayout(self.down_layout) self.main_layout.addWidget(self.up_widget, 0, 0, 1, self.column) self.main_layout.addWidget(self.slide, 1, 0, 1, self.column) self.main_layout.addWidget(self.mid_widget, 2, 2, 1, self.column - 2) self.main_layout.addWidget(self.down_widget, 3, self.column - 1, self.row, 1) self.setCentralWidget(self.main_widget) # 创建头部(head) self.head_widget = QWidget() self.head_layout = QGridLayout() self.head_widget.setLayout(self.head_layout) self.load_model_ico( 0, self.num) if self.num < self.column else self.load_model_ico( 0, self.column) self.up_layout.addWidget(self.head_widget, 0, 0, 0, 0) # 创建中部(middle) self.middle_widget = QWidget() self.middle_layout = QGridLayout() self.middle_widget.setLayout(self.middle_layout) for i in range(self.row): self.middle_icon = QLabel(chr(0xf002) + f'目录_{i}:') self.middle_icon.setFont(qtawesome.font('fa', 12)) self.middle_input = QLineEdit() # self.middle_input.setPlaceholderText("请选择文件...") self.middle_input.setObjectName(f'middle_input_{i}') self.middle_btn = QPushButton( qtawesome.icon('fa.film', color='green'), "选择文件") self.middle_btn.setObjectName(f'middle_btn_{i}') self.middle_btn.clicked.connect(self.open_dir) self.middle_layout.addWidget(self.middle_icon, i, 0, 1, 1) self.middle_layout.addWidget(self.middle_input, i, 1, 1, self.row - 1) self.middle_layout.addWidget(self.middle_btn, i, self.row, 1, 1) self.mid_layout.addWidget(self.middle_widget, 0, 0, 1, 1) # 创建尾部 self.tail_widget = QWidget() self.tail_layout = QGridLayout() self.tail_widget.setLayout(self.tail_layout) self.tail_btn = QPushButton( qtawesome.icon('fa.download', color='green'), "运行") self.tail_layout.addWidget(self.tail_btn, 0, 9, 1, 1) self.down_layout.addWidget(self.tail_widget, 0, 0, 0, 0) self.set_style() self.main_layout.setSpacing(0) # self.setWindowFlag(Qt.FramelessWindowHint) # 隐藏边框 # self.setWindowOpacity(0.9) # 设置窗口透明度 # self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明 def open_dir(self): response = QFileDialog.getOpenFileName() if isinstance(response, tuple): file_path = response[0] if not os.path.exists(file_path): return self.middle_widget.sender().previousInFocusChain().setText( file_path) def _value_change(self): value = self.slide.value() start = value - self.num self.statusBar().showMessage(f'Current Value is {value}') for i in range(self.head_layout.count()): self.head_layout.itemAt(i).widget().deleteLater() self.load_model_ico(start, value) def load_model_ico(self, start, end): for i in range(start, end): self.tool_btn = QToolButton() self.tool_btn.setText(f"{self.icon[i]}") # 设置按钮文本 self.tool_btn.setObjectName(f"{self.icon[i]}") # 设置按钮文本 self.tool_btn.setFixedSize(80, 50) self.tool_btn.setIcon( qtawesome.icon(f'fa.{self.icon[i]}', color='white')) # 设置按钮图标 self.tool_btn.setIconSize(QSize(30, 30)) # 设置图标大小 self.tool_btn.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.tool_btn.clicked.connect(self._clicked) self.head_layout.addWidget(self.tool_btn, 0, i) def _clicked(self): text = self.sender().text() self.statusBar().showMessage(f'Current Value is {text}') self.change_style(text) def change_style(self, text): self.head_widget.setStyleSheet(""" QToolButton{border:none;} QToolButton:hover{border-bottom:2px solid #F76677;} #%s{border:2px dotted black;} """ % text) def set_style(self): self.up_widget.setStyleSheet(""" #up_widget{background:gray;} """) self.mid_widget.setStyleSheet(""" #mid_widget{ background:white; border-top-left-radius: 5px; border-bottom-left-radius: 5px; } """) self.down_widget.setStyleSheet(""" #down_widget{background:darkGray;} """) self.head_widget.setStyleSheet(""" QToolButton{ border:none; } QToolButton:hover{border-bottom:2px solid #F76677;} """) self.middle_widget.setStyleSheet(""" QLineEdit{ border:1px solid gray; /*border-radius:10px;*/ padding:5px 2px; } QPushButton{ border:none; border-right:1px gray; border-radius:10px; width:40%; padding:5px 2px; } QPushButton:hover{ color:red;font-weight: bold; } QLabel{ padding:0 0 0 100%; } """) self.tail_widget.setStyleSheet(""" QPushButton{ border:none; border-right:1px gray; border-radius:10px; padding:5px 2px; } QPushButton:hover{ color:red;font-weight: bold; } """) def paintEvent(self, event): # 设置背景颜色 painter = QPainter(self) background_color = QColor() background_color.setNamedColor('darkGray') painter.setBrush(background_color) painter.drawRect(self.rect())
class BitsWidget(QWidget): def __init__(self, offset, bit_size, row_width, grid_width, grid_height, bit_border_threshold) -> None: super().__init__() self._app = App() self._offset = offset self._bit_size = bit_size self._row_width = row_width self._grid_width = grid_width self._grid_h_offset = 0 self._grid_height = grid_height self._grid_v_offset = 0 self._one_color = Qt.blue self._zero_color = Qt.white self._color_table = [ QColor(self._zero_color).rgb(), QColor(self._one_color).rgb(), ] self._bit_border_threshold = bit_border_threshold self._easter_egg = 0 self._painting = False self._bits_area = QWidget() self._h_scrollbar = QScrollBar(orientation=Qt.Horizontal) self._h_scrollbar.setMinimum(0) self._h_scrollbar.valueChanged.connect(self._on_scrollbar_change) self._h_scrollbar.hide() self._v_scrollbar = QScrollBar(orientation=Qt.Vertical) self._v_scrollbar.setMinimum(0) self._v_scrollbar.valueChanged.connect(self._on_scrollbar_change) self._v_scrollbar.hide() inner_layout = QVBoxLayout() inner_layout.setContentsMargins(0, 0, 0, 0) inner_layout.setSpacing(0) inner_layout.addWidget(self._bits_area, stretch=1) inner_layout.addWidget(self._h_scrollbar) inner_widget = QWidget() inner_widget.setLayout(inner_layout) outer_layout = QHBoxLayout() outer_layout.setContentsMargins(0, 0, 0, 0) outer_layout.setSpacing(0) outer_layout.addWidget(inner_widget, stretch=1) outer_layout.addWidget(self._v_scrollbar) self.setLayout(outer_layout) @property def offset(self) -> int: return self._offset @offset.setter def offset(self, new_offset): self._offset = new_offset @property def bit_size(self) -> int: return self._bit_size @bit_size.setter def bit_size(self, size: int): self._bit_size = size @property def row_width(self) -> int: return self._row_width @row_width.setter def row_width(self, width: int): self._row_width = width @property def grid_width(self) -> int: return self._grid_width @grid_width.setter def grid_width(self, size: int): self._grid_width = size @property def grid_h_offset(self) -> int: return self._grid_h_offset @grid_h_offset.setter def grid_h_offset(self, offset: int): self._grid_h_offset = offset @property def grid_height(self) -> int: return self._grid_height @grid_height.setter def grid_height(self, size: int): self._grid_height = size @property def grid_v_offset(self) -> int: return self._grid_v_offset @grid_v_offset.setter def grid_v_offset(self, offset: int): self._grid_v_offset = offset @property def _bits_area_width(self): return self._bits_area.width() @property def _bits_area_height(self): return self._bits_area.height() @property def _num_rows(self): return ceil((self._app.num_bits - self._offset) / self._row_width) def set_bit_border_threshold(self, threshold): self._bit_border_threshold = threshold def load_file(self, filename, max_bytes): self._app.load_file(filename, max_bytes) def paintEvent(self, a0: QPaintEvent) -> None: super().paintEvent(a0) if not self._app.num_bits: return self._painting = True self._set_scrollbars() self._paint_bits() self._draw_grid() self._painting = False def _paint_bits(self): visible_columns = self._bits_area_width // self._bit_size visible_rows = self._bits_area_height // self._bit_size bitmap = self._app.create_bitmap( self._offset, self._row_width, self._h_scrollbar.value(), self._v_scrollbar.value(), visible_rows, visible_columns, ) pixmap = self._create_pixmap(bitmap.data, bitmap.width, bitmap.bytes_per_row) painter = QPainter(self) painter.drawPixmap(0, 0, pixmap) self._draw_bit_separators(painter, pixmap.width(), pixmap.height()) self._draw_last_row_of_bits(painter, bitmap.remainder, pixmap) painter.end() def _draw_bit_separators(self, painter: QPainter, right, bottom): if self._bit_size <= self._bit_border_threshold: return painter.setPen(QPen(Qt.black, 1)) self._draw_h_grid(painter, right, bottom, 1, 0) self._draw_v_grid(painter, right, bottom, 1, 0) def _draw_last_row_of_bits(self, painter, last_row_of_bits, pixmap): painter.setPen( QPen( Qt.black if self._bit_size > self._bit_border_threshold else Qt.transparent, 1, Qt.SolidLine, )) for i, b in enumerate(last_row_of_bits): self._draw_bit(painter, i, pixmap.height() // self._bit_size, b) def _draw_bit(self, painter: QPainter, x, y, bit): painter.setBrush( QBrush(self._one_color if bit else self._zero_color, Qt.SolidPattern)) painter.drawRect(x * self._bit_size, y * self._bit_size, self._bit_size, self._bit_size) def _draw_grid(self): if not self._grid_width and not self._grid_height: return if not self._num_rows: return painter = QPainter(self) painter.setPen(QPen(Qt.red, 1, Qt.SolidLine)) right = min( (self._row_width - self._h_scrollbar.value()) * self._bit_size, self._bits_area_width, ) bottom = min( (self._num_rows - self._v_scrollbar.value()) * self._bit_size, self._bits_area_height, ) self._draw_h_grid( painter, right, bottom, self._grid_width, self._grid_h_offset - self._h_scrollbar.value(), ) self._draw_v_grid( painter, right, bottom, self._grid_height, self._grid_v_offset - self._v_scrollbar.value(), ) def _create_pixmap(self, data: bytes, width, bytes_per_row: int): height = len(data) // bytes_per_row image = QImage(data, width, height, bytes_per_row, QImage.Format_Mono) image.setColorTable(self._color_table) return QPixmap.fromImage(image).scaled(width * self._bit_size, height * self._bit_size) def _draw_h_grid(self, painter, right, bottom, grid_width, grid_offset): if not grid_width: return start_offset = grid_offset % grid_width start = start_offset * self._bit_size for x in range(start, right + 1, grid_width * self._bit_size): painter.drawLine(x, 0, x, bottom) def _draw_v_grid(self, painter, right, bottom, grid_height, grid_offset): if not grid_height: return start_offset = grid_offset % grid_height start = start_offset * self._bit_size for y in range(start, bottom + 1, grid_height * self._bit_size): painter.drawLine(0, y, right, y) def _set_scrollbars(self): self._set_h_scrollbar() v_visibility_changed = self._set_v_scrollbar() if v_visibility_changed: h_visibility_changed = self._set_h_scrollbar() if h_visibility_changed: self._set_v_scrollbar() def _set_h_scrollbar(self): h_scroll_max = self._calc_h_scrollbar_max() was_visible = self._h_scrollbar.isVisible() if h_scroll_max > 0: self._h_scrollbar.setMaximum(h_scroll_max) self._h_scrollbar.show() return not was_visible else: self._h_scrollbar.setValue(0) self._h_scrollbar.hide() return was_visible def _set_v_scrollbar(self): v_scroll_max = self._calc_v_scrollbar_max() was_visible = self._v_scrollbar.isVisible() if v_scroll_max > 0: self._v_scrollbar.setMaximum(v_scroll_max) self._v_scrollbar.show() return not was_visible else: self._v_scrollbar.setValue(0) self._v_scrollbar.hide() return was_visible def _calc_h_scrollbar_max(self): return self._row_width - (self._bits_area_width // self.bit_size) def _calc_v_scrollbar_max(self): visible_rows = self._bits_area_height // self.bit_size return self._num_rows - visible_rows def wheelEvent(self, event: QWheelEvent) -> None: y_delta = event.angleDelta().y() if y_delta: notches = ceil(y_delta / 120) self._v_scrollbar.setValue(self._v_scrollbar.value() - notches) x_delta = event.angleDelta().x() if x_delta: notches = ceil(x_delta / 120) self._h_scrollbar.setValue(self._h_scrollbar.value() - notches) def mousePressEvent(self, a0: QMouseEvent) -> None: if (a0.x() <= self._bit_size and a0.y() <= self._bit_size and self._easter_egg < 9): self._easter_egg += 1 elif (self._bit_size <= a0.x() <= self._bit_size * 2 and self._bit_size <= a0.y() <= self._bit_size * 2 and 9 <= self._easter_egg < 12): self._easter_egg += 1 elif (self._bit_size * 2 <= a0.x() <= self._bit_size * 3 and self._bit_size * 2 <= a0.y() <= self._bit_size * 3 and self._easter_egg == 12): tmp = self._one_color self._one_color = self._zero_color self._zero_color = tmp self._color_table = [self._color_table[1], self._color_table[0]] self._easter_egg = 0 else: self._easter_egg = 0 def _on_scrollbar_change(self): if not self._painting: self.repaint()
class App(QWidget): def __init__(self): super().__init__() self.title = 'Tomo Control' self.left = 400 self.top = 400 self.width = 1000 self.height = 600 self.initUI() self.img_bkg = np.array([]) self.img_tomo = np.array([]) self.img_align = np.array([]) self.img_recon = np.array([]) def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.font1 = QtGui.QFont('Arial', 11, QtGui.QFont.Bold) self.font2 = QtGui.QFont('Arial', 11, QtGui.QFont.Normal) self.fpath = os.getcwd() # lb_empty = QLabel() grid = QGridLayout() gpbox_prep = self.GP_prepare() gpbox_recon = self.recon() grid.addWidget(gpbox_prep, 0, 1) grid.addWidget(gpbox_recon, 1, 1) layout = QVBoxLayout() layout.addLayout(grid) layout.addWidget(QLabel()) self.setLayout(layout) # self.resize(640,200) def GP_prepare(self): lb_empty = QLabel() lb_empty2 = QLabel() lb_empty2.setFixedWidth(30) gpbox = QGroupBox('Load image') gpbox.setFont(self.font1) lb_ld = QLabel() lb_ld.setFont(self.font2) lb_ld.setText('Image type:') lb_ld.setFixedWidth(100) self.pb_ld = QPushButton('Load image stack') self.pb_ld.setToolTip('image type: .hdf, .tiff') self.pb_ld.setFont(self.font2) self.pb_ld.clicked.connect(self.load_image) self.pb_ld.setFixedWidth(150) lb_mod = QLabel() lb_mod.setFont(self.font2) lb_mod.setText('Image mode:') lb_mod.setFixedWidth(100) file_group = QButtonGroup() file_group.setExclusive(True) self.rd_hdf = QRadioButton('hdf') self.rd_hdf.setChecked(True) self.rd_tif = QRadioButton('tif') file_group.addButton(self.rd_hdf) file_group.addButton(self.rd_tif) type_group = QButtonGroup() type_group.setExclusive(True) self.rd_absp = QRadioButton('Absorption') self.rd_absp.setFont(self.font2) self.rd_absp.setChecked(True) self.rd_flrc = QRadioButton('Fluorescence') self.rd_flrc.setFont(self.font2) type_group.addButton(self.rd_absp) type_group.addButton(self.rd_flrc) lb_fp = QLabel() lb_fp.setFont(self.font2) lb_fp.setText('Image loaded: ') lb_fp.setFixedWidth(100) self.lb_ip = QLabel() self.lb_ip.setFont(self.font2) hbox1 = QHBoxLayout() hbox1.addWidget(lb_ld) hbox1.addWidget(self.rd_hdf) hbox1.addWidget(self.rd_tif) hbox1.addWidget(lb_empty2) hbox1.addWidget(self.pb_ld) hbox1.addWidget(lb_empty2) hbox1.addWidget(self.lb_ip) hbox1.setAlignment(QtCore.Qt.AlignLeft) hbox2 = QHBoxLayout() hbox2.addWidget(lb_mod) hbox2.addWidget(self.rd_absp) hbox2.addWidget(self.rd_flrc) hbox2.addWidget(lb_empty) hbox2.setAlignment(QtCore.Qt.AlignLeft) vbox = QVBoxLayout() vbox.addLayout(hbox1) vbox.addLayout(hbox2) vbox.setAlignment(QtCore.Qt.AlignLeft) gpbox.setLayout(vbox) return gpbox def recon(self): lb_empty = QLabel() lb_empty2 = QLabel() lb_empty2.setFixedWidth(30) gpbox = QGroupBox('Tomo reconstruction') gpbox.setFont(self.font1) self.canvas1 = MyCanvas() self.canvas2 = MyCanvas() pb_rmbg = QPushButton('Remove Bkg') pb_rmbg.setFont(self.font2) pb_rmbg.clicked.connect(self.rm_bkg) pb_rmbg.setFixedWidth(150) pb_align = QPushButton('Align image') pb_align.setFont(self.font2) pb_align.clicked.connect(self.align_img) pb_align.setFixedWidth(150) self.sl1 = QScrollBar(QtCore.Qt.Horizontal) self.sl1.setMaximum(0) self.sl1.setMinimum(0) # self.sl1.hide() self.sl1.valueChanged.connect(lambda: self.sliderval('left')) self.sl2 = QScrollBar(QtCore.Qt.Horizontal) self.sl2.setMaximum(0) self.sl2.setMinimum(0) # self.sl2.hide() self.sl2.valueChanged.connect(lambda: self.sliderval('right')) self.cb1 = QComboBox() self.cb1.setFont(self.font2) self.cb1.addItem('Raw image') self.cb1.addItem('Background') self.cb1.addItem('Aligned') self.cb1.addItem('Reconstructed') self.cb2 = QComboBox() self.cb2.setFont(self.font2) self.cb2.addItem('Raw image') self.cb2.addItem('Background') self.cb2.addItem('Aligned') self.cb2.addItem('Reconstructed') pb_sh1 = QPushButton('Update') pb_sh1.setToolTip('update left image') pb_sh1.setFont(self.font2) pb_sh1.clicked.connect(lambda: self.update_canvas_img('left')) pb_sh1.setFixedWidth(150) pb_sh2 = QPushButton('Update') pb_sh2.setToolTip('update right image') pb_sh2.setFont(self.font2) pb_sh2.clicked.connect(lambda: self.update_canvas_img('right')) pb_sh2.setFixedWidth(150) hbox = QHBoxLayout() vbox_pb = QVBoxLayout() vbox_pb.addWidget(pb_rmbg) vbox_pb.addWidget(pb_align) vbox_pb.addWidget(lb_empty) vbox_pb.setAlignment(QtCore.Qt.AlignTop) hbox_can_l = QHBoxLayout() hbox_can_l.addWidget(self.cb1) hbox_can_l.addWidget(pb_sh1) hbox_can_r = QHBoxLayout() hbox_can_r.addWidget(self.cb2) hbox_can_r.addWidget(pb_sh2) vbox_can1 = QVBoxLayout() vbox_can1.addWidget(self.canvas1) vbox_can1.addWidget(self.sl1) vbox_can1.addLayout(hbox_can_l) vbox_can1.setAlignment(QtCore.Qt.AlignLeft) vbox_can2 = QVBoxLayout() vbox_can2.addWidget(self.canvas2) vbox_can2.addWidget(self.sl2) vbox_can2.addLayout(hbox_can_r) vbox_can2.setAlignment(QtCore.Qt.AlignLeft) hbox.addLayout(vbox_pb) hbox.addLayout(vbox_can1) hbox.addWidget(lb_empty2) hbox.addLayout(vbox_can2) hbox.setAlignment(QtCore.Qt.AlignLeft) gpbox.setLayout(hbox) return gpbox def load_image(self): options = QFileDialog.Option() options |= QFileDialog.DontUseNativeDialog if self.rd_hdf.isChecked() == True: file_type = 'hdf files (*.h5)' else: file_type = 'tiff files (*.tif)' fn, _ = QFileDialog.getOpenFileName(tomo, "QFileDialog.getOpenFileName()", "", file_type, options=options) self.img_bkg = np.array([]) self.img_tomo = np.array([]) self.img_align = np.array([]) self.img_recon = np.array([]) if fn: print(fn) fn_relative = fn.split('/')[-1] self.lb_ip.setText('{} loaded'.format(fn_relative)) if self.rd_hdf.isChecked() == True: # read hdf file f = h5py.File(fn, 'r') try: self.img_tomo = np.array(f['img_tomo']) except: self.img_tomo = np.zeros([1, 100, 100]) print('bkg image not exist') try: self.img_bkg = np.array(f['img_bkg_raw']) except: self.img_bkg = np.zeros([self.img_tomo.shape]) print('tomo image not exist') f.close() else: # read tiff file self.img_tomo = np.array(io.imread(fn)) if self.img_tomo.shape[0] > 0: print('total images: ' + str(self.img_tomo.shape[0])) # self.sl1.show() # test_img = self.img_tomo[0] # self.canvas1.update_img_one(test_img) # self.show_image(test_img) # def show_image(self, test_img): # ax = self.figure.add_subplot(111) # ax.clear() # ax.imshow(test_img) # self.canvas.draw() # def show_image(self, test_img): # colormap = [] ## for i in range(255): ## colormap.append(QtGui.qRgb(i,i,i)) # w, h = test_img.shape # # pp = QtGui.QImage(test_img.data, h,w, QtGui.QImage.Format_RGB32) ## if (max(pp.width(), pp.height()) > 600) ## pixmap = QtGui.QPixmap(pp.scaled(pp.width()/2, pp.height()/2)) ## else: # pixmap = QtGui.QPixmap(pp) # self.lb_pic.setPixmap(pixmap) def sliderval(self, slide_type): if slide_type == 'left': canvas = self.canvas1 img_index = self.sl1.value() else: canvas = self.canvas2 img_index = self.sl2.value() img = canvas.img_stack[img_index] img = np.array(img) # self.show_image(img) canvas.update_img_one(img) def rm_bkg(self): pass def align_img(self): pass def update_canvas_img(self, canv): if canv == 'left': canvas = self.canvas1 slide = self.sl1 index = self.cb1.currentIndex() print(str(1) + ' ' + str(index)) else: canvas = self.canvas2 slide = self.sl2 index = self.cb2.currentIndex() print(str(2) + ' ' + str(index)) if index == 0: canvas.img_stack = self.img_tomo canvas.update_img_stack() slide.setMaximum(max(self.img_tomo.shape[0] - 1, 0)) elif index == 1: canvas.img_stack = self.img_bkg canvas.update_img_stack() slide.setMaximum(max(self.img_bkg.shape[0] - 1, 0)) elif index == 2: canvas.img_stack = self.img_align canvas.update_img_stack() slide.setMaximum(max(self.img_align.shape[0] - 1, 0)) else: canvas.img_stack = self.img_recon canvas.update_img_stack() slide.setMaximum(max(self.img_recon.shape[0] - 1, 0))
class CarlaRackW(QFrame, HostWidgetMeta): #class CarlaRackW(QFrame, HostWidgetMeta, metaclass=PyQtMetaClass): def __init__(self, parent, host, doSetup = True): QFrame.__init__(self, parent) self.host = host if False: # kdevelop likes this :) host = CarlaHostMeta() self.host = host # ------------------------------------------------------------- self.fLayout = QHBoxLayout(self) self.fLayout.setContentsMargins(0, 0, 0, 0) self.fLayout.setSpacing(0) self.setLayout(self.fLayout) self.fPadLeft = QLabel(self) self.fPadLeft.setFixedWidth(25) self.fPadLeft.setObjectName("PadLeft") self.fPadLeft.setText("") self.fPadRight = QLabel(self) self.fPadRight.setFixedWidth(25) self.fPadRight.setObjectName("PadRight") self.fPadRight.setText("") self.fRack = CarlaRackList(self, host) self.fRack.setObjectName("CarlaRackList") self.fRack.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.fRack.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.fRack.currentRowChanged.connect(self.slot_currentRowChanged) sb = self.fRack.verticalScrollBar() self.fScrollBar = QScrollBar(Qt.Vertical, self) self.fScrollBar.setMinimum(sb.minimum()) self.fScrollBar.setMaximum(sb.maximum()) self.fScrollBar.setValue(sb.value()) #sb.actionTriggered.connect(self.fScrollBar.triggerAction) #sb.sliderMoved.connect(self.fScrollBar.) #sb.sliderPressed.connect(self.fScrollBar.) #sb.sliderReleased.connect(self.fScrollBar.) sb.rangeChanged.connect(self.fScrollBar.setRange) sb.valueChanged.connect(self.fScrollBar.setValue) self.fScrollBar.rangeChanged.connect(sb.setRange) self.fScrollBar.valueChanged.connect(sb.setValue) self.fLayout.addWidget(self.fPadLeft) self.fLayout.addWidget(self.fRack) self.fLayout.addWidget(self.fPadRight) self.fLayout.addWidget(self.fScrollBar) # ------------------------------------------------------------- # Internal stuff self.fParent = parent self.fPluginCount = 0 self.fPluginList = [] self.fCurrentRow = -1 self.fLastSelectedItem = None # ------------------------------------------------------------- # Set-up GUI stuff #app = QApplication.instance() #pal1 = app.palette().base().color() #pal2 = app.palette().button().color() #col1 = "stop:0 rgb(%i, %i, %i)" % (pal1.red(), pal1.green(), pal1.blue()) #col2 = "stop:1 rgb(%i, %i, %i)" % (pal2.red(), pal2.green(), pal2.blue()) self.setStyleSheet(""" QLabel#PadLeft { background-image: url(:/bitmaps/rack_padding_left.png); background-repeat: repeat-y; } QLabel#PadRight { background-image: url(:/bitmaps/rack_padding_right.png); background-repeat: repeat-y; } CarlaRackList#CarlaRackList { background-color: black; } """) # ------------------------------------------------------------- # Connect actions to functions host.PluginAddedCallback.connect(self.slot_handlePluginAddedCallback) host.PluginRemovedCallback.connect(self.slot_handlePluginRemovedCallback) host.ReloadAllCallback.connect(self.slot_handleReloadAllCallback) if not doSetup: return parent.ui.menu_Canvas.hide() parent.ui.act_plugins_enable.triggered.connect(self.slot_pluginsEnable) parent.ui.act_plugins_disable.triggered.connect(self.slot_pluginsDisable) parent.ui.act_plugins_volume100.triggered.connect(self.slot_pluginsVolume100) parent.ui.act_plugins_mute.triggered.connect(self.slot_pluginsMute) parent.ui.act_plugins_wet100.triggered.connect(self.slot_pluginsWet100) parent.ui.act_plugins_bypass.triggered.connect(self.slot_pluginsBypass) parent.ui.act_plugins_center.triggered.connect(self.slot_pluginsCenter) parent.ui.act_plugins_panic.triggered.connect(self.slot_pluginsDisable) parent.ui.act_settings_configure.triggered.connect(self.slot_configureCarla) # ----------------------------------------------------------------- @pyqtSlot(int, str) def slot_handlePluginAddedCallback(self, pluginId, pluginName): pitem = CarlaRackItem(self.fRack, pluginId, self.fParent.getSavedSettings()[CARLA_KEY_MAIN_USE_CUSTOM_SKINS]) self.fPluginList.append(pitem) self.fPluginCount += 1 if not self.fParent.isProjectLoading(): pitem.getWidget().setActive(True, True, True) @pyqtSlot(int) def slot_handlePluginRemovedCallback(self, pluginId): pitem = self.getPluginItem(pluginId) self.fPluginCount -= 1 self.fPluginList.pop(pluginId) self.fRack.takeItem(pluginId) if pitem is not None: pitem.closeEditDialog() del pitem # push all plugins 1 slot back for i in range(pluginId, self.fPluginCount): pitem = self.fPluginList[i] pitem.setPluginId(i) # ----------------------------------------------------------------- # HostWidgetMeta methods def removeAllPlugins(self): while self.fRack.takeItem(0): pass for pitem in self.fPluginList: if pitem is None: break pitem.closeEditDialog() del pitem self.fPluginCount = 0 self.fPluginList = [] def engineStarted(self): pass def engineStopped(self): pass def idleFast(self): for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().idleFast() def idleSlow(self): for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().idleSlow() def projectLoadingStarted(self): self.fRack.setEnabled(False) def projectLoadingFinished(self): self.fRack.setEnabled(True) def saveSettings(self, settings): pass def showEditDialog(self, pluginId): dialog = self.getPluginEditDialog(pluginId) if dialog is None: return dialog.show() # ----------------------------------------------------------------- @pyqtSlot() def slot_pluginsEnable(self): if not self.host.is_engine_running(): return for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().setActive(True, True, True) @pyqtSlot() def slot_pluginsDisable(self): if not self.host.is_engine_running(): return for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().setActive(False, True, True) @pyqtSlot() def slot_pluginsVolume100(self): if not self.host.is_engine_running(): return for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().setInternalParameter(PLUGIN_CAN_VOLUME, 1.0) @pyqtSlot() def slot_pluginsMute(self): if not self.host.is_engine_running(): return for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().setInternalParameter(PLUGIN_CAN_VOLUME, 0.0) @pyqtSlot() def slot_pluginsWet100(self): if not self.host.is_engine_running(): return for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().setInternalParameter(PLUGIN_CAN_DRYWET, 1.0) @pyqtSlot() def slot_pluginsBypass(self): if not self.host.is_engine_running(): return for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().setInternalParameter(PLUGIN_CAN_DRYWET, 0.0) @pyqtSlot() def slot_pluginsCenter(self): if not self.host.is_engine_running(): return for pitem in self.fPluginList: if pitem is None: break pitem.getWidget().setInternalParameter(PARAMETER_BALANCE_LEFT, -1.0) pitem.getWidget().setInternalParameter(PARAMETER_BALANCE_RIGHT, 1.0) pitem.getWidget().setInternalParameter(PARAMETER_PANNING, 0.0) # ----------------------------------------------------------------- @pyqtSlot() def slot_configureCarla(self): dialog = CarlaSettingsW(self, self.host, False, False) if not dialog.exec_(): return self.fParent.loadSettings(False) # ----------------------------------------------------------------- @pyqtSlot(int) def slot_handleReloadAllCallback(self, pluginId): if pluginId >= self.fPluginCount: return pitem = self.fPluginList[pluginId] if pitem is None: return self.fRack.setCurrentRow(-1) self.fCurrentRow = -1 self.fLastSelectedItem = None pitem.recreateWidget() # ----------------------------------------------------------------- @pyqtSlot(int) def slot_currentRowChanged(self, row): self.fCurrentRow = row if self.fLastSelectedItem is not None: self.fLastSelectedItem.setSelected(False) if row < 0 or row >= self.fPluginCount or self.fPluginList[row] is None: self.fLastSelectedItem = None return pitem = self.fPluginList[row] pitem.getWidget().setSelected(True) self.fLastSelectedItem = pitem.getWidget() # ----------------------------------------------------------------- def getPluginItem(self, pluginId): if pluginId >= self.fPluginCount: return None pitem = self.fPluginList[pluginId] if pitem is None: return None if False: pitem = CarlaRackItem(self, 0, False) return pitem def getPluginEditDialog(self, pluginId): if pluginId >= self.fPluginCount: return None pitem = self.fPluginList[pluginId] if pitem is None: return None if False: pitem = CarlaRackItem(self, 0, False) return pitem.getEditDialog() def getPluginSlotWidget(self, pluginId): if pluginId >= self.fPluginCount: return None pitem = self.fPluginList[pluginId] if pitem is None: return None if False: pitem = CarlaRackItem(self, 0, False) return pitem.getWidget()
class MainWindow(MainWindowBase, MainWindowUI): VIDEOS = ('front_video_file', 'eyes_video_file') def __init__(self, manager, parent=None): MainWindowBase.__init__(self, parent) self.manager = manager self.current_segment = None self.current_video = 0 self.nav_hide_empty = True self.setupUi(self) self.setupConnections() def setupUi(self, parent): MainWindowUI.setupUi(self, parent) # content area layout = QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.content.setLayout(layout) # add video widget self.contentWidget = VideoWidget() self.content.layout().addWidget(self.contentWidget) self.prev_code = 'def f(img):\n return img' self.te_code = PyCodeEdit() self.te_code.setPlainText(self.prev_code) self.content.layout().addWidget(self.te_code) # footer area layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.footer.setLayout(layout) self.bar_index = QScrollBar(Qt.Horizontal) self.bar_index.setFocusPolicy(Qt.WheelFocus) self.bar_index.setMinimum(0) self.bar_index.setSingleStep(1) self.bar_index.valueChanged.connect(self.indexChanged) layout.addWidget(self.bar_index) self.info = QLabel() layout.addWidget(self.info) # construct navigation tree self.refreshNavigation() # design the view self.treeView.header().hide() # hide header self.treeView.expandToDepth(0) # expand first level def setupConnections(self): # shortcuts self.sc_next = QShortcut(QKeySequence("Right"), self) self.sc_next.activated.connect(self.nextImage) self.sc_prev = QShortcut(QKeySequence("Left"), self) self.sc_prev.activated.connect(self.prevImage) self.treeView.doubleClicked.connect(self.navigation_doubleClicked) self.pb_video_toggle.clicked.connect(self.toggleVideo) self.pb_hide_toggle.clicked.connect(self.toggleHideEmpty) def toggleVideo(self): self.current_video = (self.current_video + 1) % len(MainWindow.VIDEOS) self.setSegment(self.current_segment) def toggleHideEmpty(self): self.nav_hide_empty = not self.nav_hide_empty self.refreshNavigation() def refreshNavigation(self): items = [] for project_id in self.manager.getProjectNames(): project = self.manager.getProject(project_id) p_node = NavigationNode(project.info['Name']) p_node.obj_data = project items.append(p_node) for r_id in sorted(p_node.obj_data.getRecordingNames()): print(r_id) recording = p_node.obj_data.getRecording(r_id) print(recording) if recording: r_node = NavigationNode(r_id) r_node.obj_data = recording p_node.addChild(r_node) for segment_id in r_node.obj_data.getSegmentIDs(): s_node = NavigationNode(segment_id) s_node.obj_data = r_node.obj_data.getSegment( segment_id) r_node.addChild(s_node) self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.treeView.setUniformRowHeights(True) self.treeView.setModel(NavigationModel(items)) def navigation_doubleClicked(self, _): item = self.treeView.selectedIndexes()[0] obj = item.internalPointer().obj_data if hasattr(obj, 'segments') and obj.segments_data: obj = obj.segments_data[0] if hasattr(obj, 'eyes_video_file'): self.setSegment(obj) def applyCode(self): code = self.te_code.toPlainText() if self.prev_code != code: try: exec(code, globals(), locals()) self.contentWidget.onImage = locals()['f'] except Exception as e: print(e) def prevImage(self): self.bar_index.setValue(self.bar_index.value() - 1) def nextImage(self): self.bar_index.setValue(self.bar_index.value() + 1) def setVideo(self, path): self.contentWidget.openVideo(path) self.bar_index.setMaximum(self.contentWidget.video.length) def indexChanged(self, value): self.applyCode() video = self.contentWidget.video video.pos_frame = value self.contentWidget.updateImage() info_msg = [] info_msg.append('FPS: %s' % video.fps) info_msg.append('Frame: %d / %d (%.4f)' % (video.pos_frame + 1, video.length, video.pos_msec)) self.info.setText('\n'.join(info_msg)) def setSegment(self, segment): try: self.current_segment = segment self.setVideo( getattr(self.current_segment, MainWindow.VIDEOS[self.current_video])) self.bar_index.setValue(0) self.indexChanged(0) except: pass
class EditorMapComponent: current = None def __init__(self, tabbed=True, parent=None): EditorMapComponent.current = self self.workspace = Workspace() self.gc_state = GraphicContextState() if tabbed: self.tab_widget = QTabWidget(parent) self.widget = QWidget(self.tab_widget) self.tab_widget.addTab(self.widget, "A Label") else: self.tab_widget = None self.widget = QWidget(parent) self.layout = QGridLayout(self.widget) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.setHorizontalSpacing(0) self.layout.setVerticalSpacing(0) self.scroll_horz = QScrollBar(Qt.Horizontal) self.scroll_vert = QScrollBar(Qt.Vertical) self.editormap_widget = EditorMapWidget(self, None) self.scroll_horz.valueChanged.connect(self.move_to_x) self.scroll_vert.valueChanged.connect(self.move_to_y) self.layout.addWidget(self.editormap_widget, 0, 0) self.layout.addWidget(self.scroll_horz, 1, 0) self.layout.addWidget(self.scroll_vert, 0, 1) self.sig_drop = Signal() self.editormap_widget.sig_drop.connect(self.on_drop) def on_drop(self, data, pos): """sends (brush, pos)""" brush_id = pickle.loads(data) brush = ObjectSelector.current.get_brush(brush_id) return self.sig_drop(brush, pos) def get_workspace(self): return self.workspace def grab_mouse(self): self.editormap_widget.grabMouse() def release_mouse(self): self.editormap_widget.releaseMouse() # ifdef GRUMBEL # void # EditorMapComponentImpl::on_key_down(const CL_InputEvent& event) # { # if (event.id >= 0 && event.id < 256) # { # Rect rect = parent.get_position() # key_bindings[event.id](CL_Mouse::get_x() - rect.left, # CL_Mouse::get_y() - rect.top) # } # if (event.repeat_count == 0) # { # Rect rect = parent.get_position() # CL_InputEvent ev2 = event # ev2.mouse_pos = Point(CL_Mouse::get_x() - rect.left, # CL_Mouse::get_y() - rect.top) # workspace.key_down(InputEvent(ev2)) # } # } # void # EditorMapComponentImpl::on_key_up(const CL_InputEvent& event) # { # Rect rect = parent.get_position() # CL_InputEvent ev2 = event # ev2.mouse_pos = Point(CL_Mouse::get_x() - rect.left, # CL_Mouse::get_y() - rect.top) # workspace.key_up(InputEvent(ev2)) # } # void # EditorMapComponentImpl::draw () # { # if (workspace.get_map().is_null()) return # Display::push_cliprect(parent.get_screen_rect()) # Display::push_modelview() # Display::add_translate(parent.get_screen_x(), parent.get_screen_y()) # // Update scrollbars (FIXME: move me to function) # scrollbar_v.set_range(0, workspace.get_map().get_bounding_rect().height) # scrollbar_v.set_pagesize(parent.height/gc_state.get_zoom()) # scrollbar_v.set_pos(gc_state.get_pos().y) # scrollbar_h.set_range(0, workspace.get_map().get_bounding_rect().width) # scrollbar_h.set_pagesize(parent.width/gc_state.get_zoom()) # scrollbar_h.set_pos(gc_state.get_pos().x) # gc_state.push() # { # GraphicContext gc(gc_state, CL_Display::get_current_window().get_gc()) # workspace.draw(gc) # } # gc_state.pop() # Display::pop_modelview() # Display::pop_cliprect() # } # endif def screen2world(self, pos): return self.gc_state.screen2world(pos) def set_zoom(self, z): self.gc_state.set_zoom(z) self.editormap_widget.repaint() self.update_scrollbars() def zoom_out(self, pos): self.gc_state.set_zoom(self.gc_state.get_zoom() / 1.25, Pointf(pos.x, pos.y)) self.editormap_widget.repaint() self.update_scrollbars() def zoom_in(self, pos): self.gc_state.set_zoom(self.gc_state.get_zoom() * 1.25, Pointf(pos.x, pos.y)) self.editormap_widget.repaint() self.update_scrollbars() def zoom_to(self, rect): self.gc_state.zoom_to(rect) self.editormap_widget.repaint() self.update_scrollbars() def get_clip_rect(self): return self.gc_state.get_clip_rect() def move_to(self, x, y): self.gc_state.set_pos(Pointf(x, y)) self.editormap_widget.repaint() self.update_scrollbars() def move_to_x(self, x): self.gc_state.set_pos(Pointf(x, self.gc_state.get_pos().y)) self.editormap_widget.repaint() self.update_scrollbars() def move_to_y(self, y): self.gc_state.set_pos(Pointf(self.gc_state.get_pos().x, y)) self.editormap_widget.repaint() self.update_scrollbars() def sig_on_key(self, keyseq_str): key_sequence = QKeySequence(keyseq_str) if key_sequence.isEmpty(): raise RuntimeError("invalid key binding: '%s'" % keyseq_str) shortcut = QShortcut(key_sequence, self.editormap_widget) signal = Signal() def on_key(*args): pos = self.editormap_widget.mapFromGlobal(QCursor.pos()) # pos = self.gc_state.screen2world(Point.from_qt(pos)) signal(pos.x(), pos.y()) shortcut.activated.connect(on_key) return signal def get_gc_state(self): return self.gc_state def get_widget(self): return self.tab_widget or self.widget def update_scrollbars(self): rect = self.workspace.get_map().get_bounding_rect() border = 128 self.scroll_horz.setMinimum(rect.left - border) self.scroll_horz.setMaximum(rect.right + border) self.scroll_horz.setPageStep(self.editormap_widget.width()) self.scroll_horz.setSliderPosition(int(self.gc_state.get_pos().x)) self.scroll_vert.setMinimum(rect.top - border) self.scroll_vert.setMaximum(rect.bottom + border) self.scroll_vert.setPageStep(self.editormap_widget.height()) self.scroll_vert.setSliderPosition(int(self.gc_state.get_pos().y)) def set_sector_tab_label(self, index, text): self.tab_widget.setTabText(index, "Sector \"%s\"" % text)