Пример #1
0
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, n_attributes, y_values, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.path = QPainterPath()
        self.fitted = False

        self.n_attributes = n_attributes
        self.n_rows = int(len(y_values) / n_attributes)

        self.set_style(OWCurve.Lines)
        if isinstance(color, tuple):
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        x_values = list(range(n_attributes)) * self.n_rows
        self.set_data(x_values, y_values)

    def update_properties(self):
        self.redraw_path()

    def redraw_path(self):
        self.path = QPainterPath()
        for segment in self.segment(self.data()):
            if self.fitted:
                self.draw_cubic_path(segment)
            else:
                self.draw_normal_path(segment)
        self._item.setPath(self.graph_transform().map(self.path))
        self._item.setPen(self.pen())

    def segment(self, data):
        for i in range(self.n_rows):
            yield data[i * self.n_attributes:(i + 1) * self.n_attributes]

    def draw_cubic_path(self, segment):
        for (x1, y1), (x2, y2) in zip(segment, segment[1:]):
            self.path.moveTo(x1, y1)
            self.path.cubicTo(QPointF(x1 + 0.5, y1),
                              QPointF(x2 - 0.5, y2), QPointF(x2, y2))

    def draw_normal_path(self, segment):
        if not segment:
            return

        x, y = segment[0]
        self.path.moveTo(x, y)
        for x, y in segment[1:]:
            self.path.lineTo(x, y)
Пример #2
0
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, n_attributes, y_values, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.path = QPainterPath()
        self.fitted = False

        self.n_attributes = n_attributes
        self.n_rows = int(len(y_values) / n_attributes)

        self.set_style(OWCurve.Lines)
        if isinstance(color, tuple):
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        x_values = list(range(n_attributes)) * self.n_rows
        self.set_data(x_values, y_values)

    def update_properties(self):
        self.redraw_path()

    def redraw_path(self):
        self.path = QPainterPath()
        for segment in self.segment(self.data()):
            if self.fitted:
                self.draw_cubic_path(segment)
            else:
                self.draw_normal_path(segment)
        self._item.setPath(self.graph_transform().map(self.path))
        self._item.setPen(self.pen())

    def segment(self, data):
        for i in range(self.n_rows):
            yield data[i * self.n_attributes:(i + 1) * self.n_attributes]

    def draw_cubic_path(self, segment):
        for (x1, y1), (x2, y2) in zip(segment, segment[1:]):
            self.path.moveTo(x1, y1)
            self.path.cubicTo(QPointF(x1 + 0.5, y1), QPointF(x2 - 0.5, y2),
                              QPointF(x2, y2))

    def draw_normal_path(self, segment):
        if not segment:
            return

        x, y = segment[0]
        self.path.moveTo(x, y)
        for x, y in segment[1:]:
            self.path.lineTo(x, y)
Пример #3
0
 def _addPath(self):
   iNode = 2 * model._nodes.index(self.__node)
   x0,y0 = record.states[0][iNode:iNode+2]
   path = QPainterPath()
   path.moveTo(x0,-y0)
   item = QGraphicsPathItem()
   item.setPen( QPen( QColor(0,0,255), 0 ) )
   item.setPath(path)
   self._path = item
   for state in record.states[1:]:
     self._addPoint(state)
   if hasattr(record,'changeListeners'):
     record.changeListeners.append(self._addPoint)
   groupCurves.addToGroup(item)
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, attrCount, yData, color, name=""):
        OWCurve.__init__(self, tooltip=name)
        self._item = QGraphicsPathItem(self)
        self.fitted = False
        self.set_style(OWCurve.Lines)

        lineCount = len(yData) / attrCount
        self.attrCount = attrCount

        if type(color) == tuple:
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))

        self.set_data(range(attrCount) * lineCount, yData)

    def update_properties(self):
        if self.fitted:
            path = self.cubicPath()
        else:
            path = QPainterPath()
            for x, y in self.data():
                path.lineTo(x, y)
        self._item.setPath(self.graph_transform().map(path))
        self._item.setPen(self.pen())

    def cubicPath(self):
        path = QPainterPath()
        data = self.data()
        for i in range(len(data) / self.attrCount):
            segment = data[i * self.attrCount:(i + 1) * self.attrCount]
            for i, p in enumerate(segment[:-1]):
                x1, y1 = p
                x2, y2 = segment[i + 1]
                path.moveTo(x1, y1)
                path.cubicTo(QPointF(x1 + 0.5, y1), QPointF(x2 - 0.5, y2),
                             QPointF(x2, y2))
        return path
