Skip to content
Snippets Groups Projects
graphics_axis_item.py 5.84 KiB
Newer Older
  • Learn to ignore specific revisions
  • Andreas Bolin's avatar
    Andreas Bolin committed
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    from operator import contains
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    import os
    import sys
    from typing     import Any, Optional
    from pprint     import pprint
    from typing     import Any, AnyStr, Generic, Protocol, TypeVar, Union, Optional, overload, Final, final
    # from typing_extensions import Self, Final, Literal, LiteralString, TypeAlias, final
    import numpy    as np
    from copy       import deepcopy
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    from math       import cos, sin, pi
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
    import qtpy
    from qtpy import QtCore
    from qtpy import QtGui
    from qtpy import QtWidgets
    
    # QGraphics and QPainter imports
    from qtpy.QtCore    import (
        Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray)
    from qtpy.QtGui     import (
        QPaintEvent, QPainter, QPainterPath, QColor, QBrush, QPen, QFont, QPolygon, QIcon, QPixmap,
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        QLinearGradient, QTransform, QPolygonF)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    from qtpy.QtWidgets import (
        QGraphicsView, QGraphicsScene, QGraphicsWidget,
        QGraphicsLayout, QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayoutItem, QGraphicsAnchorLayout,
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        QGraphicsItem, QGraphicsItemGroup, QGraphicsPathItem, QGraphicsLineItem, QGraphicsTextItem, QGraphicsRectItem,
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        QStyleOptionGraphicsItem, QWidget, QGraphicsObject, QGraphicsSimpleTextItem, QGraphicsPolygonItem)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    from qtpy.QtCore    import (
        QPoint, QPointF)
    
    # B-ASIC
    import logger
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    from graphics_graph_event   import GraphicsGraphEvent
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    class GraphicsAxisItem(QGraphicsItemGroup):
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        _scale:     float = 1.0 # static, changed from MainWindow
        _width:     float
        _height:    float
        _dy_height: float
        _x_indent:  float
        _axis:      dict[str, QGraphicsItemGroup|QGraphicsLineItem]
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        def __init__(self, width: float = 10.0, height: float = 10.0, x_indent: float = 2.0, parent: QGraphicsItem = None):
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            super().__init__(parent)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self._dy_height = 5/self._scale
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self._axis = {}
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            # self.setFlag(QGraphicsItem.ItemIsMovable)
            # self.setFlag(QGraphicsItem.ItemIsSelectable)
            # self.setAcceptHoverEvents(True)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self.update_(width, height, x_indent)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
        @property
        def width(self) -> float:
            return self._axis['w']
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        # @width.setter
        # def width(self, width: float) -> None:
        #     self._axis['w'] = width
        #     self.prepareGeometryChange()
        #     self._axis.clear()
        #     self._make_axis()
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
        @property
        def height(self) -> float:
            return self._axis['h']
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        # @height.setter
        # def height(self, height: float) -> None:
        #     self._axis['h'] = height
        #     self.prepareGeometryChange()
        #     self._axis.clear()
        #     self._make_axis()
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
        # def _clear(self) -> None:
        #     for child in self._axis.values():
        #         del child
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
        def update_(self, width, height, x_indent) -> None:
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self._width = width
            self._height = height
            self._x_indent = x_indent
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            # make sure the group is empty
            keys = list(self._axis.keys())
            for key in keys:
                self._axis[key].setParentItem(None)
                del self._axis[key]
    
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            # define pencils
            pen = QPen()
            pen.setWidthF(2/self._scale)
            pen.setJoinStyle(Qt.MiterJoin)
            ledger_pen = QPen(Qt.lightGray)
            ledger_pen.setWidthF(0)         # 0 = cosmetic pen 1px width
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            
            # x-axis
            self._axis['x'] = QGraphicsItemGroup()
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            line = QGraphicsLineItem(0, 0, self._width, 0)
            line.setPen(pen)
            self._axis['x'].addToGroup(line)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            # x-axis arrow
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            arrow_size = 8/self._scale
            p0 = QPointF(0, sin(pi/6) * arrow_size)
            p1 = QPointF(arrow_size, 0)
            p2 = QPointF(0, -sin(pi/6) * arrow_size)
            polygon = QPolygonF([p0, p1, p2])
            arrow = QGraphicsPolygonItem(polygon)
            arrow.setPen(pen)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            arrow.setBrush(QBrush(Qt.SolidPattern))
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            arrow.setPos(self._width, 0)
            self._axis['x'].addToGroup(arrow)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            # x-axis scale
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            x_scale = []
            x_scale_labels = []
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            x_ledger = []
            self._axis['x_ledger'] = QGraphicsItemGroup()
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            for i in range(int(self._width/10) + 1):
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                # vertical x-scale
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                x_scale.append(QGraphicsLineItem(0, 0, 0, 0.5))
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                x_scale[i].setPen(pen)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                x_scale[i].setPos(self._x_indent + i*10, 0)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                self._axis['x'].addToGroup(x_scale[i])
                # numbers
                x_scale_labels.append(QGraphicsSimpleTextItem(str(i)))
                x_scale_labels[i].setScale(x_scale_labels[i].scale() / self._scale)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                half_width = x_scale_labels[i].boundingRect().width()/(2*self._scale)
                x_scale_labels[i].setPos(self._x_indent + i*10 - half_width, 0.8)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                self._axis['x'].addToGroup(x_scale_labels[i])
    
    Andreas Bolin's avatar
    Andreas Bolin committed
                # vertical x-ledger
                x_ledger.append(QGraphicsLineItem(0, 0, 0, self._height))
                if i == int(self._width/10):
                    ledger_pen.setWidthF(2/self._scale)
                    ledger_pen.setStyle(Qt.DashLine)
                    ledger_pen.setColor(Qt.black)
                x_ledger[i].setPen(ledger_pen)
                x_ledger[i].setPos(self._x_indent + i*10, 0)
                self._axis['x_ledger'].addToGroup(x_ledger[i])
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            # x-axis label
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            label = QGraphicsSimpleTextItem('time')
            label.setScale(label.scale() / self._scale)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            half_width = label.boundingRect().width()/(2*self._scale)
            arrow_half_width = arrow_size/2
            label.setPos(self._width - half_width + arrow_half_width, 0.8)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self._axis['x'].addToGroup(label)
            self._axis['x'].boundingRect()
    
    Andreas Bolin's avatar
    Andreas Bolin committed
    
            # y-axis
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self._axis['y'] = QGraphicsLineItem(0, 0, 0, self._height + self._dy_height)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self._axis['y'].setPen(pen)
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            
            # put it all together
            self._axis['x'].setPos(0, self._height + self._dy_height)
            self._axis['x_ledger'].setPos(0, self._dy_height)
            self.addToGroup(self._axis['x_ledger'])
            self.addToGroup(self._axis['x'])
    
    Andreas Bolin's avatar
    Andreas Bolin committed
            self.addToGroup(self._axis['y'])