def diff_colour(self, actual_colour: QColor, expected_colour: QColor, x: int, y: int): diff_size = (abs(actual_colour.red() - expected_colour.red()) + abs(actual_colour.green() - expected_colour.green()) + abs(actual_colour.blue() - expected_colour.blue())) if diff_size <= self.max_diff: diff_colour = actual_colour.toRgb() diff_colour.setAlpha(diff_colour.alpha() // 3) return diff_colour if self.different_pixels == 0: self.diff_min_x = self.diff_max_x = x self.diff_min_y = self.diff_max_y = y else: self.diff_min_x = min(self.diff_min_x, x) self.diff_max_x = max(self.diff_max_x, x) self.diff_min_y = min(self.diff_min_y, y) self.diff_max_y = max(self.diff_max_y, y) self.different_pixels += 1 # Colour dr = 0xff dg = (actual_colour.green() + expected_colour.green()) // 5 db = (actual_colour.blue() + expected_colour.blue()) // 5 # Opacity da = 0xff return QColor(dr, dg, db, da)
def AreColorsClose(color, anotherColor, threshold=100): color = QColor(color) anotherColor = QColor(anotherColor) redDifference = color.red() - anotherColor.red() blueDifference = color.blue() - anotherColor.blue() greenDifference = color.green() - anotherColor.green() return (redDifference**2 + blueDifference**2 + greenDifference**2) <= threshold * threshold
class ColorInformation(QGraphicsItem): def __init__(self, parent=None): super(ColorInformation, self).__init__(parent) self.color = QColor(255, 255, 0) self.font = QFont("courier", 10) self.font.setBold(True) self.pos = QPoint() def boundingRect(self): return QRectF(0, 0, 130, 100) def paint(self, painter, option, widget=None): painter.setBrush(QBrush(self.color)) painter.setFont(self.font) painter.drawRoundedRect(12, 12, 30, 74, 5, 5) painter.setBrush(QColor(0, 0, 0, 55)) painter.setPen(QPen(Qt.transparent)) painter.drawRect(44, 12, 74, 74) painter.setPen(QPen(Qt.red)) painter.drawText(50, 26, "R: " + str(self.color.red())) painter.setPen(QPen(Qt.green)) painter.drawText(50, 52, "G: " + str(self.color.green())) painter.setPen(QPen(Qt.blue)) painter.drawText(50, 80, "B: " + str(self.color.blue()))
def blend_colors(color1: QColor, color2: QColor, r: float = 0.2, alpha=255) -> QColor: """Blend two qt colors together. Args: color1 (QColor): first color color2 (QColor): second color r (float): ratio alpha (int): alpha Returns: QColor: new color """ color3 = QColor(color1.red() * (1 - r) + color2.red() * r, color1.green() * (1 - r) + color2.green() * r, color1.blue() * (1 - r) + color2.blue() * r, alpha) return color3
def draw_tron_extended_background(self, painter): # main rect c = QColor('#212224') painter.setBrush(c) pen = QPen(self.parent_node.color) pen.setWidth(2) painter.setPen(pen) body_path = self.get_extended_body_path_TRON_DESIGN(10) painter.drawPath(body_path) # painter.drawRoundedRect(self.boundingRect(), 12, 12) c = self.parent_node.color header_gradient = QLinearGradient(self.get_header_rect().topRight(), self.get_header_rect().bottomLeft()) header_gradient.setColorAt(0, QColor(c.red(), c.green(), c.blue(), 255)) header_gradient.setColorAt(0.5, QColor(c.red(), c.green(), c.blue(), 100)) header_gradient.setColorAt(1, QColor(c.red(), c.green(), c.blue(), 0)) painter.setBrush(header_gradient) header_path = self.get_extended_header_path_TRON_DESIGN(10) painter.drawPath(header_path)
def selected(self, color: QColor): w: ColorStyle = self.sender() for widget in self.widgets: if widget != w: widget.checked = False self.sliderRed.setValue(color.red()) self.sliderGreen.setValue(color.green()) self.sliderBlue.setValue(color.blue()) # 根据背景色自动计算合适的前景色 gray: float = (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255 textColor: QColor = QColor(Qt.black) if gray > 0.5 else QColor( Qt.white) self.labValue.setStyleSheet("font:16px;color:%s;" % textColor.name()) self.labValue.setText(color.name().upper()) self.colorStyle0.bgColor = color self.colorStyle0.checked = False self.changeStyle.emit(color.name())
def setColor(self, color: QColor) -> None: # 根据背景色自动计算合适的前景色 gray: float = (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255 textColor: QColor = QColor(Qt.black) if gray > 0.5 else QColor( Qt.white) self.labColor.setText(color.name().upper()) self.labColor.setStyleSheet( "QLabel{font:25px;color:%s;background:%s;}" % (textColor.name(), color.name())) percentRed: float = color.redF() * 100 percentGreen: float = color.greenF() * 100 percentBlue: float = color.blueF() * 100 self.btnCyan.text = "Cyan\n%0.1f%%" % round(100 - percentRed, 1) self.btnMagenta.text = "Magenta\n%0.1f%%" % round( 100 - percentGreen, 1) self.btnYellow.text = "Yellow\n%0.1f%%" % round(100 - percentBlue, 1) self.btnRed.text = "Red\n%0.1f%%" % round(percentRed, 1) self.btnGreen.text = "Green\n%0.1f%%" % round(percentGreen, 1) self.btnBlue.text = "Blue\n%0.1f%%" % round(percentBlue, 1)
def generatedIconPixmap(self, iconMode, pixmap, option): """ Draws the icon button brighter when hovered over. """ if iconMode == QIcon.Normal: return pixmap elif iconMode == QIcon.Active: if self.brighterPixmap is None: img = pixmap.toImage().convertToFormat(QImage.Format_ARGB32) imgh = img.height() imgw = img.width() pixel = None for y in range(0, imgh): for x in range(0, imgw): pixel = img.pixel(x, y) color = QColor(pixel) h, s, v, a = color.getHsv() if v > self.LOW_LIMIT: # value below this limit will not be adjusted if v < self.HIGH_LIMIT: # value above this limit will just max up to 255 v = v + self.ADJUSTMNET else: v = self.MAX_VALUE color.setHsv(h,s,v) img.setPixel(x, y, qRgba(color.red(), color.green(), color.blue(), qAlpha(pixel))) self.brighterPixmap = QPixmap.fromImage(img) return self.brighterPixmap
class OptionsFromSourceWidget(QWidget): def __init__(self, label_width=64, status_bar=None): super(OptionsFromSourceWidget, self).__init__() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.status_bar = status_bar self.pixels = 10 self.margin = 0 self.background = QColor(255, 255, 255) pixel_param = ParameterInteger( self, value=self.pixels, max_visible=64, min_value=1, name="pixels", label_text="Pix per Unit", label_width=label_width, change_callback=self.chenge_value_callback) margin_param = ParameterInteger( self, value=self.margin, max_visible=64, min_value=0, name="margin", label_text="Margin", label_width=label_width, change_callback=self.chenge_value_callback) back_color = ParameterColor(self, value=self.background, name="background", label_text="Background", label_width=label_width, change_callback=self.chenge_value_callback) layout.addWidget(pixel_param) layout.addWidget(margin_param) layout.addWidget(back_color) self.setLayout(layout) def chenge_value_callback(self, param_name="", param_value=None): if param_name == "pixels": self.pixels = param_value if self.status_bar is not None: self.status_bar.showMessage("Set pixels per unit to " + str(self.pixels)) elif param_name == "margin": self.margin = param_value if self.status_bar is not None: self.status_bar.showMessage("Set margin to " + str(self.margin) + " pixels") elif param_name == "background": self.background = param_value if self.status_bar is not None: self.status_bar.showMessage("Set background color to RGB(" + ", ".join([ str(self.background.red()), str(self.background.green()), str(self.background.blue()) ]) + ")") def get_pixel_value(self): return self.pixels def get_margin_value(self): return self.margin def get_background_value(self): return (self.background.red(), self.background.green(), self.background.blue())
class QAVButton(QPushButton): def __init__(self, label): """ builds a custom button and displays it""" # calls super constuctor super(QAVButton, self).__init__(label) self.sound = QSoundEffect() self.volume = 1. self.color = QColor(Qt.gray) self.count = 0 self.duration = 1000 self.rate = 20 self.timer = QTimer() self.timer.timeout.connect(self.update_anim) self.mode = "toggle" self.pressed.connect(self.start) self.released.connect(self.stop) self.is_accelerating = False self.update_style("") def setSound(self, sound_file): self.sound.setSource(QUrl.fromLocalFile(sound_file)) #self.sound.setLoopCount(QSoundEffect.Infinite) def start(self): self.count = 0 self.sound.play() self.timer.start(self.rate) def stop(self): self.timer.stop() self.sound.stop() self.update_style("") def set_color(self, col): self.color = col def update_color_with_alha(self, alpha): red = self.color.red() green = self.color.green() blue = self.color.blue() bg_style = f"background-color:rgba({red},{green},{blue}, {alpha});" self.update_style(bg_style) def update_style(self, bg): bg_style = "QPushButton {" + bg + BUTTON_STYLE + "}" self.setStyleSheet(bg_style) def update_anim(self): # logarithmic (check with perception of luminosity/brighness) # val = math.log(count + 1) # linear if self.mode == "sin": val = math.sin(self.count * 2 * math.pi) / 2 + 0.5 elif self.mode == "lin": val = 1 - self.count elif self.mode == "toggle": val = 1 else: val = math.log(self.count + 1) alpha = round(val * 100) + 155 self.update_color_with_alha(alpha) amplitude = val * 0.8 + 0.2 self.sound.setVolume(amplitude) self.count = self.count + self.rate / self.duration # print(count) if self.count >= 1 - self.rate / self.duration: self.count = 0 if self.is_accelerating: self.duration = max(200, self.duration * 0.95)
def paint(self, painter, option, widget=None): painter.setRenderHint(QPainter.Antialiasing) brush = QBrush(QColor(100, 100, 100, 150)) # QBrush(QColor('#3B9CD9')) painter.setBrush(brush) std_pen = QPen( QColor(30, 43, 48) ) # QColor(30, 43, 48) # used for header title and minimal std dark border std_pen.setWidthF(1.5) # painter.setPen(std_pen) if self.parent_node.design_style == 'extended': if GlobalStorage.storage['design style'] == 'dark std': c = self.parent_node.color # main rect body_gradient = QRadialGradient( self.boundingRect().topLeft(), self.flow.pythagoras(self.height, self.width)) body_gradient.setColorAt( 0, QColor(c.red() / 10 + 100, c.green() / 10 + 100, c.blue() / 10 + 100, 200)) body_gradient.setColorAt( 1, QColor(c.red() / 10 + 100, c.green() / 10 + 100, c.blue() / 10 + 100, 0)) painter.setBrush(body_gradient) painter.setPen(Qt.NoPen) painter.drawRoundedRect(self.boundingRect(), 12, 12) header_gradient = QLinearGradient( self.get_header_rect().topRight(), self.get_header_rect().bottomLeft()) header_gradient.setColorAt( 0, QColor(c.red(), c.green(), c.blue(), 255)) header_gradient.setColorAt( 1, QColor(c.red(), c.green(), c.blue(), 0)) painter.setBrush(header_gradient) painter.setPen(Qt.NoPen) painter.drawRoundedRect(self.get_header_rect(), 12, 12) elif GlobalStorage.storage['design style'] == 'dark tron': # main rect c = QColor('#212224') painter.setBrush(c) pen = QPen(self.parent_node.color) pen.setWidth(2) painter.setPen(pen) body_path = self.get_extended_body_path_TRON_DESIGN(10) painter.drawPath(body_path) # painter.drawRoundedRect(self.boundingRect(), 12, 12) c = self.parent_node.color header_gradient = QLinearGradient( self.get_header_rect().topRight(), self.get_header_rect().bottomLeft()) header_gradient.setColorAt( 0, QColor(c.red(), c.green(), c.blue(), 255)) header_gradient.setColorAt( 0.5, QColor(c.red(), c.green(), c.blue(), 100)) header_gradient.setColorAt( 1, QColor(c.red(), c.green(), c.blue(), 0)) painter.setBrush(header_gradient) header_path = self.get_extended_header_path_TRON_DESIGN(10) painter.drawPath(header_path) painter.setFont(self.display_name_font) painter.setPen(std_pen) painter.drawText(self.get_title_rect(), Qt.AlignVCenter | Qt.AlignLeft, self.parent_node.title) painter.setBrush(Qt.NoBrush) painter.setPen(QPen(Qt.white, 1)) # painter.drawRect(self.get_header_rect()) elif self.parent_node.design_style == 'minimalistic': path = QPainterPath() path.moveTo(-self.width / 2, 0) if GlobalStorage.storage['design style'] == 'dark std': path.cubicTo(-self.width / 2, -self.height / 2, -self.width / 2, -self.height / 2, 0, -self.height / 2) path.cubicTo(+self.width / 2, -self.height / 2, +self.width / 2, -self.height / 2, +self.width / 2, 0) path.cubicTo(+self.width / 2, +self.height / 2, +self.width / 2, +self.height / 2, 0, +self.height / 2) path.cubicTo(-self.width / 2, +self.height / 2, -self.width / 2, +self.height / 2, -self.width / 2, 0) path.closeSubpath() c = self.parent_node.color body_gradient = QLinearGradient( self.boundingRect().bottomLeft(), self.boundingRect().topRight()) # 2*self.flow.pythagoras(self.height, self.width)) body_gradient.setColorAt( 0, QColor(c.red(), c.green(), c.blue(), 150)) body_gradient.setColorAt( 1, QColor(c.red(), c.green(), c.blue(), 80)) painter.setBrush(body_gradient) painter.setPen(std_pen) elif GlobalStorage.storage['design style'] == 'dark tron': corner_size = 10 path.lineTo(-self.width / 2 + corner_size / 2, -self.height / 2 + corner_size / 2) path.lineTo(0, -self.height / 2) path.lineTo(+self.width / 2 - corner_size / 2, -self.height / 2 + corner_size / 2) path.lineTo(+self.width / 2, 0) path.lineTo(+self.width / 2 - corner_size / 2, +self.height / 2 - corner_size / 2) path.lineTo(0, +self.height / 2) path.lineTo(-self.width / 2 + corner_size / 2, +self.height / 2 - corner_size / 2) path.closeSubpath() c = QColor('#36383B') painter.setBrush(c) pen = QPen(self.parent_node.color) pen.setWidth(2) painter.setPen(pen) painter.drawPath(path) painter.setFont(self.display_name_font) painter.drawText(self.boundingRect(), Qt.AlignCenter, self.parent_node.title)
class Canvas (QWidget): def __init__(self): QWidget.__init__(self) self.file = "mug.webp" self.__img = cv2.imread(self.file) self.__mask = np.zeros(1) self.original = cv2.imread(self.file) self.__thirdChannelMask = np.dstack((self.__mask, self.__mask, self.__mask)) self.__nseg = 1 self.__sig = 1 self.__comp = 1 self.nSlider = QSlider(orientation=Qt.Horizontal) self.sigSlider = QSlider(orientation=Qt.Horizontal) self.thicSlider = QSlider(orientation=Qt.Horizontal) self.resize_spinbox = QSpinBox(self) self.resize_spinbox.setRange(1, 100) self.resize_spinbox.setValue(100) self.resize_spinbox.setSuffix(" %") self.double_spin_width = QDoubleSpinBox(self) self.double_spin_width.setSuffix(" px") self.double_spin_width.setValue(0) self.double_spin_width.setRange(1, 2000) self.double_spin_height = QDoubleSpinBox(self) self.double_spin_height.setSuffix(" px") self.double_spin_height.setValue(0) self.double_spin_height.setRange(1, 2000) self.zeroModeCheck = QCheckBox("Usar SLIC0") self.__highlightcolor = QColor(255, 255, 255) self.__transparency = 0.5 self.__AllColors = [self.__highlightcolor.toTuple()[:3]] nLabel = QLabel("Numero de segmentos:") sigLabel = QLabel("Sigma:") thicLabel = QLabel("Compactação:") resizeLabel = QLabel("Fator de resize da image:") makssizeLabel = QLabel("Dimensão da mascara de saída:") self.__label = QLabel() nLabel.setToolTip("O número aproximado de labels da imagem segmentada") sigLabel.setToolTip("A largura da Gaussiana") thicLabel.setToolTip("Equilibra a proximidade das cores e a proximidade do espaço, maiores valores tornam os Superpixels mais quadrados") self.nSlider.setMinimum(1) self.nSlider.setMaximum(100) self.sigSlider.setMinimum(1) self.sigSlider.setMaximum(100) self.thicSlider.setMinimum(1) self.thicSlider.setMaximum(100) glayout1 = QGridLayout() glayout1.addWidget(nLabel, 0, 0) glayout1.addWidget(self.nSlider, 0, 1) glayout1.addWidget(sigLabel, 1, 0) glayout1.addWidget(self.sigSlider, 1, 1) glayout1.addWidget(thicLabel, 2, 0) glayout1.addWidget(self.thicSlider, 2, 1) glayout2 = QGridLayout() glayout2.addWidget(resizeLabel, 0, 0) glayout2.addWidget(self.resize_spinbox, 0, 1) glayout2.addWidget(self.zeroModeCheck, 0, 2) glayout2.addWidget(makssizeLabel, 1, 0) glayout2.addWidget(self.double_spin_width, 1, 1) glayout2.addWidget(self.double_spin_height, 1, 2) glayout2.setColumnStretch(3, 1) self.__label.setAlignment(Qt.AlignLeft | Qt.AlignTop) mainlayout = QVBoxLayout() mainlayout.addLayout(glayout1) mainlayout.addLayout(glayout2) mainlayout.addStretch(1) mainlayout.addWidget(self.__label) mainlayout.addStretch(1) mainlayout.setAlignment(Qt.AlignCenter) self.setLayout(mainlayout) self.nSlider.sliderReleased.connect(self.onNsegChange) self.sigSlider.sliderReleased.connect(self.onSigChange) self.thicSlider.sliderReleased.connect(self.onCompChange) self.__label.mousePressEvent = self.Highlight self.resize_spinbox.valueChanged.connect(self.Resize) self.open_image(self.__img) def getBackground(self): mask = self.__thirdChannelMask.copy() mask_r = mask[:, :, 2] mask_g = mask[:, :, 1] mask_b = mask[:, :, 0] offImage = list() for color in self.__AllColors: b_off = mask_b != color[2] g_off = mask_g != color[1] r_off = mask_r != color[0] aux = np.logical_and(b_off, g_off) offImage.append(np.logical_and(aux, r_off)) final = offImage[0] for cut in offImage: final = np.logical_or(final, cut) return final def changeImage(self): self.__mask = slic(self.__img, n_segments=self.__nseg, compactness=self.__comp, sigma=self.__sig, convert2lab=True, slic_zero=self.zeroModeCheck.isChecked()) mask = self.__mask.copy() mask = np.dstack((mask, mask, mask)) mask = img_as_ubyte(mask) self.__thirdChannelMask = mask img = cv2.addWeighted(self.__img, 1, mask, 0.5, 0) marc_img = mark_boundaries(img, self.__mask) self.open_image(marc_img) def load_image(self): self.__img = cv2.imread(self.file) self.original = self.__img self.double_spin_width.setValue(self.__img.shape[1]) self.double_spin_height.setValue(self.__img.shape[0]) val = self.resize_spinbox.value() newDim = int(self.__img.shape[1]*val/100), int(self.__img.shape[0]*val/100) self.__img = cv2.resize(self.__img, newDim) self.open_image(self.__img) def open_image(self, img): if img.shape[2] == 4: qformat = QImage.Format_RGBA8888 else: qformat = QImage.Format_RGB888 copy = img_as_ubyte(img) qimg = QImage(copy.data, copy.shape[1], copy.shape[0], copy.strides[0], qformat).rgbSwapped() pixmap = QPixmap.fromImage(qimg) self.__label.setPixmap(pixmap) self.__label.adjustSize() @Slot() def onNsegChange(self): self.__nseg = self.nSlider.value() self.changeImage() @Slot() def onSigChange(self): self.__sig = self.sigSlider.value() self.changeImage() @Slot() def onCompChange(self): self.__comp = self.thicSlider.value() self.changeImage() @Slot() def onFileOpen(self): self.thicSlider.setValue(1) self.nSlider.setValue(1) self.sigSlider.setValue(1) diag = QFileDialog() file = diag.getOpenFileName()[0] if file != "": self.file = file self.load_image() @Slot() def onSaveFile(self): diag = QFileDialog() file = diag.getSaveFileName()[0] if self.file != "": self.__label.pixmap().save(file) @Slot() def onSaveMask(self): diag = QFileDialog() file = diag.getSaveFileName()[0] final_img = cv2.resize(self.__mask, (self.double_spin_width.value(), self.double_spin_height.value())) if file != "": cv2.imwrite(file, final_img) @Slot() def Highlight(self, e): if e.x() < 0 or e.x() > self.__img.shape[1] or e.y() < 0 or e.y() > self.__img.shape[0]: return self.__mask = flood_fill(self.__mask, (e.y(), e.x()), 255) self.__thirdChannelMask[:, :, 2] = flood_fill(self.__thirdChannelMask[:, :, 2], (e.y(), e.x()), self.__highlightcolor.red()) self.__thirdChannelMask[:, :, 1] = flood_fill(self.__thirdChannelMask[:, :, 1], (e.y(), e.x()), self.__highlightcolor.green()) self.__thirdChannelMask[:, :, 0] = flood_fill(self.__thirdChannelMask[:, :, 0], (e.y(), e.x()), self.__highlightcolor.blue()) img = cv2.addWeighted(self.__img, 1, self.__thirdChannelMask, self.__transparency, 0) marc_img = mark_boundaries(img, self.__mask) self.open_image(marc_img) @Slot() def exportBinary(self): diag = QFileDialog() file = diag.getSaveFileName()[0] mask = self.__thirdChannelMask.copy() final = self.getBackground() b = mask[:, :, 0] g = mask[:, :, 1] r = mask[:, :, 2] b[final] = 0 g[final] = 0 r[final] = 0 final_img = cv2.resize(mask, (int(self.double_spin_width.value()), int(self.double_spin_height.value()))) if file != "": cv2.imwrite(file, final_img) @Slot() def onRemoveBackgroud(self): box = QMessageBox() box.setText("Selecione a cor do background") box.setIcon(QMessageBox.Information) box.exec() diag = QColorDialog() backColor = diag.getColor() final = self.getBackground() b = self.__img[:, :, 0] g = self.__img[:, :, 1] r = self.__img[:, :, 2] b[final] = backColor.blue() g[final] = backColor.green() r[final] = backColor.red() self.open_image(self.__img) @Slot() def Resize(self): val = self.resize_spinbox.value() newDim = int(self.original.shape[1] * val / 100), int(self.original.shape[0] * val / 100) self.__img = cv2.resize(self.original, newDim) self.open_image(self.__img) @Slot() def setHighlightColor(self, color): self.__highlightcolor = color @Slot() def getAllColors(self, colors): self.__AllColors = colors @Slot() def setTran(self, value): self.__transparency = 1- value/100 @Slot() def onUndo(self): self.thicSlider.setValue(1) self.nSlider.setValue(1) self.sigSlider.setValue(1) self.onNsegChange() self.onSigChange() self.onCompChange() self.__img = self.original self.open_image(self.__img)
def getBrush(self, size, opacity, color, hardness, flow, spacing=1.0, jitter=0.0, orientation=0, pattern=None): """ initializes and returns a brush as a dictionary @param size: brush size @type size: int @param opacity: brush opacity, range 0..1 @type opacity: float @param color: @type color: QColor @param hardness: brush hardness, range 0..1 @type hardness: float @param flow: brush flow, range 0..1 @type flow: float @return: @rtype: dict """ s = float(self.baseSize) / 2 # set brush color if self.name == 'eraser': color = QColor(0, 0, 0, 0) else: op_max = 255 # 64 color = QColor(color.red(), color.green(), color.blue(), int(op_max * flow)) gradient = QRadialGradient(QPointF(s, s), s) gradient.setColorAt(0, color) gradient.setColorAt(hardness, color) if hardness < 1.0: # fade action to 0, starting from hardness to 1 if self.name == 'eraser': gradient.setColorAt(1, QColor(0, 0, 0, 255)) else: gradient.setColorAt(1, QColor(0, 0, 0, 0)) pxmp = self.basePixmap.copy() qp = QPainter(pxmp) # fill brush contour with gradient (pxmp color is (0,0,0,0) # outside of contourPath) qp.setCompositionMode(qp.CompositionMode_Source) qp.fillPath(self.contourPath, QBrush(gradient)) if self.preset is not None: ################################################ # we adjust the preset pixmap to pxmp size while keeping # its aspect ratio and we center it into pxmp ################################################ w, h = self.preset.width(), self.preset.height() # get the bounding rect of the scaled and centered preset # and the 2 complementary rects if w > h: rh = int(self.baseSize * h / w) # height of bounding rect m = int((self.baseSize - rh) / 2.0) # top and bottom margins r = QRect(0, m, self.baseSize, rh) r1 = QRect(0, 0, self.baseSize, m) r2 = QRect(0, rh + m, self.baseSize, m) else: rw = int(self.baseSize * w / h) # width of bounding rect m = int((self.baseSize - rw) / 2.0) # left and right margins r = QRect(m, 0, rw, self.baseSize) r1 = QRect(0, 0, m, self.baseSize) r2 = QRect(rw + m, 0, m, self.baseSize) # set opacity of r to that of preset qp.setCompositionMode(QPainter.CompositionMode_DestinationIn) qp.drawPixmap(r, self.preset) # paint the outside of r with transparent color pxmp1 = QPixmap(pxmp.size()) pxmp1.fill(QColor(0, 0, 0, 0)) qp.drawPixmap(r1, pxmp1) qp.drawPixmap(r2, pxmp1) qp.end() s = size / self.baseSize self.pxmp = pxmp.transformed(QTransform().scale( s, s).rotate(orientation)) # pxmp.scaled(size, size) pattern = pattern return { 'family': self, 'name': self.name, 'pixmap': self.pxmp, 'size': size, 'color': color, 'opacity': opacity, 'hardness': hardness, 'flow': flow, 'spacing': spacing, 'jitter': jitter, 'orientation': orientation, 'pattern': pattern, 'cursor': self.baseCursor }
def drawMagnifier(self): # First, calculate the magnifier position due to the mouse position watch_area_width = 16 watch_area_height = 16 cursor_pos = self.mousePoint watch_area = QRect( QPoint(cursor_pos.x() - watch_area_width / 2, cursor_pos.y() - watch_area_height / 2), QPoint(cursor_pos.x() + watch_area_width / 2, cursor_pos.y() + watch_area_height / 2)) if watch_area.left() < 0: watch_area.moveLeft(0) watch_area.moveRight(watch_area_width) if self.mousePoint.x( ) + watch_area_width / 2 >= self.screenPixel.width(): watch_area.moveRight(self.screenPixel.width() - 1) watch_area.moveLeft(watch_area.right() - watch_area_width) if self.mousePoint.y() - watch_area_height / 2 < 0: watch_area.moveTop(0) watch_area.moveBottom(watch_area_height) if self.mousePoint.y( ) + watch_area_height / 2 >= self.screenPixel.height(): watch_area.moveBottom(self.screenPixel.height() - 1) watch_area.moveTop(watch_area.bottom() - watch_area_height) # tricks to solve the hidpi impact on QCursor.pos() watch_area.setTopLeft( QPoint(watch_area.topLeft().x() * self.scale, watch_area.topLeft().y() * self.scale)) watch_area.setBottomRight( QPoint(watch_area.bottomRight().x() * self.scale, watch_area.bottomRight().y() * self.scale)) watch_area_pixmap = self.screenPixel.copy(watch_area) # second, calculate the magnifier area magnifier_area_width = watch_area_width * 10 magnifier_area_height = watch_area_height * 10 font_area_height = 40 cursor_size = 24 magnifier_area = QRectF( QPoint(QCursor.pos().x() + cursor_size, QCursor.pos().y() + cursor_size), QPoint(QCursor.pos().x() + cursor_size + magnifier_area_width, QCursor.pos().y() + cursor_size + magnifier_area_height)) if magnifier_area.right() >= self.screenPixel.width(): magnifier_area.moveLeft(QCursor.pos().x() - magnifier_area_width - cursor_size / 2) if magnifier_area.bottom( ) + font_area_height >= self.screenPixel.height(): magnifier_area.moveTop(QCursor.pos().y() - magnifier_area_height - cursor_size / 2 - font_area_height) # third, draw the watch area to magnifier area watch_area_scaled = watch_area_pixmap.scaled( QSize(magnifier_area_width * self.scale, magnifier_area_height * self.scale)) magnifier_pixmap = self.graphics_scene.addPixmap(watch_area_scaled) magnifier_pixmap.setOffset(magnifier_area.topLeft()) # then draw lines and text self.graphics_scene.addRect(QRectF(magnifier_area), QPen(QColor(255, 255, 255), 2)) self.graphics_scene.addLine( QLineF( QPointF(magnifier_area.center().x(), magnifier_area.top()), QPointF(magnifier_area.center().x(), magnifier_area.bottom())), QPen(QColor(0, 255, 255), 2)) self.graphics_scene.addLine( QLineF( QPointF(magnifier_area.left(), magnifier_area.center().y()), QPointF(magnifier_area.right(), magnifier_area.center().y())), QPen(QColor(0, 255, 255), 2)) # get the rgb of mouse point point_rgb = QColor(self.screenPixel.toImage().pixel(self.mousePoint)) # draw information self.graphics_scene.addRect( QRectF( magnifier_area.bottomLeft(), magnifier_area.bottomRight() + QPoint(0, font_area_height + 30)), QPen(Qt.black), QBrush(Qt.black)) rgb_info = self.graphics_scene.addSimpleText( ' Rgb: ({0}, {1}, {2})'.format(point_rgb.red(), point_rgb.green(), point_rgb.blue())) rgb_info.setPos(magnifier_area.bottomLeft() + QPoint(0, 5)) rgb_info.setPen(QPen(QColor(255, 255, 255), 2)) rect = self.selected_area.normalized() size_info = self.graphics_scene.addSimpleText( ' Size: {0} x {1}'.format(rect.width() * self.scale, rect.height() * self.scale)) size_info.setPos(magnifier_area.bottomLeft() + QPoint(0, 15) + QPoint(0, font_area_height / 2)) size_info.setPen(QPen(QColor(255, 255, 255), 2))
def interpolate(start: QColor, end: QColor, ratio: float) -> QColor: """Interpolate between two colors""" r = int(ratio * start.red() + (1 - ratio) * end.red()) g = int(ratio * start.green() + (1 - ratio) * end.green()) b = int(ratio * start.blue() + (1 - ratio) * end.blue()) return QColor.fromRgb(r, g, b)
def drawForeground(self, painter, rect): """Draws all connections and borders around selected items.""" # DRAW CONNECTIONS for ni in self.all_node_instances: for o in ni.outputs: for cpi in o.connected_port_instances: path = self.connection_path( o.gate.get_scene_center_pos(), cpi.gate.get_scene_center_pos()) w = path.boundingRect().width() h = path.boundingRect().height() gradient = QRadialGradient(path.boundingRect().center(), pythagoras(w, h) / 2) pen = Design.flow_theme.get_flow_conn_pen_inst(o.type_) c = pen.color() # highlight hovered connections if self.hovered_port_inst_gate == o.gate or self.hovered_port_inst_gate is cpi.gate: c = QColor('#c5c5c5') pen.setWidth(5) c_r = c.red() c_g = c.green() c_b = c.blue() gradient.setColorAt(0.0, QColor(c_r, c_g, c_b, 255)) gradient.setColorAt(0.75, QColor(c_r, c_g, c_b, 200)) gradient.setColorAt(0.95, QColor(c_r, c_g, c_b, 0)) gradient.setColorAt(1.0, QColor(c_r, c_g, c_b, 0)) pen.setBrush(gradient) painter.setPen(pen) painter.drawPath(path) # DRAW CURRENTLY DRAGGED CONNECTION if self.dragging_connection: pen = QPen('#101520') pen.setWidth(3) pen.setStyle(Qt.DotLine) painter.setPen(pen) gate_pos = self.gate_selected.get_scene_center_pos() if self.gate_selected.parent_port_instance.direction == 'output': painter.drawPath( self.connection_path(gate_pos, self.last_mouse_move_pos)) else: painter.drawPath( self.connection_path(self.last_mouse_move_pos, gate_pos)) # DRAW SELECTED NIs BORDER for ni in self.selected_node_instances(): pen = QPen(QColor('#245d75')) pen.setWidth(3) painter.setPen(pen) painter.setBrush(Qt.NoBrush) size_factor = 1.2 x = ni.pos().x() - ni.boundingRect().width() / 2 * size_factor y = ni.pos().y() - ni.boundingRect().height() / 2 * size_factor w = ni.boundingRect().width() * size_factor h = ni.boundingRect().height() * size_factor painter.drawRoundedRect(x, y, w, h, 10, 10) # DRAW SELECTED DRAWINGS BORDER for p_o in self.selected_drawings(): pen = QPen(QColor('#a3cc3b')) pen.setWidth(2) painter.setPen(pen) painter.setBrush(Qt.NoBrush) size_factor = 1.05 x = p_o.pos().x() - p_o.width / 2 * size_factor y = p_o.pos().y() - p_o.height / 2 * size_factor w = p_o.width * size_factor h = p_o.height * size_factor painter.drawRoundedRect(x, y, w, h, 6, 6) painter.drawEllipse(p_o.pos().x(), p_o.pos().y(), 2, 2)
class ButtonIcon(QPushButton): def __init__(self, label=None, icon="", iconsize=40, inactive=(255, 255, 255), active=(255, 0, 0), duration=300): super(ButtonIcon, self).__init__() self.activeColor = QColor(active[0], active[1], active[2]) self.inactiveColor = QColor(inactive[0], inactive[1], inactive[2]) self.animDuration = duration self.iconResolution = iconsize self.setStyleSheet("background-color : transparent;") self.setFixedSize(self.iconResolution + 5, self.iconResolution + 5) self.setCursor(QCursor(Qt.PointingHandCursor)) self.changeIcon(icon) if hasattr(self, "px_mask"): self.px.fill(self.inactiveColor) self.px.setMask(self.px_mask) self.setIcon(QIcon(self.px)) self.setIconSize(QSize(self.iconResolution, self.iconResolution)) if isinstance(label, str): font = self.font() font.setPointSize(self.iconResolution / 10) self.setFont(font) self.setText(label) if self.px: self.setColor(self.inactiveColor) self.hoverAnimation = self.animate(self.inactiveColor, self.activeColor, self.animDuration, self.animationCallback) self.leaveAnimation = self.animate(self.activeColor, self.inactiveColor, self.animDuration, self.animationCallback) def setHeight(self, value): self.setFixedHeight(value) self.setFixedWidth(value) def getHeight(self): return self.height() Height = Property(int, getHeight, setHeight) def changeIcon(self, path): self.iconPath = path if os.path.isfile(self.iconPath): self.px = QPixmap(self.iconPath) self.px.scaled(self.iconResolution, self.iconResolution, Qt.KeepAspectRatio, Qt.SmoothTransformation) self.px_mask = self.px.createMaskFromColor(QColor('transparent')) self.event(QEvent(QEvent.Type.MouseButtonRelease)) self.update() def setColor(self, value): self.__color = value self.px.fill(self.__color) self.px.setMask(self.px_mask) self.setIcon(QIcon(self.px)) def getColor(self): return self.__color color = Property(QColor, getColor, setColor) def animationCallback(self, state): if state == QAbstractAnimation.State.Stopped: self.hoverAnimation = self.animate(self.inactiveColor, self.activeColor, self.animDuration, self.animationCallback) self.leaveAnimation = self.animate(self.activeColor, self.inactiveColor, self.animDuration, self.animationCallback) def animate(self, start, end, duration, callback): ani = QPropertyAnimation(self, b"color") ani.setStartValue(start) ani.setEndValue(end) ani.setDuration(duration) ani.stateChanged.connect(callback) return ani def event(self, event): if event.type() == QEvent.Type.Enter: if self.leaveAnimation.state() == QAbstractAnimation.State.Running: self.leaveAnimation.stop() current = sum([ self.getColor().redF(), self.getColor().greenF(), self.getColor().blueF() ]) target = sum([ self.activeColor.redF(), self.activeColor.greenF(), self.activeColor.blueF() ]) self.hoverAnimation = self.animate( self.getColor(), self.activeColor, max(target - current, 0) * self.animDuration, self.animationCallback) self.hoverAnimation.start() elif event.type() == QEvent.Type.Leave: if self.hoverAnimation.state() == QAbstractAnimation.State.Running: self.hoverAnimation.stop() current = max([ self.getColor().redF(), self.getColor().greenF(), self.getColor().blueF() ]) target = max([ self.inactiveColor.redF(), self.inactiveColor.greenF(), self.inactiveColor.blueF() ]) self.leaveAnimation = self.animate( self.getColor(), self.inactiveColor, max(current - target, 0) * self.animDuration, self.animationCallback) self.leaveAnimation.start() elif event.type() in [ QEvent.Type.MouseButtonPress, QEvent.Type.MouseButtonDblClick ]: pressColor = QColor( (self.inactiveColor.red() + self.activeColor.red()) / 2, (self.inactiveColor.green() + self.activeColor.green()) / 2, (self.inactiveColor.blue() + self.activeColor.blue()) / 2) self.px.fill(pressColor) self.px.setMask(self.px_mask) self.setIcon(QIcon(self.px)) elif event.type() == QEvent.Type.MouseButtonRelease: self.px.fill(self.activeColor) self.px.setMask(self.px_mask) self.setIcon(QIcon(self.px)) return super(ButtonIcon, self).event(event)
def color(self, value: QColor): self.color_array = np.array( [value.red(), value.green(), value.blue(), value.alpha()])
class OptionsAWidget(QWidget): def __init__(self, label_width=64, status_bar=None): super(OptionsAWidget, self).__init__() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.status_bar = status_bar self.margin = 50 self.align = 0 self.background = QColor(255, 255, 255) margin_param = ParameterInteger( self, value=self.margin, max_visible=128, min_value=0, name="margin", label_text="Margin", label_width=label_width, change_callback=self.chenge_value_callback) align_param = ParameterCombobox( self, value=0, items=[ "Center", "Center-Top", "Center-Bottom", "Left-Top", "Left-Center", "Left-Bottom", "Right-Top", "Right-Center", "Right-Bottom" ], name="align", label_text="Align", label_width=label_width, change_callback=self.chenge_value_callback) back_color = ParameterColor(self, value=self.background, name="background", label_text="Background", label_width=label_width, change_callback=self.chenge_value_callback) layout.addWidget(margin_param) layout.addWidget(align_param) layout.addWidget(back_color) self.setLayout(layout) def chenge_value_callback(self, param_name="", param_value=None): if param_name == "margin": self.margin = param_value if self.status_bar is not None: self.status_bar.showMessage("Set margin to " + str(self.margin) + " units") elif param_name == "align": self.align = param_value[0] if self.status_bar is not None: self.status_bar.showMessage("Set align to " + str(param_value[1][self.align])) elif param_name == "background": self.background = param_value if self.status_bar is not None: self.status_bar.showMessage("Set background color to RGB(" + ", ".join([ str(self.background.red()), str(self.background.green()), str(self.background.blue()) ]) + ")") def get_margin_value(self): return self.margin def get_align_value(self): return self.align def get_background_value(self): return (self.background.red(), self.background.green(), self.background.blue())
class WLight(QtWidgets.QWidget): def __init__(self, parent, off, onColor, name, index, sound_file): super(WLight, self).__init__(parent) ulx_list = [0.11, 0.56] ulx = ulx_list[index] width_proportion = 1 / 3. wh_ratio = 3 # width = 2 * height self.lightWidth = width_proportion * self.parent().width() self.lightHeight = self.lightWidth / wh_ratio font = QtGui.QFont("sans-serif", self.lightWidth / 13., QtGui.QFont.Bold) self.light = QtWidgets.QLabel(self) self.light.setLineWidth(self.lightWidth / 37.) self.off = off self.id = index self.light.setText("<b>%s</b>" % name) self.light.setFont(font) self.onColor = onColor self.ulx = ulx * self.parent().width() self.uly = 0.05 * self.parent().height() # ~ self.feedback = 0 # Useless yet self.light.setGeometry(self.ulx, self.uly, self.lightWidth, self.lightHeight) self.light.setAlignment(QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter) # audio part self.sound_file = sound_file self.color = QColor(self.onColor) self.count = 0 self.duration = 1000 self.rate = 20 self.sound = QSoundEffect() self.setSound(self.sound_file) self.timer = QTimer() self.timer.timeout.connect(self.update_anim) self.mode = "sin" #print('devices',QAudioDeviceInfo.availableDevices()) def setSound(self, sound_file): self.sound.setSource(QUrl.fromLocalFile(sound_file)) self.sound.setLoopCount(QSoundEffect.Infinite) def start(self): #print('starting sound?', self.sound.status()) if not self.sound.isPlaying(): self.count = 0 self.sound.play() self.timer.start(self.rate) def stop(self): self.timer.stop() self.sound.stop() def update_color_with_alha(self, alpha): red = self.color.red() green = self.color.green() blue = self.color.blue() bg_style = f"rgba({red},{green},{blue}, {alpha})" self.light.setStyleSheet("QLabel { background-color: " + bg_style + "; color: black}") def update_anim(self): # logarithmic (check with perception of luminosity/brighness) # val = math.log(count + 1) # linear if self.mode == "sin": val = math.sin(self.count * 2 * math.pi) / 2 + 0.5 elif self.mode == "lin": val = 1 - self.count else: val = math.log(self.count + 1) alpha = round(val * 100) + 155 self.update_color_with_alha(alpha) amplitude = val * 0.8 + 0.2 self.sound.setVolume(amplitude) self.count = self.count + self.rate / self.duration # print(count) if self.count >= 1 - self.rate / self.duration: self.count = 0 def refreshState(self, on): if on: bg = self.onColor self.start() self.light.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Raised) else: bg = "" self.light.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken) self.stop() self.light.setStyleSheet("QLabel { background-color: " + bg + "; color: black}")