class ParallelCoordinatesCurve(OWCurve):
    def __init__(self, attrCount, yData, color, name = ""):
        OWCurve.__init__(self, tooltip=name)
	self._item = QGraphicsPathItem(self)
        self.fitted = False
        self.set_style(OWCurve.Lines)

        lineCount = len(yData) / attrCount
        self.attrCount = attrCount

        if type(color) == tuple:
            self.set_pen(QPen(QColor(*color)))
        else:
            self.set_pen(QPen(QColor(color)))
            
	self.set_data(range(attrCount) * lineCount, yData)

    def update_properties(self):
	if self.fitted:
	    path = self.cubicPath()
	else:
	    path = QPainterPath()
	    for x, y in self.data():
		path.lineTo(x, y)
        self._item.setPath(self.graph_transform().map(path))
        self._item.setPen(self.pen())
	
    def cubicPath(self):
        path = QPainterPath()
        data = self.data()
        for i in range(len(data) / self.attrCount):
            segment = data[i*self.attrCount: (i + 1)*self.attrCount]
            for i, p in enumerate(segment[:-1]):
                x1, y1 = p
                x2, y2 = segment[i + 1]
                path.moveTo(x1, y1)
                path.cubicTo(QPointF(x1 + 0.5, y1), QPointF(x2 - 0.5, y2), QPointF(x2, y2))
        return path
Пример #6
0
class PlotGrid(orangeqt.PlotItem):
    """
        Draws a grid onto the plot

        :param plot: If specified, the grid will be attached to the ``plot``.
        :type plot: :obj:`.OWPlot`
    """

    def __init__(self, plot=None):
        orangeqt.PlotItem.__init__(self)
        self._x_enabled = True
        self._y_enabled = True
        self._path_item = QGraphicsPathItem(self)
        self.set_in_background(True)
        if plot:
            self.attach(plot)
            self._path_item.setPen(plot.color(OWPalette.Grid))

    def set_x_enabled(self, b):
        """
            Enables or disabled vertial grid lines
        """
        if b < 0:
            b = not self._x_enabled
        self._x_enabled = b
        self.update_properties()

    def is_x_enabled(self):
        """
            Returns whether vertical grid lines are enabled
        """
        return self._x_enabled

    def set_y_enabled(self, b):
        """
            Enables or disabled horizontal grid lines
        """
        if b < 0:
            b = not self._y_enabled
        self._y_enabled = b
        self.update_properties()

    def is_y_enabled(self):
        """
            Returns whether horizontal grid lines are enabled
        """
        return self._y_enabled

    def set_pen(self, pen):
        """
            Sets the pen used for drawing the grid lines
        """
        self._path_item.setPen(pen)

    def update_properties(self):
        p = self.plot()
        if p is None:
            return
        x_id, y_id = self.axes()
        rect = p.data_rect_for_axes(x_id, y_id)
        path = QPainterPath()
        if self._x_enabled and x_id in p.axes:
            for pos, label, size, _w in p.axes[x_id].ticks():
                path.moveTo(pos, rect.bottom())
                path.lineTo(pos, rect.top())
        if self._y_enabled and y_id in p.axes:
            for pos, label, size, _w in p.axes[y_id].ticks():
                path.moveTo(rect.left(), pos)
                path.lineTo(rect.right(), pos)
        self._path_item.setPath(self.graph_transform().map(path))
