Source code for qwt.plot_grid

# -*- coding: utf-8 -*-
#
# Licensed under the terms of the Qwt License
# Copyright (c) 2002 Uwe Rathmann, for the original C++ code
# Copyright (c) 2015 Pierre Raybaut, for the Python translation/optimization
# (see LICENSE file for more details)

"""
QwtPlotGrid
-----------

.. autoclass:: QwtPlotGrid
   :members:
"""

from qtpy.QtCore import QLineF, Qt
from qtpy.QtGui import QPen

from qwt._math import qwtFuzzyGreaterOrEqual, qwtFuzzyLessOrEqual
from qwt.plot import QwtPlotItem
from qwt.qthelpers import qcolor_from_str
from qwt.scale_div import QwtScaleDiv


class QwtPlotGrid_PrivateData(object):
    def __init__(self):
        self.xEnabled = True
        self.yEnabled = True
        self.xMinEnabled = False
        self.yMinEnabled = False
        self.xScaleDiv = QwtScaleDiv()
        self.yScaleDiv = QwtScaleDiv()
        self.majorPen = QPen()
        self.minorPen = QPen()


[docs] class QwtPlotGrid(QwtPlotItem): """ A class which draws a coordinate grid The `QwtPlotGrid` class can be used to draw a coordinate grid. A coordinate grid consists of major and minor vertical and horizontal grid lines. The locations of the grid lines are determined by the X and Y scale divisions which can be assigned with `setXDiv()` and `setYDiv()`. The `draw()` member draws the grid within a bounding rectangle. """ def __init__(self, title="Grid"): QwtPlotItem.__init__(self, title) self.__data = QwtPlotGrid_PrivateData() self.setItemInterest(QwtPlotItem.ScaleInterest, True) self.setZ(10.0)
[docs] @classmethod def make( cls, plot=None, z=None, enablemajor=None, enableminor=None, color=None, width=None, style=None, mincolor=None, minwidth=None, minstyle=None, ): """ Create and setup a new `QwtPlotGrid` object (convenience function). :param plot: Plot to attach the curve to :type plot: qwt.plot.QwtPlot or None :param z: Z-value :type z: float or None :param enablemajor: Tuple of two boolean values (x, y) for enabling major grid lines :type enablemajor: bool or None :param enableminor: Tuple of two boolean values (x, y) for enabling minor grid lines :type enableminor: bool or None :param color: Pen color for both major and minor grid lines (default: Qt.gray) :type color: QColor or str or None :param width: Pen width for both major and minor grid lines (default: 1.0) :type width: float or None :param style: Pen style for both major and minor grid lines (default: Qt.DotLine) :type style: Qt.PenStyle or None :param mincolor: Pen color for minor grid lines only (default: Qt.gray) :type mincolor: QColor or str or None :param minwidth: Pen width for minor grid lines only (default: 1.0) :type minwidth: float or None :param minstyle: Pen style for minor grid lines only (default: Qt.DotLine) :type minstyle: Qt.PenStyle or None .. seealso:: :py:meth:`setMinorPen()`, :py:meth:`setMajorPen()` """ item = cls() if z is not None: item.setZ(z) color = qcolor_from_str(color, Qt.gray) width = 1.0 if width is None else float(width) style = Qt.DotLine if style is None else style item.setPen(QPen(color, width, style)) if mincolor is not None or minwidth is not None or minstyle is not None: mincolor = qcolor_from_str(mincolor, Qt.gray) minwidth = 1.0 if width is None else minwidth minstyle = Qt.DotLine if style is None else minstyle item.setMinorPen(QPen(mincolor, minwidth, minstyle)) if enablemajor is not None: if isinstance(enablemajor, tuple) and len(enablemajor) == 2: item.enableX(enablemajor[0]) item.enableY(enablemajor[1]) else: raise TypeError( "Invalid enablemajor %r (expecting tuple of two booleans)" % enablemajor ) if enableminor is not None: if isinstance(enableminor, tuple) and len(enableminor) == 2: item.enableXMin(enableminor[0]) item.enableYMin(enableminor[1]) else: raise TypeError( "Invalid enableminor %r (expecting tuple of two booleans)" % enableminor ) if plot is not None: item.attach(plot) return item
[docs] def rtti(self): """ :return: Return `QwtPlotItem.Rtti_PlotGrid` """ return QwtPlotItem.Rtti_PlotGrid
[docs] def enableX(self, on): """ Enable or disable vertical grid lines :param bool on: Enable (true) or disable .. seealso:: :py:meth:`enableXMin()` """ if self.__data.xEnabled != on: self.__data.xEnabled = on self.legendChanged() self.itemChanged()
[docs] def enableY(self, on): """ Enable or disable horizontal grid lines :param bool on: Enable (true) or disable .. seealso:: :py:meth:`enableYMin()` """ if self.__data.yEnabled != on: self.__data.yEnabled = on self.legendChanged() self.itemChanged()
[docs] def enableXMin(self, on): """ Enable or disable minor vertical grid lines. :param bool on: Enable (true) or disable .. seealso:: :py:meth:`enableX()` """ if self.__data.xMinEnabled != on: self.__data.xMinEnabled = on self.legendChanged() self.itemChanged()
[docs] def enableYMin(self, on): """ Enable or disable minor horizontal grid lines. :param bool on: Enable (true) or disable .. seealso:: :py:meth:`enableY()` """ if self.__data.yMinEnabled != on: self.__data.yMinEnabled = on self.legendChanged() self.itemChanged()
[docs] def setXDiv(self, scaleDiv): """ Assign an x axis scale division :param qwt.scale_div.QwtScaleDiv scaleDiv: Scale division """ if self.__data.xScaleDiv != scaleDiv: self.__data.xScaleDiv = scaleDiv self.itemChanged()
[docs] def setYDiv(self, scaleDiv): """ Assign an y axis scale division :param qwt.scale_div.QwtScaleDiv scaleDiv: Scale division """ if self.__data.yScaleDiv != scaleDiv: self.__data.yScaleDiv = scaleDiv self.itemChanged()
[docs] def setPen(self, *args): """ Build and/or assign a pen for both major and minor grid lines .. py:method:: setPen(color, width, style) :noindex: Build and assign a pen for both major and minor grid lines In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it non cosmetic (see `QPen.isCosmetic()`). This method signature has been introduced to hide this incompatibility. :param QColor color: Pen color :param float width: Pen width :param Qt.PenStyle style: Pen style .. py:method:: setPen(pen) :noindex: Assign a pen for both major and minor grid lines :param QPen pen: New pen .. seealso:: :py:meth:`pen()`, :py:meth:`brush()` """ if len(args) == 3: color, width, style = args self.setPen(QPen(color, width, style)) elif len(args) == 1: (pen,) = args if self.__data.majorPen != pen or self.__data.minorPen != pen: self.__data.majorPen = pen self.__data.minorPen = pen self.legendChanged() self.itemChanged() else: raise TypeError( "%s().setPen() takes 1 or 3 argument(s) (%s given)" % (self.__class__.__name__, len(args)) )
[docs] def setMajorPen(self, *args): """ Build and/or assign a pen for both major grid lines .. py:method:: setMajorPen(color, width, style) :noindex: Build and assign a pen for both major grid lines In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it non cosmetic (see `QPen.isCosmetic()`). This method signature has been introduced to hide this incompatibility. :param QColor color: Pen color :param float width: Pen width :param Qt.PenStyle style: Pen style .. py:method:: setMajorPen(pen) :noindex: Assign a pen for the major grid lines :param QPen pen: New pen .. seealso:: :py:meth:`majorPen()`, :py:meth:`setMinorPen()`, :py:meth:`setPen()`, :py:meth:`pen()`, :py:meth:`brush()` """ if len(args) == 3: color, width, style = args self.setMajorPen(QPen(color, width, style)) elif len(args) == 1: (pen,) = args if self.__data.majorPen != pen: self.__data.majorPen = pen self.legendChanged() self.itemChanged() else: raise TypeError( "%s().setMajorPen() takes 1 or 3 argument(s) (%s " "given)" % (self.__class__.__name__, len(args)) )
[docs] def setMinorPen(self, *args): """ Build and/or assign a pen for both minor grid lines .. py:method:: setMinorPen(color, width, style) :noindex: Build and assign a pen for both minor grid lines In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it non cosmetic (see `QPen.isCosmetic()`). This method signature has been introduced to hide this incompatibility. :param QColor color: Pen color :param float width: Pen width :param Qt.PenStyle style: Pen style .. py:method:: setMinorPen(pen) :noindex: Assign a pen for the minor grid lines :param QPen pen: New pen .. seealso:: :py:meth:`minorPen()`, :py:meth:`setMajorPen()`, :py:meth:`setPen()`, :py:meth:`pen()`, :py:meth:`brush()` """ if len(args) == 3: color, width, style = args self.setMinorPen(QPen(color, width, style)) elif len(args) == 1: (pen,) = args if self.__data.minorPen != pen: self.__data.minorPen = pen self.legendChanged() self.itemChanged() else: raise TypeError( "%s().setMinorPen() takes 1 or 3 argument(s) (%s " "given)" % (self.__class__.__name__, len(args)) )
[docs] def draw(self, painter, xMap, yMap, canvasRect): """ Draw the grid The grid is drawn into the bounding rectangle such that grid lines begin and end at the rectangle's borders. The X and Y maps are used to map the scale divisions into the drawing region screen. :param QPainter painter: Painter :param qwt.scale_map.QwtScaleMap xMap: X axis map :param qwt.scale_map.QwtScaleMap yMap: Y axis :param QRectF canvasRect: Contents rectangle of the plot canvas """ minorPen = QPen(self.__data.minorPen) minorPen.setCapStyle(Qt.FlatCap) painter.setPen(minorPen) if self.__data.xEnabled and self.__data.xMinEnabled: self.drawLines( painter, canvasRect, Qt.Vertical, xMap, self.__data.xScaleDiv.ticks(QwtScaleDiv.MinorTick), ) self.drawLines( painter, canvasRect, Qt.Vertical, xMap, self.__data.xScaleDiv.ticks(QwtScaleDiv.MediumTick), ) if self.__data.yEnabled and self.__data.yMinEnabled: self.drawLines( painter, canvasRect, Qt.Horizontal, yMap, self.__data.yScaleDiv.ticks(QwtScaleDiv.MinorTick), ) self.drawLines( painter, canvasRect, Qt.Horizontal, yMap, self.__data.yScaleDiv.ticks(QwtScaleDiv.MediumTick), ) majorPen = QPen(self.__data.majorPen) majorPen.setCapStyle(Qt.FlatCap) painter.setPen(majorPen) if self.__data.xEnabled: self.drawLines( painter, canvasRect, Qt.Vertical, xMap, self.__data.xScaleDiv.ticks(QwtScaleDiv.MajorTick), ) if self.__data.yEnabled: self.drawLines( painter, canvasRect, Qt.Horizontal, yMap, self.__data.yScaleDiv.ticks(QwtScaleDiv.MajorTick), )
def drawLines(self, painter, canvasRect, orientation, scaleMap, values): x1 = canvasRect.left() x2 = canvasRect.right() - 1.0 y1 = canvasRect.top() y2 = canvasRect.bottom() - 1.0 for val in values: value = scaleMap.transform(val) if orientation == Qt.Horizontal: if qwtFuzzyGreaterOrEqual(value, y1) and qwtFuzzyLessOrEqual(value, y2): painter.drawLine(QLineF(x1, value, x2, value)) else: if qwtFuzzyGreaterOrEqual(value, x1) and qwtFuzzyLessOrEqual(value, x2): painter.drawLine(QLineF(value, y1, value, y2))
[docs] def majorPen(self): """ :return: the pen for the major grid lines .. seealso:: :py:meth:`setMajorPen()`, :py:meth:`setMinorPen()`, :py:meth:`setPen()` """ return self.__data.majorPen
[docs] def minorPen(self): """ :return: the pen for the minor grid lines .. seealso:: :py:meth:`setMinorPen()`, :py:meth:`setMajorPen()`, :py:meth:`setPen()` """ return self.__data.minorPen
[docs] def xEnabled(self): """ :return: True if vertical grid lines are enabled .. seealso:: :py:meth:`enableX()` """ return self.__data.xEnabled
[docs] def yEnabled(self): """ :return: True if horizontal grid lines are enabled .. seealso:: :py:meth:`enableY()` """ return self.__data.yEnabled
[docs] def xMinEnabled(self): """ :return: True if minor vertical grid lines are enabled .. seealso:: :py:meth:`enableXMin()` """ return self.__data.xMinEnabled
[docs] def yMinEnabled(self): """ :return: True if minor horizontal grid lines are enabled .. seealso:: :py:meth:`enableYMin()` """ return self.__data.yMinEnabled
[docs] def xScaleDiv(self): """ :return: the scale division of the x axis """ return self.__data.xScaleDiv
[docs] def yScaleDiv(self): """ :return: the scale division of the y axis """ return self.__data.yScaleDiv
[docs] def updateScaleDiv(self, xScaleDiv, yScaleDiv): """ Update the grid to changes of the axes scale division :param qwt.scale_map.QwtScaleMap xMap: Scale division of the x-axis :param qwt.scale_map.QwtScaleMap yMap: Scale division of the y-axis .. seealso:: :py:meth:`updateAxes()` """ self.setXDiv(xScaleDiv) self.setYDiv(yScaleDiv)