def __init__(self, parent=None): super().__init__(parent) self.sx = Settings.width self.sy = Settings.height self.lines = [] #self.draw_grid() #self.set_opacity(0.3) self.scene = QGraphicsScene(0, 0, Settings.width, Settings.height) self.setScene(self.scene) self.x = 0 self.y = 0 self.w = 5 self.h = 5 pen = QPen(QColor('dodgerblue')) #pen = QPen(QColor(Qt.green)) brush = QBrush(pen.color()) #brush = QBrush(pen.color().darker(150)) # As opposed to using QPen and QBrush, this colors the periphery only #dot = scene.addEllipse(self.x, self.y, self.w, self.h, QColor('dodgerblue')) self.dot = self.scene.addEllipse(self.x, self.y, self.w, self.h, pen, brush) self.dot.setFlag(QGraphicsItem.ItemIsMovable)
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) pen = QPen(Qt.red) pen.setWidth(3) pen.setCapStyle(Qt.RoundCap) scene = QtWidgets.QGraphicsScene() pen.setCosmetic(True) scene.addPixmap(QPixmap('back.png')) self.item = scene.addLine(60, 170, 97, 97, pen) pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.gray)) brush = QtGui.QBrush(pen.color().darker(100)) scene.addEllipse(87, 87, 20, 20, pen, brush) self.item.setTransformOriginPoint(97, 97) self.Grafik.setScene(scene) self.stop_flag_time = Event() self.stop_flag_RS232 = Event() self.getController = Controller(self.stop_flag_time) self.getController.start() self.getController.newTime.connect(self.updateTime) self.getArduino = ControlArduino(self.stop_flag_RS232) self.getArduino.newValue.connect(self.updatePoti) self.getArduino.testRS232.connect(self.updateInfoRS232) self.getArduino.start()
def line(xml: QXmlStreamWriter, pen: QPen, tag: str = "line"): xml.writeStartElement(tag) xml.writeAttribute("color", pen.color().name()) xml.writeAttribute("width", str(pen.width())) if pen.style() == Qt.DashLine: xml.writeAttribute("style", "dash") elif pen.style() == Qt.DotLine: xml.writeAttribute("style", "dot") else: xml.writeAttribute("style", "solid") xml.writeEndElement() #fecha line
class ColorButton(QPushButton): def __init__(self, parent=None): super().__init__(parent) self.on = False def initialize(self, brightness_color_list, background_color=None, border_color=None, style='rectangular'): self.brightness = 0 self.brightness_pens = [QPen(c) for c in brightness_color_list] self.background_pen = QPen(self.palette().color(QPalette.Background) if background_color is None else background_color) self.border_pen = QPen(self.palette().color(QPalette.WindowText) if border_color is None else border_color) if style in ['rectangular', 'circular']: self.style = style else: raise ValueError("ColorButton style has to be either 'rectangular' or 'circular'") def paintEvent(self, _event): painter = QPainter(self) if self.style == 'rectangular': draw_fn = lambda rect, color: painter.drawRect(rect) fill_fn = lambda rect, color: painter.fillRect(rect, color) elif self.style == 'circular': draw_fn = lambda rect, color: painter.drawEllipse(rect) def fillEllipse(rect, color): painter.setBrush(QBrush(color)) painter.drawEllipse(rect) fill_fn = fillEllipse if self.on: pen = self.brightness_pens[self.brightness] else: pen = self.background_pen fill_fn(QRect(0, 0, self.width() - 1, self.height() - 1), pen.color()) painter.setPen(self.border_pen) draw_fn(QRect(0, 0, self.width() - 1, self.height() - 1), self.border_pen.color()) def switch_off(self): self.on = False self.update() def switch_on(self, brightness=None): self.on = True if brightness is not None: self.brightness = brightness self.update() def set_brightness(self, brightness): self.brightness = brightness
def setValues(self, pen: QPen): for i in range(self.lstPenStyles.count()): item = self.lstPenStyles.item(i) if item.data(PenParametersDialog.PenStyleRole) == pen.style(): item.setSelected(True) break for i in range(self.lstPenColors.count()): item = self.lstPenColors.item(i) if QColor(item.data(PenParametersDialog.ColorRole)).name( ) == pen.color().name(): item.setSelected(True) break self.spinPenSize.setValue(pen.width())
def __init__(self, parent=None): super().__init__(parent) self.sx = 635 self.sy = 475 scene = QGraphicsScene(0, 0, self.sx, self.sy) self.setScene(scene) self.x = 0 self.y = 0 self.w = 30 self.h = 30 pen = QPen(QColor('dodgerblue')) #pen = QPen(QColor(Qt.green)) brush = QBrush(pen.color()) #brush = QBrush(pen.color().darker(150)) # As opposed to using QPen and QBrush, this colors the periphery only #dot = scene.addEllipse(self.x, self.y, self.w, self.h, QColor('dodgerblue')) self.dot = scene.addEllipse(self.x, self.y, self.w, self.h, pen, brush) self.dot.setFlag(QGraphicsItem.ItemIsMovable)
def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) #===================== define pen ======================== pen = QPen(Qt.red) pen.setWidth(3) pen.setCapStyle(Qt.RoundCap) pen.setCosmetic(True) #====================== add GraphicsScene ================== scene = QtWidgets.QGraphicsScene() scene.addPixmap(QPixmap(img_path + '/back.png')) self.item = scene.addLine(60, 170, 97, 97, pen) #(center to other side) #================= add ellipse to graphics scence ======================== pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.gray)) brush = QtGui.QBrush(pen.color().darker(100)) scene.addEllipse(87, 87, 20, 20, pen, brush) self.item.setTransformOriginPoint(97, 97) self.graphicsView.setScene(scene) #====================== get data from control arduino file ======================== self.stop_flag_time = Event() self.stop_flag_arduino = Event() self.getControltime = ControlTime(self.stop_flag_time) self.getControltime.start() self.getControltime.newTime.connect(self.updateTime) self.getControlArduino = ControlArduino(self.stop_flag_arduino) self.getControlArduino.check_Arduino.connect(self.updateInfoArduino) self.getControlArduino.ser_val.connect(self.getSerialData) self.getControlArduino.start()
class RenderArea(QWidget): """ Класс области рисования """ def __init__(self, parent=None): super(RenderArea, self).__init__(parent) self.sphere = Sphere(self) self.pen = QPen(QColor(0, 0, 0), 0) self.faces_color = QColor(0, 255, 0) self.is_light = False self.is_clipping = False self.setBackgroundRole(QPalette.Base) self.setAutoFillBackground(True) def minimumSizeHint(self): return QSize(200, 200) def sizeHint(self): return QSize(400, 400) def set_pen_width(self, width): self.pen = QPen(self.pen.color(), width) self.update() def set_pen_color(self, label): color = QColorDialog.getColor() if color.isValid(): self.pen = QPen(color, self.pen.width()) label_palette = QPalette() label_palette.setColor(QPalette.WindowText, color) label.setPalette(label_palette) label.setText("Цвет линии " + color.name()) self.update() def paintEvent(self, event): painter = QPainter(self) painter.setPen(self.pen) # Пересчитываем сферу self.sphere.recalculate() # Рисуем for face in self.sphere.geom.faces: self.draw_item(face, painter) # Окантовка виджета painter.setPen(self.palette().dark().color()) painter.setBrush(Qt.NoBrush) painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1)) def draw_item(self, face, painter): is_draw = True if self.is_clipping: is_draw = self.sphere.is_face_visible(face) if is_draw: polygon = QPolygon() for index, point_index in enumerate(face): p1_x = int(self.sphere.geom.points[face[index-1]][0]) p1_y = int(self.sphere.geom.points[face[index-1]][1]) p1_z = int(self.sphere.geom.points[face[index-1]][2]) p2_x = int(self.sphere.geom.points[point_index][0]) p2_y = int(self.sphere.geom.points[point_index][1]) p2_z = int(self.sphere.geom.points[point_index][2]) if self.sphere.projection_name == "front": # Фронтальная проекция (вид спереди) -> z = 0 real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) elif self.sphere.projection_name == "horizontal": # Горизонтальная проекция (вид сверху) -> y = 0 real_p1 = QPoint(p1_x, p1_z) real_p2 = QPoint(p2_x, p2_z) elif self.sphere.projection_name == "profile": # Профильная проекция (вид сбоку) -> x = 0 real_p1 = QPoint(p1_y, p1_z) real_p2 = QPoint(p2_y, p2_z) else: real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) # Точки для проволочного рисования real_p1.setX(self.width()/2 + real_p1.x()) real_p1.setY(self.height()/2 - real_p1.y()) real_p2.setX(self.width()/2 + real_p2.x()) real_p2.setY(self.height()/2 - real_p2.y()) # Полигоны для рисования с цветом polygon.append(real_p1) polygon.append(real_p2) if not self.is_light: painter.drawLine(real_p1, real_p2) if self.is_light: painter.setBrush(self.sphere.get_face_light(face, self.faces_color)) painter.drawPolygon(polygon) def set_projection(self, button): self.sphere.projection_name = button.objectName() self.update() def set_clipping(self, state): self.is_clipping = True if state == Qt.Checked else False self.update() def set_faces_color(self, label): color = QColorDialog.getColor() if color.isValid(): self.faces_color = color label_palette = QPalette() label_palette.setColor(QPalette.WindowText, color) label.setPalette(label_palette) label.setText("Цвет объекта " + color.name()) self.update() def set_light(self, is_light, clipping_checkbox): self.is_light = is_light clipping_checkbox.setChecked(self.is_light) clipping_checkbox.setDisabled(self.is_light) self.update()
class QImagePainter(QSmoothGraphicsView): # signals imageFlattened = pyqtSignal(QImage) def __init__(self): super().__init__() self.scene = QGraphicsScene(self) self.setScene(self.scene) self.setRenderHint(QPainter.Antialiasing) self.mainPixmapItem = self.scene.addPixmap(QPixmap()) self._appContext = None # policies # self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) # self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.toolbar = QToolBar() self.initToolbar() self._pen = QPen() self._pen.setWidth(50) self.setDefaultPenColor() self._drawStartPos = None self._dynamicOval = None self._drawnItems = [] self.updateDragMode() @property def appContext(self): return self._appContext @appContext.setter def appContext(self, context): self._appContext = context self.toolbar.clear() self.initToolbar() def setMainPixmapFromPath(self, imgPath): # set image image = QImage(str(imgPath)) pixmap = self.mainPixmapItem.pixmap() pixmap.convertFromImage(image) self.setMainPixmap(pixmap) def setMainPixmap(self, pixmap): self.mainPixmapItem.setPixmap(pixmap) # set scene rect boundingRect = self.mainPixmapItem.boundingRect() margin = 0 boundingRect += QMarginsF(margin, margin, margin, margin) self.scene.setSceneRect(boundingRect) def saveImage(self, fileName): image = self.flattenImage() image.save(fileName) def flattenImageIfDrawnOn(self): if not len(self._drawnItems) == 0: self.flattenImage() def flattenImage(self): # get region of scene area = self.mainPixmapItem.boundingRect() # create a QImage to render to and fix up a QPainter for it image = QImage(area.width(), area.height(), QImage.Format_ARGB32_Premultiplied) painter = QPainter(image) # render the region of interest to the QImage self.scene.render(painter, QRectF(image.rect()), area) painter.end() # set this flattened image to this view pixmap = self.mainPixmapItem.pixmap() pixmap.convertFromImage(image) self.setMainPixmap(pixmap) # clear the drawings from the view self.clearDrawnItems() # emit flattened image signal self.imageFlattened.emit(image) # return the flattened image return image def clearDrawnItems(self): for item in self._drawnItems: self.scene.removeItem(item) self._drawnItems.clear() def removeLastDrawnItem(self): try: item = self._drawnItems.pop() except IndexError: pass else: self.scene.removeItem(item) def scaleView(self, scaleFactor): # print(f'self.width: {self.width()}') # print(f'pixmap.width(): {self.scene.map.mainPixmapItem.boundingRect().width()}') self.scale(scaleFactor, scaleFactor) def centerImage(self): self.centerOn(self.mainPixmapItem) def bestFitImage(self): self.fitInView(self.mainPixmapItem, Qt.KeepAspectRatio) def keyPressEvent(self, event: QKeyEvent): key = event.key() if key == Qt.Key_Space: self.bestFitImage() else: super().keyPressEvent(event) def mousePressEvent(self, event): self._drawStartPos = None if self.ovalModeAct.isChecked(): if self.mainPixmapItem.isUnderMouse(): self._drawStartPos = self.mapToScene(event.pos()) self._dynamicOval = self.scene.addEllipse( QRectF(self._drawStartPos.x(), self._drawStartPos.y(), 1, 1), self._pen) else: super().mousePressEvent(event) def mouseMoveEvent(self, event): if self._dynamicOval: pos = self.mapToScene(event.pos()) self._dynamicOval.setRect( QRectF(self._drawStartPos.x(), self._drawStartPos.y(), pos.x() - self._drawStartPos.x(), pos.y() - self._drawStartPos.y())) else: super().mouseMoveEvent(event) def mouseReleaseEvent(self, event): if self._dynamicOval: self._drawnItems.append(self._dynamicOval) self._dynamicOval = None else: super().mouseReleaseEvent(event) def toggleSelectionMode(self): if self.selectionModeAct.isChecked(): self.ovalModeAct.setChecked(False) else: self.selectionModeAct.setChecked(True) self.updateDragMode() def toggleOvalMode(self): if self.ovalModeAct.isChecked(): self.selectionModeAct.setChecked(False) else: self.ovalModeAct.setChecked(True) self.updateDragMode() def updateDragMode(self): if self.selectionModeAct.isChecked(): self.setDragMode(QGraphicsView.ScrollHandDrag) else: self.setDragMode(QGraphicsView.NoDrag) @property def penWidth(self): return self._pen.width() @penWidth.setter def penWidth(self, value): self._pen.setWidth(value) @property def penColor(self): return self._pen.color() @penColor.setter def penColor(self, value): self._pen.setColor(QColor(value)) def setDefaultPenColor(self): self.setPenColor(COLORS['Teleric Blue']) def promptForPenWidth(self): width, okPressed = QInputDialog.getInt(self, 'Pen Width', 'Pen width (px):', self.penWidth, 1, 100, 1) if okPressed: self.penWidth = width def setResourcePaths(self): if self.appContext is None: self.selectionModeFp = './icons/selectIcon.png' self.ovalModeFp = './icons/ovalIcon.png' self.flattenFp = './icons/saveIcon.png' self.undoFp = './icons/undoIcon.png' self.penFp = './icons/pen.png' self.penWidthFp = './icons/penWidth.png' else: self.selectionModeFp = self.appContext.get_resource( 'selectIcon.png') self.ovalModeFp = self.appContext.get_resource('ovalIcon.png') self.flattenFp = self.appContext.get_resource('saveIcon.png') self.undoFp = self.appContext.get_resource('undoIcon.png') self.penFp = self.appContext.get_resource('pen.png') self.penWidthFp = self.appContext.get_resource('penWidth.png') def createActions(self): self.setResourcePaths() self.selectionModeAct = QAction(QIcon(self.selectionModeFp), 'Select (v)', self, checkable=True, checked=True, shortcut=Qt.Key_V, triggered=self.toggleSelectionMode) self.ovalModeAct = QAction(QIcon(self.ovalModeFp), 'Draw &Oval (o)', self, checkable=True, checked=False, shortcut=Qt.Key_O, triggered=self.toggleOvalMode) self.flattenAct = QAction(QIcon(self.flattenFp), 'Save', self, shortcut=QKeySequence.Save, triggered=self.flattenImage) self.undoAct = QAction(QIcon(self.undoFp), 'Undo', self, shortcut=QKeySequence.Undo, triggered=self.removeLastDrawnItem) self.setPenWidthAct = QAction(QIcon(self.penWidthFp), 'Set Pen Width', self, triggered=self.promptForPenWidth) def addPenToolMenu(self): penButton = QToolButton(self) penButton.setText('Pen') penButton.setIcon(QIcon(self.penFp)) penButton.setPopupMode(QToolButton.InstantPopup) self.penMenu = QMenu(penButton) self.penMenu.addAction(self.setPenWidthAct) self.addPaletteToMenu(self.penMenu) penButton.setMenu(self.penMenu) self.toolbar.addWidget(penButton) def setPenColor(self, color): qColor = QColor(color) for a in self.penMenu.actions(): a.setChecked(False) try: actionColor = QColor(a.color) except AttributeError: pass else: if actionColor == qColor: a.setChecked(True) self.penColor = actionColor def addPaletteToMenu(self, menu): for name, color in COLORS.items(): paletteIcon = QPaletteIcon(color) action = QAction(paletteIcon, name, self, checkable=True) action.color = color action.triggered.connect( lambda checked, color=color: self.setPenColor(color)) menu.addAction(action) def initToolbar(self): self.createActions() # self.toolbar.addAction(self.flattenAct) self.toolbar.addAction(self.undoAct) # self.toolbar.addSeparator() self.toolbar.addAction(self.selectionModeAct) self.toolbar.addAction(self.ovalModeAct) self.addPenToolMenu()
class RenderArea(QWidget): """ Класс области рисования """ def __init__(self, parent=None): super(RenderArea, self).__init__(parent) self.sphere = Sphere(self) self.pen = QPen(QColor(0, 0, 0), 0) self.faces_color = QColor(0, 255, 0) self.is_light = False self.is_clipping = False self.setBackgroundRole(QPalette.Base) self.setAutoFillBackground(True) def minimumSizeHint(self): return QSize(200, 200) def sizeHint(self): return QSize(400, 400) def set_pen_width(self, width): self.pen = QPen(self.pen.color(), width) self.update() def set_pen_color(self, label): color = QColorDialog.getColor() if color.isValid(): self.pen = QPen(color, self.pen.width()) label_palette = QPalette() label_palette.setColor(QPalette.WindowText, color) label.setPalette(label_palette) label.setText("Цвет линии " + color.name()) self.update() def paintEvent(self, event): painter = QPainter(self) painter.setPen(self.pen) # Пересчитываем сферу self.sphere.recalculate() # Рисуем for face in self.sphere.geom.faces: self.draw_item(face, painter) # Окантовка виджета painter.setPen(self.palette().dark().color()) painter.setBrush(Qt.NoBrush) painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1)) def draw_item(self, face, painter): is_draw = True if self.is_clipping: is_draw = self.sphere.is_face_visible(face) if is_draw: polygon = QPolygon() for index, point_index in enumerate(face): p1_x = int(self.sphere.geom.points[face[index - 1]][0]) p1_y = int(self.sphere.geom.points[face[index - 1]][1]) p1_z = int(self.sphere.geom.points[face[index - 1]][2]) p2_x = int(self.sphere.geom.points[point_index][0]) p2_y = int(self.sphere.geom.points[point_index][1]) p2_z = int(self.sphere.geom.points[point_index][2]) if self.sphere.projection_name == "front": # Фронтальная проекция (вид спереди) -> z = 0 real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) elif self.sphere.projection_name == "horizontal": # Горизонтальная проекция (вид сверху) -> y = 0 real_p1 = QPoint(p1_x, p1_z) real_p2 = QPoint(p2_x, p2_z) elif self.sphere.projection_name == "profile": # Профильная проекция (вид сбоку) -> x = 0 real_p1 = QPoint(p1_y, p1_z) real_p2 = QPoint(p2_y, p2_z) else: real_p1 = QPoint(p1_x, p1_y) real_p2 = QPoint(p2_x, p2_y) # Точки для проволочного рисования real_p1.setX(self.width() / 2 + real_p1.x()) real_p1.setY(self.height() / 2 - real_p1.y()) real_p2.setX(self.width() / 2 + real_p2.x()) real_p2.setY(self.height() / 2 - real_p2.y()) # Полигоны для рисования с цветом polygon.append(real_p1) polygon.append(real_p2) if not self.is_light: painter.drawLine(real_p1, real_p2) if self.is_light: painter.setBrush( self.sphere.get_face_light(face, self.faces_color)) painter.drawPolygon(polygon) def set_projection(self, button): self.sphere.projection_name = button.objectName() self.update() def set_clipping(self, state): self.is_clipping = True if state == Qt.Checked else False self.update() def set_faces_color(self, label): color = QColorDialog.getColor() if color.isValid(): self.faces_color = color label_palette = QPalette() label_palette.setColor(QPalette.WindowText, color) label.setPalette(label_palette) label.setText("Цвет объекта " + color.name()) self.update() def set_light(self, is_light, clipping_checkbox): self.is_light = is_light clipping_checkbox.setChecked(self.is_light) clipping_checkbox.setDisabled(self.is_light) self.update()
class PFSNode(PFSElement): def __init__(self, id: str, x: int, y: int): PFSElement.__init__(self, id) self.setPos(x / 2, y / 2) self._width = 0 self._height = 0 self._pen = QPen(Qt.black) self._brush = QBrush(Qt.white, Qt.SolidPattern) self.emitter = PFSSenderSignal() self.changed = self.emitter.changed self.deleted = self.emitter.deleted self.penEdited = self.emitter.penEdited def move(self, x, y): self.moveBy(x / 2, y / 2) self.changed.emit() for it in self.scene().items(): print(str(it.__class__) + " " + str(it.shape().boundingRect())) def setPenColor(self, color: QColor): self._pen.setColor(color) self.scene().update() def setPenStyle(self, style: Qt): self._pen.setStyle(style) self.scene().update() self.penEdited.emit(self) def setPenWidth(self, width: str): self._pen.setWidth(float(width)) self.scene().update() def setBrushColor(self, color: QColor): self._brush.setColor(color) self.scene().update() def changeElementPosX(self, prop): x = PFSUndoPropertyText(prop, self.moveX) self.scene()._page._net.undoStack.push(x) def changeElementPosY(self, prop): x = PFSUndoPropertyText(prop, self.moveY) self.scene()._page._net.undoStack.push(x) def changeElementWidth(self, prop): x = PFSUndoPropertyText(prop, self.resizeWidth) self.scene()._page._net.undoStack.push(x) def changeElementHeight(self, prop): x = PFSUndoPropertyText(prop, self.resizeHeight) self.scene()._page._net.undoStack.push(x) def changeLineColor(self): color = QColorDialog.getColor(self._pen.color(), self.scene()._page._net, "Escolha a cor do contorno") if color.isValid() and color != self._pen.color(): x = PFSUndoPropertyButton(color, self._pen.color(), self.setPenColor) self.scene()._page._net.undoStack.push(x) def changeLineStyle(self, text): if text in self.PEN_LIST: x = PFSUndoPropertyCombo(self.PEN_LIST[text], self._pen.style(), self.setPenStyle) self.scene()._page._net.undoStack.push(x) def changeLineWidth(self, prop): x = PFSUndoPropertyText(prop, self.setPenWidth) self.scene()._page._net.undoStack.push(x) def changeFillColor(self): color = QColorDialog.getColor(self._brush.color(), self.scene()._page._net, "Escolha a cor do preenchimento") if color.isValid() and color != self._brush.color(): x = PFSUndoPropertyButton(color, self._brush.color(), self.setBrushColor) self.scene()._page._net.undoStack.push(x) def moveX(self, txt, update=True): self.moveBy(float(txt) / 2, 0) if update: self.scene().update() def moveY(self, txt, update=True): self.moveBy(0, float(txt) / 2) if update: self.scene().update() def resizeWidth(self, txt): self._width = float(txt) self.changed.emit() self.scene().update() def resizeHeight(self, txt): self._height = float(txt) self.changed.emit() self.scene().update()
def setPen(self, pen): pen = QPen(pen) # convert to pen if argument is a QColor QAbstractGraphicsShapeItem.setPen(self, pen) self._text_item.setDefaultTextColor(pen.color())
from PyQt5.QtCore import Qt from PyQt5.QtGui import QPen WIDTH = 5 COLOR = Qt.gray STYLE = Qt.SolidLine ACTIVE_WIDTH = 7 ACTIVE_COLOR = Qt.darkGray ACTIVE_STYLE = STYLE line = QPen(COLOR, WIDTH, STYLE) point = QPen(line.color(), WIDTH * 2, line.style()) activeLine = QPen(ACTIVE_COLOR, ACTIVE_WIDTH, ACTIVE_STYLE) activePoint = QPen(ACTIVE_COLOR, ACTIVE_WIDTH * 2, ACTIVE_STYLE)
class PenFormation(InstrumentFormation): ''' Specialize to Qt <QPen> Redefine: - applyTo() ''' # TODO: a QPen has a QBrush also, and it needs to be scaled also def __init__(self, parentSelector, role=""): InstrumentFormation.__init__(self, name="Pen", parentSelector=parentSelector, role=role) self.instrument = QPen() self.styleProperties=[BaseStyleProperty("Color", self.instrument.setColor, self.selector, default = self.instrument.color(), resettableValueFactory=ResettableColorValue, layoutFactory=ColorStylePropertyLayout), BaseStyleProperty("Width", self.instrument.setWidth, self.selector, default=self.instrument.width(), layoutFactory=IntStylePropertyLayout, minimum=0, maximum=10, singleStep=1), BaseStyleProperty("Style", self.instrument.setStyle, self.selector, default=self.instrument.style(), layoutFactory=ComboBoxStylePropertyLayout, domainModel = config.PenModel) ] def applyTo(self, morph): ''' Assert this formation's values have already been applied to instrument via editing (which calls Instrument.setters()) What remains is to set the instrument to the morph. Also, scale instrument correlated with scale of morph. ''' # Callback morph API: only morph knows its scale, and how to inversely scale drawing instrument morph.scaleInstrument(self.instrument, baseValue=self.styleProperties[1].resettableValue.value) morph.setPen(self.instrument) """ def scaledPropagateToInstrument(self, morph): ''' Propagate my values that are transformed, after unscaling by the local (item) transform. Where a DocumentElement has a transform that is used to size it (e.g. when the DocumentElement comprises a unit shape, scaled to size.) TODO when item transform is 2D and not uniform in x, y??? This is not undoing viewing transform, only local transform. For a Pen in Qt, width property. Note that in Qt, QPen.setWidth() also affects the QPen's QBrush. ''' unscaledWidth = self.styleProperties[1].resettableValue.value() itemScale = morph.scale() scaledWidthF = 1.0/itemScale * unscaledWidth # !!! Note float value and setWidthF is float setter self.instrument.setWidthF(scaledWidthF) #print "PenFormation.applyTo width: item scale, unscaled width, scaled width", itemScale, unscaledWidth, scaledWidthF, " on morph", morph """
class Window(QtWidgets.QMainWindow): def __init__(self): QtWidgets.QWidget.__init__(self) uic.loadUi("window.ui", self) self.scene = QtWidgets.QGraphicsScene(0, 0, 500, 500) self.canvas.setScene(self.scene) self.image = QImage(511, 511, QImage.Format_ARGB32_Premultiplied) self.pen = QPen() self.draw.clicked.connect(lambda: self.draw_one()) self.clear.clicked.connect(lambda: self.clear_canvas()) self.bg_color.clicked.connect(lambda: self.set_bg_color()) self.line_color.clicked.connect(lambda: self.set_line_color()) self.concentr.clicked.connect(lambda: self.draw_konc()) layout = QtWidgets.QHBoxLayout() layout.addWidget(self.what) layout.addWidget(self.other) # self.setLayout(layout) self.circle.setChecked(True) self.canon.setChecked(True) def circle_canon(self, cx, cy, r): for x in range(0, r + 1, 1): y = round(sqrt(r**2 - x**2)) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) for y in range(0, r + 1, 1): x = round(sqrt(r**2 - y**2)) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) def circle_param(self, cx, cy, r): len_of_circle = round(2 * pi * r) + 1 # длина окружности for i in range(len_of_circle): x = (cx + r * cos(i / r)) y = (cy + r * sin(i / r)) self.image.setPixel(x, y, self.pen.color().rgb()) def circle_brez(self, cx, cy, r): x = 0 # задание начальных значений y = r d = 2 - 2 * r # значение D(x,y) при (0,R) while y >= 0: # высвечивание текущего пиксела self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) if d < 0: # пиксель лежит внутри окружности buf = 2 * d + 2 * y - 1 x += 1 if buf <= 0: # горизонтальный шаг d = d + 2 * x + 1 else: # диагональный шаг y -= 1 d = d + 2 * x - 2 * y + 2 continue if d > 0: # пиксель лежит вне окружности buf = 2 * d - 2 * x - 1 y -= 1 if buf > 0: # вертикальный шаг d = d - 2 * y + 1 else: # диагональный шаг x += 1 d = d + 2 * x - 2 * y + 2 continue if d == 0.0: # пиксель лежит на окружности x += 1 # диагональный шаг y -= 1 d = d + 2 * x - 2 * y + 2 def circle_middle(self, cx, cy, r): x = 0 # начальные значения y = r p = 5 / 4 - r # (x + 1)^2 + (y - 1/2)^2 - r^2 while True: self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - y, cy + x, self.pen.color().rgb()) self.image.setPixel(cx + y, cy - x, self.pen.color().rgb()) self.image.setPixel(cx - y, cy - x, self.pen.color().rgb()) self.image.setPixel(cx + y, cy + x, self.pen.color().rgb()) x += 1 if p < 0: # средняя точка внутри окружности, ближе верхний пиксел, горизонтальный шаг p += 2 * x + 1 else: # средняя точка вне окружности, ближе диагональный пиксел, диагональный шаг p += 2 * x - 2 * y + 5 y -= 1 if x > y: break def ellips_canon(self, cx, cy, a, b): for x in range(0, a + 1, 1): y = round(b * sqrt(1.0 - x**2 / a / a)) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) for y in range(0, b + 1, 1): x = round(a * sqrt(1.0 - y**2 / b / b)) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) def ellips_param(self, cx, cy, a, b): m = max(a, b) l = round(pi * m / 2) for i in range(0, l + 1, 1): x = round(a * cos(i / m)) y = round(b * sin(i / m)) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) def ellips_brez(self, cx, cy, a, b): x = 0 # начальные значения y = b a = a**2 d = round(b * b / 2 - a * b * 2 + a / 2) b = b**2 while y >= 0: self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) if d < 0: # пиксель лежит внутри эллипса buf = 2 * d + 2 * a * y - a x += 1 if buf <= 0: # горизотальный шаг d = d + 2 * b * x + b else: # диагональный шаг y -= 1 d = d + 2 * b * x - 2 * a * y + a + b continue if d > 0: # пиксель лежит вне эллипса buf = 2 * d - 2 * b * x - b y -= 1 if buf > 0: # вертикальный шаг d = d - 2 * y * a + a else: # диагональный шаг x += 1 d = d + 2 * x * b - 2 * y * a + a + b continue if d == 0.0: # пиксель лежит на окружности x += 1 # диагональный шаг y -= 1 d = d + 2 * x * b - 2 * y * a + a + b def ellips_middle(self, cx, cy, a, b): x = 0 # начальные положения y = b p = b * b - a * a * b + 0.25 * a * a # начальное значение параметра принятия решения в области tg<1 while 2 * (b**2 ) * x < 2 * a * a * y: # пока тангенс угла наклона меньше 1 self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) x += 1 if p < 0: # средняя точка внутри эллипса, ближе верхний пиксел, горизонтальный шаг p += 2 * b * b * x + b * b else: # средняя точка вне эллипса, ближе диагональный пиксел, диагональный шаг y -= 1 p += 2 * b * b * x - 2 * a * a * y + b * b p = b * b * (x + 0.5) * (x + 0.5) + a * a * (y - 1) * ( y - 1) - a * a * b * b # начальное значение параметра принятия решения в области tg>1 в точке (х + 0.5, y - 1) полседнего положения while y >= 0: self.image.setPixel(cx - x, cy + y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx - x, cy - y, self.pen.color().rgb()) self.image.setPixel(cx + x, cy + y, self.pen.color().rgb()) y -= 1 if p > 0: p -= 2 * a * a * y + a * a else: x += 1 p += 2 * b * b * x - 2 * a * a * y + a * a def draw_one(self): is_standart = False x = int(self.xc.text()) y = int(self.yc.text()) if self.circle.isChecked(): r = int(self.radius.text()) if self.canon.isChecked(): self.circle_canon(x + 250, y + 250, r) if self.param.isChecked(): self.circle_canon(x + 250, y + 250, r) if self.brez.isChecked(): self.circle_canon(x + 250, y + 250, r) if self.middleDot.isChecked(): self.circle_canon(x + 250, y + 250, r) if self.bibl.isChecked(): is_standart = True self.scene.addEllipse(x + 250 - r, y + 250 - r, r * 2, r * 2, self.pen) if self.ellips.isChecked(): a = int(self.A.text()) b = int(self.B.text()) if self.canon.isChecked(): self.ellips_canon(x + 250, y + 250, b, a) if self.param.isChecked(): self.ellips_canon(x + 250, y + 250, b, a) if self.brez.isChecked(): self.ellips_canon(x + 250, y + 250, b, a) if self.middleDot.isChecked(): self.ellips_canon(x + 250, y + 250, b, a) if self.bibl.isChecked(): is_standart = True self.scene.addEllipse(x + 250 - b, y + 250 - a, b * 2, a * 2, self.pen) if not is_standart: pix = QPixmap(511, 511) pix.convertFromImage(self.image) self.scene.addPixmap(pix) def draw_konc(self): is_standart = False x = int(self.xc.text()) y = int(self.yc.text()) d = int(self.step.text()) c = int(self.amount.text()) if self.circle.isChecked(): for i in range(d, d * c + d, d): if self.canon.isChecked(): self.circle_canon(x + 250, y + 250, i) if self.param.isChecked(): self.circle_canon(x + 250, y + 250, i) if self.brez.isChecked(): self.circle_canon(x + 250, y + 250, i) if self.middleDot.isChecked(): self.circle_canon(x + 250, y + 250, i) if self.bibl.isChecked(): is_standart = True self.scene.addEllipse(x + 250 - i, y + 250 - i, i * 2, i * 2, self.pen) if self.ellips.isChecked(): for i in range(d, d * c + d, d): if self.canon.isChecked(): self.ellips_canon(x + 250, y + 250, i * 2, i) if self.param.isChecked(): self.ellips_canon(x + 250, y + 250, i * 2, i) if self.brez.isChecked(): self.ellips_canon(x + 250, y + 250, i * 2, i) if self.middleDot.isChecked(): self.ellips_canon(x + 250, y + 250, i * 2, i) if self.bibl.isChecked(): self.is_standart = True self.scene.addEllipse(x + 250 - i * 2, y + 250 - i, i * 4, i * 2, self.pen) if not is_standart: pix = QPixmap(511, 511) pix.convertFromImage(self.image) self.scene.addPixmap(pix) def set_bg_color(self): color = QtWidgets.QColorDialog.getColor( initial=Qt.white, title='Цвет фона', options=QtWidgets.QColorDialog.DontUseNativeDialog) if color.isValid(): self.color_bground = color self.image.fill(color) s = QtWidgets.QGraphicsScene(0, 0, 10, 10) s.setBackgroundBrush(color) self.bg_color_win.setScene(s) self.scene.setBackgroundBrush(color) def set_line_color(self): color = QtWidgets.QColorDialog.getColor( initial=Qt.black, title='Цвет линии', options=QtWidgets.QColorDialog.DontUseNativeDialog) if color.isValid(): self.color_line = color self.pen.setColor(color) s = QtWidgets.QGraphicsScene(0, 0, 10, 10) s.setBackgroundBrush(color) self.line_color_win.setScene(s) def clear_canvas(self): self.image.fill(Qt.color0) self.scene.clear()