Пример #7
0
class TextAnnotation(Annotation):
    """Text annotation item for the canvas scheme.

    """
    editingFinished = Signal()
    """Emitted when the editing is finished (i.e. the item loses focus)."""

    textEdited = Signal()
    """Emitted when the edited text changes."""
    def __init__(self, parent=None, **kwargs):
        Annotation.__init__(self, parent, **kwargs)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)

        self.setFocusPolicy(Qt.ClickFocus)

        self.__textMargins = (2, 2, 2, 2)

        rect = self.geometry().translated(-self.pos())
        self.__framePen = QPen(Qt.NoPen)
        self.__framePathItem = QGraphicsPathItem(self)
        self.__framePathItem.setPen(self.__framePen)

        self.__textItem = GraphicsTextEdit(self)
        self.__textItem.setPlaceholderText(self.tr("Enter text here"))
        self.__textItem.setPos(2, 2)
        self.__textItem.setTextWidth(rect.width() - 4)
        self.__textItem.setTabChangesFocus(True)
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.setFont(self.font())
        self.__textInteractionFlags = Qt.NoTextInteraction

        layout = self.__textItem.document().documentLayout()
        layout.documentSizeChanged.connect(self.__onDocumentSizeChanged)

        self.__updateFrame()

    def adjustSize(self):
        """Resize to a reasonable size.
        """
        self.__textItem.setTextWidth(-1)
        self.__textItem.adjustSize()
        size = self.__textItem.boundingRect().size()
        left, top, right, bottom = self.textMargins()
        geom = QRectF(self.pos(), size + QSizeF(left + right, top + bottom))
        self.setGeometry(geom)

    def setFramePen(self, pen):
        """Set the frame pen. By default Qt.NoPen is used (i.e. the frame
        is not shown).
        """
        if pen != self.__framePen:
            self.__framePen = QPen(pen)
            self.__updateFrameStyle()

    def framePen(self):
        """Return the frame pen.
        """
        return QPen(self.__framePen)

    def setFrameBrush(self, brush):
        """Set the frame brush.
        """
        self.__framePathItem.setBrush(brush)

    def frameBrush(self):
        """Return the frame brush.
        """
        return self.__framePathItem.brush()

    def __updateFrameStyle(self):
        if self.isSelected():
            pen = QPen(QColor(96, 158, 215), 1.25, Qt.DashDotLine)
        else:
            pen = self.__framePen

        self.__framePathItem.setPen(pen)

    def setPlainText(self, text):
        """Set the annotation plain text.
        """
        self.__textItem.setPlainText(text)

    def toPlainText(self):
        return self.__textItem.toPlainText()

    def setHtml(self, text):
        """Set the annotation rich text.
        """
        self.__textItem.setHtml(text)

    def toHtml(self):
        return self.__textItem.toHtml()

    def setDefaultTextColor(self, color):
        """Set the default text color.
        """
        self.__textItem.setDefaultTextColor(color)

    def defaultTextColor(self):
        return self.__textItem.defaultTextColor()

    def setTextMargins(self, left, top, right, bottom):
        """Set the text margins.
        """
        margins = (left, top, right, bottom)
        if self.__textMargins != margins:
            self.__textMargins = margins
            self.__textItem.setPos(left, top)
            self.__textItem.setTextWidth(
                max(self.geometry().width() - left - right, 0))

    def textMargins(self):
        """Return the text margins.
        """
        return self.__textMargins

    def document(self):
        """Return the QTextDocument instance used internally.
        """
        return self.__textItem.document()

    def setTextCursor(self, cursor):
        self.__textItem.setTextCursor(cursor)

    def textCursor(self):
        return self.__textItem.textCursor()

    def setTextInteractionFlags(self, flags):
        self.__textInteractionFlags = flags

    def textInteractionFlags(self):
        return self.__textInteractionFlags

    def setDefaultStyleSheet(self, stylesheet):
        self.document().setDefaultStyleSheet(stylesheet)

    def mouseDoubleClickEvent(self, event):
        Annotation.mouseDoubleClickEvent(self, event)

        if event.buttons() == Qt.LeftButton and \
                self.__textInteractionFlags & Qt.TextEditable:
            self.startEdit()

    def startEdit(self):
        """Start the annotation text edit process.
        """
        self.__textItem.setTextInteractionFlags(self.__textInteractionFlags)
        self.__textItem.setFocus(Qt.MouseFocusReason)

        # Install event filter to find out when the text item loses focus.
        self.__textItem.installSceneEventFilter(self)
        self.__textItem.document().contentsChanged.connect(self.textEdited)

    def endEdit(self):
        """End the annotation edit.
        """
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.removeSceneEventFilter(self)
        self.__textItem.document().contentsChanged.disconnect(self.textEdited)
        cursor = self.__textItem.textCursor()
        cursor.clearSelection()
        self.__textItem.setTextCursor(cursor)
        self.editingFinished.emit()

    def __onDocumentSizeChanged(self, size):
        # The size of the text document has changed. Expand the text
        # control rect's height if the text no longer fits inside.
        try:
            rect = self.geometry()
            _, top, _, bottom = self.textMargins()
            if rect.height() < (size.height() + bottom + top):
                rect.setHeight(size.height() + bottom + top)
                self.setGeometry(rect)
        except Exception:
            log.error("error in __onDocumentSizeChanged", exc_info=True)

    def __updateFrame(self):
        rect = self.geometry()
        rect.moveTo(0, 0)
        path = QPainterPath()
        path.addRect(rect)
        self.__framePathItem.setPath(path)

    def resizeEvent(self, event):
        width = event.newSize().width()
        left, _, right, _ = self.textMargins()
        self.__textItem.setTextWidth(max(width - left - right, 0))
        self.__updateFrame()
        QGraphicsWidget.resizeEvent(self, event)

    def sceneEventFilter(self, obj, event):
        if obj is self.__textItem and event.type() == QEvent.FocusOut:
            self.__textItem.focusOutEvent(event)
            self.endEdit()
            return True

        return Annotation.sceneEventFilter(self, obj, event)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedHasChanged:
            self.__updateFrameStyle()

        return Annotation.itemChange(self, change, value)

    def changeEvent(self, event):
        if event.type() == QEvent.FontChange:
            self.__textItem.setFont(self.font())

        Annotation.changeEvent(self, event)
