def merged_colors(colorA, colorB, factor): maxFactor = 100 colorA = QColor(colorA) colorB = QColor(colorB) tmp = colorA tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor) tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor) tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor) return tmp
def __init__(self, linelist, parent=None, *args): QAbstractTableModel.__init__(self, parent, *args) self._linelist = linelist #TODO move entire table contents to an array of QVector # instances that will store the columns. This should # speed up the sorting (as far as some indications in # the net suggest: # http://www.qtforum.org/article/30638/qsortfilterproxymodel-qtreeview-sort-performance.html). # Bummer... this is C++ only; PyQt never went to the trouble # of converting QVector it to python. # # get rid entirely of astropy table and store its contents in # a 2-D list of lists. By using python lists instead of an # astropy table, and storing the QVariant instances instead # of the raw content, we can speed up sorting by a factor > 10X. # we have to do this here because some lists may # have no lines at all. self._nrows = 0 self._ncols = 0 self._row_cells = [] for row in self._linelist: cells = [] for rindex in range(len(row)): cell = row[rindex] # handling of a color object can be tricky. Color names # returned by QColor.colorNames() are inconsistent with # color names in Qt.GlobalColor. We just go to the basics # and compare color equality (or closeness) using a distance # criterion in r,g,b coordinates. # Although costly, this would be a CPU burden only when # sorting columns with color information. For now, only # the Plotted Lines line list has such information, and # the number of actually plotted lines tends to be small # anyway. if isinstance(cell, QColor): r = cell.red() g = cell.green() b = cell.blue() min_dist = 100000 result = cell for color_name, orig_color in ID_COLORS.items(): orig_rgb = QColor(orig_color) dist = abs(orig_rgb.red() - r) + abs(orig_rgb.green() - g) + abs(orig_rgb.blue() - b) if dist < min_dist: min_dist = dist result = orig_color key = [ k for k, value in ID_COLORS.items() if value == result ][0] cells.append(QVariant(key)) else: cells.append(QVariant(str(cell))) self._row_cells.append(cells) self._nrows = len(self._row_cells) self._ncols = len(self._row_cells[0])
def __init__(self, linelist, parent=None, *args): QAbstractTableModel.__init__(self, parent, *args) self._linelist = linelist #TODO move entire table contents to an array of QVector # instances that will store the columns. This should # speed up the sorting (as far as some indications in # the net suggest: # http://www.qtforum.org/article/30638/qsortfilterproxymodel-qtreeview-sort-performance.html). # Bummer... this is C++ only; PyQt never went to the trouble # of converting QVector to python. # # get rid entirely of astropy table and store its contents in # a 2-D list of lists. By using python lists instead of an # astropy table, and storing the QVariant instances instead # of the raw content, we can speed up sorting by a factor > 10X. # we have to do this here because some lists may # have no lines at all. self._nrows = 0 self._ncols = 0 self._row_cells = [] for row in self._linelist: cells = [] for rindex in range(len(row)): cell = row[rindex] # handling of a color object can be tricky. Color names # returned by QColor.colorNames() are inconsistent with # color names in Qt.GlobalColor. We just go to the basics # and compare color equality (or closeness) using a distance # criterion in r,g,b coordinates. # Although costly, this would be a CPU burden only when # sorting columns with color information. For now, only # the Plotted Lines line list has such information, and # the number of actually plotted lines tends to be small # anyway. if isinstance(cell, QColor): r = cell.red() g = cell.green() b = cell.blue() min_dist = 100000 result = cell for color_name, orig_color in ID_COLORS.items(): orig_rgb = QColor(orig_color) dist = abs(orig_rgb.red() - r) + abs(orig_rgb.green() - g) + abs(orig_rgb.blue() - b) if dist < min_dist: min_dist = dist result = orig_color key = [k for k,value in ID_COLORS.items() if value == result][0] cells.append(QVariant(key)) else: cells.append(QVariant(str(cell))) self._row_cells.append(cells) self._nrows = len(self._row_cells) self._ncols = len(self._row_cells[0])
class PSpinBox(QFrame): valueChanged = Signal(int) def __init__(self, parent=None): super().__init__(parent) self.minimum = 0 self.maximum = 100 self.parent = parent self.value = 0 self.singleStep = 1 self.hover = False self.border_radius = 8 self.rate = 0.25 self.up_arrow_poly = QPolygon() self.down_arrow_poly = QPolygon() self.back_color = QColor(108, 108, 115) self.text_color = QColor(255, 255, 255) self.arrow_activate_color = QColor(255, 255, 255) self.arrow_deactivate_color = QColor(200, 200, 200) self.up_arrow_color = self.arrow_deactivate_color self.down_arrow_color = self.arrow_deactivate_color self.label_width = 0 self.drop_thick = 1.5 self.setMinimumHeight(25) self.setMinimumWidth(50) self.setMouseTracking(True) self.lineEdit = PLineEdit(self) self.validator = QIntValidator(self.minimum, self.maximum) self.init_ui() def init_ui(self): self.setObjectName("PSpinBox") self.setStyleSheet( f"#PSpinBox {{background: rgba({self.back_color.red()}, {self.back_color.green()}, {self.back_color.blue()}, 255); " f"border-radius: {self.border_radius}; color: rgb({self.text_color.red()}, {self.text_color.green()}, {self.text_color.blue()});}}" ) self.lineEdit.setValidator(self.validator) self.lineEdit.setText("0") self.lineEdit.textChanged.connect(self.set_value) self.lineEdit.focusOut.connect(self.set_last_value) self.set_font(QFont("Arial", 14)) self.setFocusProxy(self.lineEdit) def set_single_step(self, step): self.singleStep = step def set_back_color(self, color): self.back_color = color self.update() self.lineEdit.set_back_color(color) def set_text_color(self, color): self.text_color = color self.lineEdit.set_text_color(color) def set_arrow_deactivate_color(self, color): self.up_arrow_color = color self.down_arrow_color = color def set_arrow_color(self, act_color, deact_color): self.arrow_activate_color = act_color self.arrow_deactivate_color = deact_color def set_border_radius(self, rad): self.border_radius = rad def get_maximum(self): return self.maximum def get_minimum(self): return self.minimum def set_maximum(self, maxval): self.maximum = maxval if self.value > maxval: self.set_text(maxval) def set_minimum(self, minval): self.minimum = minval if self.value < minval: self.set_text(minval) def set_range(self, minval, maxval): self.set_minimum(minval) self.set_maximum(maxval) self.validator = QIntValidator(self.minimum, self.maximum) self.lineEdit.setValidator(self.validator) def single_step(self): return self.singleStep def get_value(self): return self.value def set_last_value(self): self.lineEdit.setText(str(self.value)) def set_text(self, val): self.lineEdit.setText(str(val)) def set_value(self, val): if val == "" or val == "+" or int(val) < self.minimum or int( val) > self.maximum: return if self.value == int(val): return self.value = int(val) self.valueChanged.emit(int(self.value)) def set_font(self, font): self.lineEdit.setFont(font) def set_text_alignment(self, align): self.lineEdit.setAlignment(align) def keyPressEvent(self, event): if event.key() == Qt.Key_Up: self.increase() if event.key() == Qt.Key_Down: self.decrease() def wheelEvent(self, event): if event.angleDelta().y() > 0: self.increase() else: self.decrease() def mouseMoveEvent(self, event): tmp_color = self.up_arrow_color if self.up_arrow_poly.containsPoint(event.pos(), Qt.OddEvenFill): self.setCursor(Qt.PointingHandCursor) self.up_arrow_color = self.arrow_activate_color else: self.setCursor(Qt.ArrowCursor) self.up_arrow_color = self.arrow_deactivate_color if self.up_arrow_color != tmp_color: self.update() return tmp_color = self.down_arrow_color if self.down_arrow_poly.containsPoint(event.pos(), Qt.OddEvenFill): self.setCursor(Qt.PointingHandCursor) self.down_arrow_color = self.arrow_activate_color else: self.down_arrow_color = self.arrow_deactivate_color if self.down_arrow_color != tmp_color: self.update() def increase(self): if self.value + self.singleStep <= self.maximum: self.lineEdit.setText(str(self.value + self.singleStep)) else: self.lineEdit.setText(str(self.maximum)) self.lineEdit.selectAll() self.lineEdit.setFocus() def decrease(self): if self.value - self.singleStep >= self.minimum: self.lineEdit.setText(str(self.value - self.singleStep)) else: self.lineEdit.setText(str(self.minimum)) self.lineEdit.selectAll() self.lineEdit.setFocus() def mousePressEvent(self, event): if self.up_arrow_poly.containsPoint(event.pos(), Qt.OddEvenFill): self.increase() if self.down_arrow_poly.containsPoint(event.pos(), Qt.OddEvenFill): self.decrease() def enterEvent(self, event): self.hover = True self.update() def leaveEvent(self, event): self.hover = False self.update() def resizeEvent(self, event): self.label_width = self.width( ) - self.height() * self.rate - self.height() * 2 / 3 self.lineEdit.setGeometry(self.border_radius, 0, self.label_width - self.border_radius, self.height()) self.set_border_radius(self.height() / 4) def paintEvent(self, event): painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.setPen(Qt.NoPen) if self.hover: painter.setBrush( QColor(self.back_color.red() + 30, self.back_color.green() + 30, self.back_color.blue() + 30)) self.lineEdit.set_back_color( QColor(self.back_color.red() + 30, self.back_color.green() + 30, self.back_color.blue() + 30)) else: painter.setBrush(self.back_color) self.lineEdit.set_back_color(self.back_color) painter.drawRoundedRect(QRect(0, 0, self.width(), self.height()), self.border_radius, self.border_radius) pen = QPen(self.down_arrow_color, self.drop_thick, Qt.SolidLine) painter.setPen(pen) self.down_arrow_poly = QPolygon() x1 = QPoint(self.label_width + float(self.height() / 3), float(self.height() * 0.6)) x2 = QPoint( self.label_width + float(self.height() / 3) + float(self.height() * self.rate / 2), float(self.height() * 0.75)) x3 = QPoint(self.width() - float(self.height() / 3), float(self.height() * 0.6)) self.down_arrow_poly << x1 << x2 << x3 check_path = QPainterPath() check_path.moveTo(x1) check_path.lineTo(x2) check_path.lineTo(x3) check_path.lineTo(x1) painter.drawPath(check_path) if self.down_arrow_color == self.arrow_activate_color: painter.fillPath(check_path, QBrush(self.down_arrow_color)) else: if self.hover: painter.fillPath( check_path, QColor(self.back_color.red() + 30, self.back_color.green() + 30, self.back_color.blue() + 30)) else: painter.fillPath(check_path, QBrush(self.back_color)) pen = QPen(self.up_arrow_color, self.drop_thick, Qt.SolidLine) painter.setPen(pen) x1 = QPoint(self.label_width + float(self.height() / 3), float(self.height() * 0.4)) x2 = QPoint( self.label_width + float(self.height() / 3) + float(self.height() * self.rate / 2), float(self.height() * 0.25)) x3 = QPoint(self.width() - float(self.height() / 3), float(self.height() * 0.4)) self.up_arrow_poly = QPolygon() self.up_arrow_poly << x1 << x2 << x3 check_path = QPainterPath() check_path.moveTo(x1) check_path.lineTo(x2) check_path.lineTo(x3) check_path.lineTo(x1) painter.drawPath(check_path) if self.up_arrow_color == self.arrow_activate_color: painter.fillPath(check_path, QBrush(self.up_arrow_color)) else: if self.hover: painter.fillPath( check_path, QColor(self.back_color.red() + 30, self.back_color.green() + 30, self.back_color.blue() + 30)) else: painter.fillPath(check_path, QBrush(self.back_color))
def color_from_qcolor(color: QColor) -> Color: """Convert :py:class:`PyQt5.QtGui.QColor` to :py:class:`.Color`""" return Color(color.red() / 255, color.green() / 255, color.blue() / 255, color.alpha() / 255)
def on_color_picker_color_changed(color: QColor): for channel in self._controller.selected_channels: channel.color = (color.red() / 255, color.green() / 255, color.blue() / 255, color.alpha() / 255)
class PCheck(QFrame): stateChanged = Signal(bool) x1 = QPoint(6, 16) x2 = QPoint(14, 24) x3 = QPoint(24, 9) def __init__(self, parent=None): super().__init__(parent) self.is_checked = False self.is_pressed = False self.border_radius = 0 self.check_thick = 2 self.back_color = QColor(108, 108, 115) self.check_color = QColor(255, 255, 255) def resizeEvent(self, event): self.border_radius = self.height() / 4 self.update() def mousePressEvent(self, event): QFrame.mousePressEvent(self, event) self.is_pressed = True self.update() def mouseReleaseEvent(self, event): QFrame.mouseReleaseEvent(self, event) if self.is_pressed: self.is_checked = not self.is_checked self.stateChanged.emit(self.is_checked) self.is_pressed = False self.update() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) side = min(self.width(), self.height()) painter.scale(side / 32.0, side / 32.0) painter.setPen(Qt.NoPen) if not self.is_pressed: painter.setBrush(self.back_color) else: painter.setBrush( QColor(self.back_color.red() + 30, self.back_color.green() + 30, self.back_color.blue() + 30)) painter.drawRoundedRect(QRect(0, 0, 32, 32), 8, 8) if self.is_checked: check_path = QPainterPath() check_path.moveTo(self.x1) check_path.lineTo(self.x2) check_path.lineTo(self.x3) pen = QPen(self.check_color, self.check_thick, Qt.SolidLine) painter.setPen(pen) painter.drawPath(check_path)
class PComboBox(QFrame): """ Customized combo box """ currentChanged = Signal(str) def __init__(self, parent): super().__init__(parent) self.rate = 0.25 self.back_color = QColor(108, 108, 115) self.text_color = QColor(255, 255, 255) self.hover = False self.label_width = 0 self.drop_thick = 1.5 self.border_radius = 8 self.parent = parent self.popup_height = 0 self.setObjectName("PComboBox") self.setCursor(Qt.PointingHandCursor) self.setMinimumHeight(25) self.setMinimumWidth(50) self.init_ui() def init_ui(self): self.textFrame = QFrame(self) self.hTextLayout = QHBoxLayout(self.textFrame) self.hTextLayout.setContentsMargins(10, 0, 10, 0) self.hTextLayout.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) self.label = ElideLabel(self.textFrame) self.hTextLayout.addWidget(self.label) self.popupFrame = QFrame(self.parent) self.popupFrame.setObjectName("PComboBoxPopup") self.lsWidget = PListWidget(self.parent) self.hPopuplayout = QHBoxLayout(self.popupFrame) self.hPopuplayout.setContentsMargins(0, 0, 0, 0) self.hPopuplayout.addWidget(self.lsWidget) self.popupFrame.hide() self.lsWidget.currentTextChanged.connect(self.set_current_text) self.lsWidget.itemClicked.connect(self.hide_popup) self.lsWidget.focusOut.connect(self.hide_popup) self.setFocusProxy(self.lsWidget) self.set_font(QFont("Arial", 14)) self.set_border_radius(self.border_radius) def set_border_radius(self, radius): self.border_radius = radius self.lsWidget.set_border_radius(radius) self.update_style() def set_background_color(self, color): self.back_color = color self.lsWidget.set_back_color(color) self.update_style() def set_text_color(self, color): self.text_color = color self.lsWidget.set_text_color(color) self.update_style() def update_style(self): self.setStyleSheet( f"#PComboBox {{border-radius: {self.border_radius}; " f"color: rgb({self.text_color.red()}, {self.text_color.green()}, {self.text_color.blue()});}}" ) self.label.setStyleSheet( f"QLabel {{color: rgb({self.text_color.red()}, {self.text_color.green()}, {self.text_color.blue()})}}" ) self.popupFrame.setStyleSheet( f"#PComboBoxPopup {{background: rgb({self.back_color.red()}, {self.back_color.green()}, {self.back_color.blue()}); " f"border-radius: {self.border_radius}; " f"color: rgb({self.text_color.red()}, {self.text_color.green()}, {self.text_color.blue()});}}" ) def set_popup_height(self, height): self.popup_height = height def add_items(self, texts): self.lsWidget.addItems(texts) if self.lsWidget.count() > 0: self.lsWidget.setCurrentRow(0) def clear(self): self.lsWidget.clear() self.label.setText("") def set_current_index(self, row): self.lsWidget.setCurrentRow(row) def count(self): return self.lsWidget.count() def current_index(self): return self.lsWidget.currentRow() def set_current_text(self, text): self.hide_popup() if self.label.text() != text: self.label.setText(text) self.currentChanged.emit(text) def set_font(self, font): self.label.setFont(font) self.lsWidget.setFont(font) def current_text(self): return self.label.text() def show_popup(self): return def hide_popup(self): self.popupFrame.hide() def set_text_alignment(self, align): self.hTextLayout.setAlignment(align) def find_text(self, text, flags): items = self.lsWidget.findItems(text, flags) if len(items) == 0: return -1 else: return self.lsWidget.row(items[0]) def enterEvent(self, event): self.hover = True self.update() def leaveEvent(self, event): self.hover = False self.update() def resizeEvent(self, event): self.label_width = self.width() - float( self.height() * self.rate) - float(self.height() * 2 / 3) self.textFrame.setGeometry(0, 0, self.label_width, self.height()) self.popupFrame.setGeometry( self.mapToParent(QPoint(0, 0)).x(), self.mapToParent(QPoint(0, 0)).y() + self.height(), self.width(), 150) self.set_border_radius(self.height() / 4) def mousePressEvent(self, event): if not self.popupFrame.isHidden(): self.hide_popup() return if self.popup_height == 0: self.popupFrame.setFixedHeight( (self.lsWidget.fontMetrics().height() + 2) * self.lsWidget.count()) else: self.popupFrame.setFixedHeight(self.popup_height) self.lsWidget.setFocus() self.popupFrame.raise_() self.popupFrame.show() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) if self.label_width <= 0: return painter.setPen(Qt.NoPen) if self.hover: painter.setBrush( QColor(self.back_color.red() + 30, self.back_color.green() + 30, self.back_color.blue() + 30)) else: painter.setBrush(self.back_color) painter.drawRoundedRect(QRect(0, 0, self.width(), self.height()), self.border_radius, self.border_radius) x1 = QPointF(self.label_width + float(self.height() / 3), float(self.height() * 0.45)) x2 = QPointF( self.label_width + float(self.height() * (0.66 + self.rate) / 2), float(self.height() * 0.55)) x3 = QPointF(self.width() - float(self.height() / 3), float(self.height() * 0.45)) check_path = QPainterPath() check_path.moveTo(x1) check_path.lineTo(x2) check_path.lineTo(x3) pen = QPen(self.text_color, self.drop_thick, Qt.SolidLine) painter.setPen(pen) painter.drawPath(check_path)
class PCard(QFrame): def __init__(self, parent=None): super().__init__(parent) self.setObjectName("PCard") self.border_radius = 8 self.text_color = QColor(255, 255, 255) self.lighttext_color = QColor(self.text_color.red() - 30, self.text_color.green() - 30, self.text_color.blue() - 30) self.back_color = QColor(108, 108, 115) self.title = "30 Barry Rise, Bowdon, Altrincham, Greater Manchester" self.homename = "Park_Home" self.rooms = "5" self.fontSize = 11 self.font = QFont("Roboto", self.fontSize) self.posteddate = "12/10/19" self.price = "$20, 000 pcm" self.description = "Superb opportunity to purchase this bright and spacious two bedroom flat occupying the two bedroom flat occupying the " self.pictures = [ 'image1.jpg', 'image2.jpg', 'image1.jpg', 'image2.jpg' ] self.init_ui() self.set_style() def init_ui(self): self.pic_label = QLabel(self) self.pic_label.setObjectName("PCardPicture") self.pic_label.setAutoFillBackground(True) self.pic_label.setScaledContents(True) self.pic_label.setPixmap(QPixmap(self.pictures[0])) self.title_label = ElideLabel(self) self.title_label.setObjectName("PCardTitle") self.title_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.title_label.setText(self.title) self.title_label.setWordWrap(True) self.set_style_label(self.title_label, 1) self.homename_label = QLabel(self) self.homename_label.setObjectName("PCardHomeName") self.homename_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.homename_label.setText(self.homename) self.set_style_label(self.homename_label, 0) self.rooms_label = QLabel(self) self.rooms_label.setObjectName("PCardRooms") self.rooms_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.rooms_label.setText(self.rooms) self.set_style_label(self.rooms_label, 0) self.posteddate_label = QLabel(self) self.posteddate_label.setObjectName("PCardPostedDate") self.posteddate_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.posteddate_label.setText("posted " + self.posteddate) self.set_style_label(self.posteddate_label, 0) self.description_label = ElideLabel(self) self.description_label.setObjectName("PCardDescription") self.description_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.description_label.setText(self.description) self.set_style_label(self.description_label, 0) self.price_label = QLabel(self) self.price_label.setObjectName("PCardPrice") self.price_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.price_label.setText(self.price) self.set_style_label(self.price_label, 1) self.set_font(self.font) def set_font(self, font): self.fontSize = font.pointSize() self.homename_label.setFont(font) self.rooms_label.setFont(font) self.posteddate_label.setFont(font) self.description_label.setFont(font) self.title_label.setFont( QFont(font.family(), self.fontSize + 3, QFont.DemiBold)) self.price_label.setFont( QFont(font.family(), self.fontSize + 3, QFont.DemiBold)) def set_style_label(self, label, dark): if dark == 0: color = self.lighttext_color else: color = self.text_color qssString = f"#{label.objectName()} {{background: rgba({self.back_color.red()}, {self.back_color.green()}, {self.back_color.blue()}, 255);" \ f"color: rgb({color.red()}, {color.green()}, {color.blue()}); padding: 2px; }}" label.setStyleSheet(qssString) def set_border_radius(self, rad): self.border_radius = rad print(rad) self.set_style() def set_text_color(self, color): self.text_color = color self.lighttext_color = QColor(self.text_color.red() - 30, self.text_color.green() - 30, self.text_color.blue() - 30) self.set_style() def set_back_color(self, color): self.back_color = color self.set_style() def set_style(self): self.setStyleSheet( f"#PCard {{border-radius: {self.border_radius}; " f"background: rgb({self.back_color.red()}, {self.back_color.green()}, {self.back_color.blue()}); " f"color: rgb({self.text_color.red()}, {self.text_color.green()}, {self.text_color.blue()});}}" ) def resizeEvent(self, event): self.setFixedHeight(self.width() * 1.2) self.pic_label.setGeometry(0, 0, self.width(), self.height() * 0.61) self.title_label.setGeometry(0, self.height() * 0.61, self.width() * 11 / 12, self.height() * 0.12) self.homename_label.setGeometry(0, self.height() * 0.73, self.width() / 3, self.height() * 0.07) self.rooms_label.setGeometry(self.width() / 3, self.height() * 0.73, self.width() / 6, self.height() * 0.07) self.posteddate_label.setGeometry(self.width() / 2, self.height() * 0.73, self.width() / 2, self.height() * 0.07) self.description_label.setGeometry(5, self.height() * 0.8, self.width() - 10, self.height() * 0.1) self.price_label.setGeometry(self.width() * 0.5, self.height() * 0.9, self.width() * 0.5 - self.border_radius, self.height() * 0.1) self.set_border_radius(self.height() / 25) def paintEvent(self, event): painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.setPen(Qt.NoPen) painter.setBrush(self.back_color) painter.drawRoundedRect(QRect(0, 0, self.width(), self.height()), self.border_radius, self.border_radius)