Пример #8
0
class TextAnnotation(Annotation):
    """Text annotation item for the canvas scheme.

    """
    editingFinished = Signal()
    """Emitted when the editing is finished (i.e. the item loses focus)."""

    textEdited = Signal()
    """Emitted when the edited text changes."""

    def __init__(self, parent=None, **kwargs):
        Annotation.__init__(self, parent, **kwargs)
        self.setFlag(QGraphicsItem.ItemIsMovable)
        self.setFlag(QGraphicsItem.ItemIsSelectable)

        self.setFocusPolicy(Qt.ClickFocus)

        self.__textMargins = (2, 2, 2, 2)

        rect = self.geometry().translated(-self.pos())
        self.__framePathItem = QGraphicsPathItem(self)
        self.__framePathItem.setPen(QPen(Qt.NoPen))

        self.__textItem = GraphicsTextEdit(self)
        self.__textItem.setPlaceholderText(self.tr("Enter text here"))
        self.__textItem.setPos(2, 2)
        self.__textItem.setTextWidth(rect.width() - 4)
        self.__textItem.setTabChangesFocus(True)
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.setFont(self.font())
        self.__textInteractionFlags = Qt.NoTextInteraction

        layout = self.__textItem.document().documentLayout()
        layout.documentSizeChanged.connect(self.__onDocumentSizeChanged)

        self.__updateFrame()

    def adjustSize(self):
        """Resize to a reasonable size.
        """
        self.__textItem.setTextWidth(-1)
        self.__textItem.adjustSize()
        size = self.__textItem.boundingRect().size()
        left, top, right, bottom = self.textMargins()
        geom = QRectF(self.pos(), size + QSizeF(left + right, top + bottom))
        self.setGeometry(geom)

    def setFramePen(self, pen):
        """Set the frame pen. By default Qt.NoPen is used (i.e. the frame
        is not shown).

        """
        self.__framePathItem.setPen(pen)

    def framePen(self):
        """Return the frame pen.
        """
        return self.__framePathItem.pen()

    def setFrameBrush(self, brush):
        """Set the frame brush.
        """
        self.__framePathItem.setBrush(brush)

    def frameBrush(self):
        """Return the frame brush.
        """
        return self.__framePathItem.brush()

    def setPlainText(self, text):
        """Set the annotation plain text.
        """
        self.__textItem.setPlainText(text)

    def toPlainText(self):
        return self.__textItem.toPlainText()

    def setHtml(self, text):
        """Set the annotation rich text.
        """
        self.__textItem.setHtml(text)

    def toHtml(self):
        return self.__textItem.toHtml()

    def setDefaultTextColor(self, color):
        """Set the default text color.
        """
        self.__textItem.setDefaultTextColor(color)

    def defaultTextColor(self):
        return self.__textItem.defaultTextColor()

    def setTextMargins(self, left, top, right, bottom):
        """Set the text margins.
        """
        margins = (left, top, right, bottom)
        if self.__textMargins != margins:
            self.__textMargins = margins
            self.__textItem.setPos(left, top)
            self.__textItem.setTextWidth(
                max(self.geometry().width() - left - right, 0)
            )

    def textMargins(self):
        """Return the text margins.
        """
        return self.__textMargins

    def document(self):
        """Return the QTextDocument instance used internally.
        """
        return self.__textItem.document()

    def setTextCursor(self, cursor):
        self.__textItem.setTextCursor(cursor)

    def textCursor(self):
        return self.__textItem.textCursor()

    def setTextInteractionFlags(self, flags):
        self.__textInteractionFlags = flags

    def textInteractionFlags(self):
        return self.__textInteractionFlags

    def setDefaultStyleSheet(self, stylesheet):
        self.document().setDefaultStyleSheet(stylesheet)

    def mouseDoubleClickEvent(self, event):
        Annotation.mouseDoubleClickEvent(self, event)

        if event.buttons() == Qt.LeftButton and \
                self.__textInteractionFlags & Qt.TextEditable:
            self.startEdit()

    def startEdit(self):
        """Start the annotation text edit process.
        """
        self.__textItem.setTextInteractionFlags(self.__textInteractionFlags)
        self.__textItem.setFocus(Qt.MouseFocusReason)

        # Install event filter to find out when the text item loses focus.
        self.__textItem.installSceneEventFilter(self)
        self.__textItem.document().contentsChanged.connect(
            self.textEdited
        )

    def endEdit(self):
        """End the annotation edit.
        """
        self.__textItem.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__textItem.removeSceneEventFilter(self)
        self.__textItem.document().contentsChanged.disconnect(
            self.textEdited
        )
        self.editingFinished.emit()

    def __onDocumentSizeChanged(self, size):
        # The size of the text document has changed. Expand the text
        # control rect's height if the text no longer fits inside.
        try:
            rect = self.geometry()
            _, top, _, bottom = self.textMargins()
            if rect.height() < (size.height() + bottom + top):
                rect.setHeight(size.height() + bottom + top)
                self.setGeometry(rect)
        except Exception:
            log.error("error in __onDocumentSizeChanged",
                      exc_info=True)

    def __updateFrame(self):
        rect = self.geometry()
        rect.moveTo(0, 0)
        path = QPainterPath()
        path.addRect(rect)
        self.__framePathItem.setPath(path)

    def resizeEvent(self, event):
        width = event.newSize().width()
        left, _, right, _ = self.textMargins()
        self.__textItem.setTextWidth(max(width - left - right, 0))
        self.__updateFrame()
        QGraphicsWidget.resizeEvent(self, event)

    def sceneEventFilter(self, obj, event):
        if obj is self.__textItem and event.type() == QEvent.FocusOut:
            self.__textItem.focusOutEvent(event)
            self.endEdit()
            return True

        return Annotation.sceneEventFilter(self, obj, event)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSelectedHasChanged:
            if self.isSelected():
                self.setFramePen(QPen(Qt.DashDotLine))
            else:
                self.setFramePen(QPen(Qt.NoPen))

        return Annotation.itemChange(self, change, value)

    def changeEvent(self, event):
        if event.type() == QEvent.FontChange:
            self.__textItem.setFont(self.font())

        Annotation.changeEvent(self, event)
Пример #9
0
 def setPath(self, path):
     self.__shape = None
     QGraphicsPathItem.setPath(self, path)
Пример #10
0
class PlotGrid(orangeqt.PlotItem):
    """
        Draws a grid onto the plot

        :param plot: If specified, the grid will be attached to the ``plot``.
        :type plot: :obj:`.OWPlot`
    """
    def __init__(self, plot=None):
        orangeqt.PlotItem.__init__(self)
        self._x_enabled = True
        self._y_enabled = True
        self._path_item = QGraphicsPathItem(self)
        self.set_in_background(True)
        if plot:
            self.attach(plot)
            self._path_item.setPen(plot.color(OWPalette.Grid))

    def set_x_enabled(self, b):
        """
            Enables or disabled vertial grid lines
        """
        if b < 0:
            b = not self._x_enabled
        self._x_enabled = b
        self.update_properties()

    def is_x_enabled(self):
        """
            Returns whether vertical grid lines are enabled
        """
        return self._x_enabled

    def set_y_enabled(self, b):
        """
            Enables or disabled horizontal grid lines
        """
        if b < 0:
            b = not self._y_enabled
        self._y_enabled = b
        self.update_properties()

    def is_y_enabled(self):
        """
            Returns whether horizontal grid lines are enabled
        """
        return self._y_enabled

    def set_pen(self, pen):
        """
            Sets the pen used for drawing the grid lines
        """
        self._path_item.setPen(pen)

    def update_properties(self):
        p = self.plot()
        if p is None:
            return
        x_id, y_id = self.axes()
        rect = p.data_rect_for_axes(x_id, y_id)
        path = QPainterPath()
        if self._x_enabled and x_id in p.axes:
            for pos, label, size, _w in p.axes[x_id].ticks():
                path.moveTo(pos, rect.bottom())
                path.lineTo(pos, rect.top())
        if self._y_enabled and y_id in p.axes:
            for pos, label, size, _w in p.axes[y_id].ticks():
                path.moveTo(rect.left(), pos)
                path.lineTo(rect.right(), pos)
        self._path_item.setPath(self.graph_transform().map(path))
Пример #11
0
 def setPath(self, path):
     self.__shape = None
     QGraphicsPathItem.setPath(self, path)
Пример #12
0
class AxisScene(QGraphicsScene):
    def __init__(self, parent = None):
        super(AxisScene, self).__init__(parent)
        self.guidePen = QPen(QColor("blue"),1)
        self.dot = QGraphicsEllipseItem(-10, -10, 20, 20)
        self.dot.setPos(QPointF(0,0))
        self.dot.setPen(QPen(QColor("red"), 4))
        self.dot.setBrush(QColor("black"))
        self.lastPos = {}
        self.lastPos['x'] = 0
        self.lastPos['y'] = 0
        self.grid = False
        self.gridPen = QPen(QColor("blue"), 2)
        self.pathItem = QGraphicsPathItem()
        self.pathItem.setPen(QPen(QColor("red"), 1, Qt.DotLine))
        self.path = None
        self.xAxis = "Select Axis..."
        self.yAxis = self.xAxis
        self.addItem(self.dot)
    
    def setXAxisName(self, x):
        self.xAxis = "Axis " + str(x)
        self.invalidate()

    def setYAxisName(self, y):
        self.yAxis = "Axis " + str(y)
        self.invalidate()

    def pathToggled(self, toggled):
        if toggled:
            self.path = QPainterPath()
            self.path.moveTo(0,0)
            self.pathItem.setPath(self.path)
            self.addItem(self.pathItem)
        else:
            if self.path != None:
                self.removeItem(self.pathItem)
            self.path = None
        self.invalidate()

    def gridToggled(self, toggled):
        self.grid = toggled
        self.invalidate()

    def updateDotX(self, x):
        self.lastPos['x'] = x * (self.sceneRect().width() / 2)
        self.update(self.lastPos['x'], self.lastPos['y'])
    
    def updateDotY(self, y):
        self.lastPos['y'] = y * (self.sceneRect().height() / 2)
        self.update(self.lastPos['x'], self.lastPos['y'])
    
    def update(self, x, y):
        if self.path != None:
            self.path.lineTo(x, y)
            self.pathItem.setPath(self.path)
        self.dot.setPos(self.lastPos['x'], self.lastPos['y'])
        self.invalidate()
    
    def drawBackground(self, painter, rect):
        if self.grid:
            painter.setClipRect(rect)
            painter.setPen(self.gridPen)

    def drawForeground(self, painter, rect):
        painter.setClipRect(rect)
        painter.setPen(self.gridPen)
        r = self.sceneRect()
        if self.grid:
            painter.drawLine(r.center().x(), r.top(), r.center().x(), r.bottom())
            painter.drawLine(r.left(), r.center().y(), r.right(), r.center().y())
            painter.setPen(QPen(QColor("red"), 1))
            painter.drawText(QRectF(r.left(), r.center().y(), 80, 80), self.xAxis)
            painter.drawText(QRectF(r.center().x()+5, r.top(), 80, 80), self.yAxis)
        if self.path != None:
            painter.setPen(QPen(QColor("red"), 1))
            painter.drawLine(QPointF(self.lastPos['x'], r.top()), QPointF(self.lastPos['x'], r.bottom()))
            painter.drawLine(QPointF(r.left(), self.lastPos['y']), QPointF(r.right(), self.lastPos['y']))