Python项目学习二:项目2:绘制图表--初次实现

说明:博客,只展示练习后的代码,具体内容,请参考“Python基础教程”书籍。

遇到的坑:我用的Python解释器是3.6版本,但是ReportLab最新的,只有3.5版本的。我只好,更换了一下Python。更换Python解释器版本便捷方法:在PyCharm开发工具中,使用Conda Environment进行添加,上图:

 

 

 以上,是练习中遇到的坑。

初次实现,代码:我的代码中,有print函数,是为了加强理解用的。

from reportlab.lib import colors
from reportlab.graphics.shapes import *
from reportlab.graphics import renderPDF

data = [
    # Year Month Predicted	High	Low

    (2007, 8, 113.2, 114.2, 112.2),
    (2007, 9, 112.8, 115.8, 109.8),
    (2007, 10, 111.0, 116.0, 106.0),
    (2007, 11, 109.8, 116.8, 102.8),
    (2007, 12, 107.3, 115.3, 99.3),
    (2008, 1, 105.2, 114.2, 96.2),
    (2008, 2, 104.1, 114.1, 94.1),
    (2008, 3, 99.9, 110.9, 88.9),
    (2008, 4, 94.8, 106.8, 82.8),
    (2008, 5, 91.2, 104.2, 78.2),
]

# times = [200 * ((row[0] + row[1] / 12.0) - 2007) - 110 for row in data]
# print(times)


drawing = Drawing(200, 150)

pred = [row[2] - 40 for row in data]
# print(pred)
high = [row[3] - 40 for row in data]
low = [row[4] - 40 for row in data]
times = [200 * ((row[0] + row[1] / 12.0) - 2007) - 110 for row in data]

drawing.add(PolyLine(list(zip(times, pred)), strokeColor=colors.blue))
drawing.add(PolyLine(list(zip(times, high)), strokeColor=colors.red))
drawing.add(PolyLine(list(zip(times, low)), strokeColor=colors.green))

drawing.add(String(65, 115, 'Sunspots', fontSize=18, fillColor=colors.red))
renderPDF.drawToFile(drawing, 'report1.pdf', 'Sunspots')

 运行之后,会在如下目录生成report1.pdf文件:打开文件,如下:

 

 

源码解析,加强理解:

 

class Drawing(Group, Flowable):
    """Outermost container; the thing a renderer works on.
    This has no properties except a height, width and list
    of contents."""

    _saveModes=(
            'pdf','ps','eps','gif','png','jpg','jpeg','pct',
            'pict','tiff','tif','py','bmp','svg','tiffp','tiffl','tiff1',
            )

    _xtraAttrMap = AttrMap(
        width = AttrMapValue(isNumber,desc="Drawing width in points."),
        height = AttrMapValue(isNumber,desc="Drawing height in points."),
        canv = AttrMapValue(None),
        background = AttrMapValue(isValidChildOrNone,desc="Background widget for the drawing e.g. Rect(0,0,width,height)"),
        hAlign = AttrMapValue(OneOf("LEFT", "RIGHT", "CENTER", "CENTRE"), desc="Horizontal alignment within parent document"),
        vAlign = AttrMapValue(OneOf("TOP", "BOTTOM", "CENTER", "CENTRE"), desc="Vertical alignment within parent document"),
        #AR temporary hack to track back up.
        #fontName = AttrMapValue(isStringOrNone),
        renderScale = AttrMapValue(isNumber,desc="Global scaling for rendering"),
        )

    _attrMap = AttrMap(BASE=Group,
            formats = AttrMapValue(SequenceOf(
                OneOf('pdf','gif','png','tif','jpg','tiff','pct','pict',
                        'bmp','tiffp','tiffl','tiff1','eps','svg','ps','py'),
                lo=1,emptyOK=0), desc='One or more plot modes'),
            )
    _attrMap.update(_xtraAttrMap)

    def __init__(self, width=400, height=200, *nodes, **keywords):
        self.background = None
        Group.__init__(self,*nodes,**keywords)
        self.width = width
        self.height = height
        self.hAlign = 'LEFT'
        self.vAlign = 'BOTTOM'
        self.renderScale = 1.0

    def _renderPy(self):
        I = {'reportlab.graphics.shapes': ['_DrawingEditorMixin','Drawing','Group']}
        G = _renderGroupPy(self._explode(),'self',I)
        n = 'ExplodedDrawing_' + self.__class__.__name__
        s = '#Autogenerated by ReportLab guiedit do not edit\n'
        for m, o in I.items():
            s = s + 'from %s import %s\n' % (m,str(o)[1:-1].replace("'",""))
        s = s + '\nclass %s(_DrawingEditorMixin,Drawing):\n' % n
        s = s + '\tdef __init__(self,width=%s,height=%s,*args,**kw):\n' % (self.width,self.height)
        s = s + '\t\tDrawing.__init__(self,width,height,*args,**kw)\n'
        s = s + G
        s = s + '\n\nif __name__=="__main__": #NORUNTESTS\n\t%s().save(formats=[\'pdf\'],outDir=\'.\',fnRoot=None)\n' % n
        return s

    def draw(self,showBoundary=_unset_):
        """This is used by the Platypus framework to let the document
        draw itself in a story.  It is specific to PDF and should not
        be used directly."""
        from reportlab.graphics import renderPDF
        renderPDF.draw(self, self.canv, 0, 0, showBoundary=showBoundary)

    def wrap(self, availWidth, availHeight):
        width = self.width
        height = self.height
        renderScale = self.renderScale
        if renderScale!=1.0:
            width *= renderScale
            height *= renderScale
        return width, height

    def expandUserNodes(self):
        """Return a new drawing which only contains primitive shapes."""
        obj = Group.expandUserNodes(self)
        obj.width = self.width
        obj.height = self.height
        return obj

    def copy(self):
        """Returns a copy"""
        return self._copy(self.__class__(self.width, self.height))

    def asGroup(self,*args,**kw):
        return self._copy(Group(*args,**kw))

    def save(self, formats=None, verbose=None, fnRoot=None, outDir=None, title='', **kw):
        """Saves copies of self in desired location and formats.
        Multiple formats can be supported in one call

        the extra keywords can be of the form
        _renderPM_dpi=96 (which passes dpi=96 to renderPM)
        """
        genFmt = kw.pop('seqNumber','')
        if isinstance(genFmt,int):
            genFmt = '%4d: ' % genFmt
        else:
            genFmt = ''
        genFmt += 'generating %s file %s'
        from reportlab import rl_config
        ext = ''
        if not fnRoot:
            fnRoot = getattr(self,'fileNamePattern',(self.__class__.__name__+'%03d'))
            chartId = getattr(self,'chartId',0)
            if hasattr(chartId,'__call__'):
                chartId = chartId(self)
            if hasattr(fnRoot,'__call__'):
                fnRoot = fnRoot(chartId)
            else:
                try:
                    fnRoot = fnRoot % chartId
                except TypeError as err:
                    #the exact error message changed from 2.2 to 2.3 so we need to
                    #check a substring
                    if str(err).find('not all arguments converted') < 0: raise

        if os.path.isabs(fnRoot):
            outDir, fnRoot = os.path.split(fnRoot)
        else:
            outDir = outDir or getattr(self,'outDir','.')
        outDir = outDir.rstrip().rstrip(os.sep)
        if not outDir: outDir = '.'
        if not os.path.isabs(outDir): outDir = os.path.join(getattr(self,'_override_CWD',os.path.dirname(sys.argv[0])),outDir)
        if not os.path.isdir(outDir): os.makedirs(outDir)
        fnroot = os.path.normpath(os.path.join(outDir,fnRoot))
        plotMode = os.path.splitext(fnroot)
        if plotMode[1][1:].lower() in self._saveModes:
            fnroot = plotMode[0]

        plotMode = [x.lower() for x in (formats or getattr(self,'formats',['pdf']))]
        verbose = (verbose is not None and (verbose,) or (getattr(self,'verbose',verbose),))[0]
        _saved = logger.warnOnce.enabled, logger.infoOnce.enabled
        logger.warnOnce.enabled = logger.infoOnce.enabled = verbose
        if 'pdf' in plotMode:
            from reportlab.graphics import renderPDF
            filename = fnroot+'.pdf'
            if verbose: print(genFmt % ('PDF',filename))
            renderPDF.drawToFile(self, filename, title, showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPDF_',**kw))
            ext = ext +  '/.pdf'
            if sys.platform=='mac':
                import macfs, macostools
                macfs.FSSpec(filename).SetCreatorType("CARO", "PDF ")
                macostools.touched(filename)

        for bmFmt in ('gif','png','tif','jpg','tiff','pct','pict', 'bmp','tiffp','tiffl','tiff1'):
            if bmFmt in plotMode:
                from reportlab.graphics import renderPM
                filename = '%s.%s' % (fnroot,bmFmt)
                if verbose: print(genFmt % (bmFmt,filename))
                dtc = getattr(self,'_drawTimeCollector',None)
                if dtc:
                    dtcfmts = getattr(dtc,'formats',[bmFmt])
                    if bmFmt in dtcfmts and not getattr(dtc,'disabled',0):
                        dtc.clear()
                    else:
                        dtc = None
                renderPM.drawToFile(self, filename,fmt=bmFmt,showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPM_',**kw))
                ext = ext + '/.' + bmFmt
                if dtc: dtc.save(filename)

        if 'eps' in plotMode:
            try:
                from rlextra.graphics import renderPS_SEP as renderPS
            except ImportError:
                from reportlab.graphics import renderPS
            filename = fnroot+'.eps'
            if verbose: print(genFmt % ('EPS',filename))
            renderPS.drawToFile(self,
                                filename,
                                title = fnroot,
                                dept = getattr(self,'EPS_info',['Testing'])[0],
                                company = getattr(self,'EPS_info',['','ReportLab'])[1],
                                preview = getattr(self,'preview',rl_config.eps_preview),
                                showBoundary=getattr(self,'showBorder',rl_config.showBoundary),
                                ttf_embed=getattr(self,'ttf_embed',rl_config.eps_ttf_embed),
                                **_extraKW(self,'_renderPS_',**kw))
            ext = ext +  '/.eps'

        if 'svg' in plotMode:
            from reportlab.graphics import renderSVG
            filename = fnroot+'.svg'
            if verbose: print(genFmt % ('SVG',filename))
            renderSVG.drawToFile(self,
                                filename,
                                showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderSVG_',**kw))
            ext = ext +  '/.svg'

        if 'ps' in plotMode:
            from reportlab.graphics import renderPS
            filename = fnroot+'.ps'
            if verbose: print(genFmt % ('EPS',filename))
            renderPS.drawToFile(self, filename, showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPS_',**kw))
            ext = ext +  '/.ps'

        if 'py' in plotMode:
            filename = fnroot+'.py'
            if verbose: print(genFmt % ('py',filename))
            with open(filename,'wb') as f:
                f.write(asBytes(self._renderPy().replace('\n',os.linesep)))
            ext = ext +  '/.py'

        logger.warnOnce.enabled, logger.infoOnce.enabled = _saved
        if hasattr(self,'saveLogger'):
            self.saveLogger(fnroot,ext)
        return ext and fnroot+ext[1:] or ''

    def asString(self, format, verbose=None, preview=0, **kw):
        """Converts to an 8 bit string in given format."""
        assert format in ('pdf','ps','eps','gif','png','jpg','jpeg','bmp','ppm','tiff','tif','py','pict','pct','tiffp','tiffl','tiff1'), 'Unknown file format "%s"' % format
        from reportlab import rl_config
        #verbose = verbose is not None and (verbose,) or (getattr(self,'verbose',verbose),)[0]
        if format == 'pdf':
            from reportlab.graphics import renderPDF
            return renderPDF.drawToString(self)
        elif format in ('gif','png','tif','tiff','jpg','pct','pict','bmp','ppm','tiffp','tiffl','tiff1'):
            from reportlab.graphics import renderPM
            return renderPM.drawToString(self, fmt=format,showBoundary=getattr(self,'showBorder',
                            rl_config.showBoundary),**_extraKW(self,'_renderPM_',**kw))
        elif format == 'eps':
            try:
                from rlextra.graphics import renderPS_SEP as renderPS
            except ImportError:
                from reportlab.graphics import renderPS

            return renderPS.drawToString(self,
                                preview = preview,
                                showBoundary=getattr(self,'showBorder',rl_config.showBoundary))
        elif format == 'ps':
            from reportlab.graphics import renderPS
            return renderPS.drawToString(self, showBoundary=getattr(self,'showBorder',rl_config.showBoundary))
        elif format == 'py':
            return self._renderPy()

    def resized(self,kind='fit',lpad=0,rpad=0,bpad=0,tpad=0):
        '''return a base class drawing which ensures all the contents fits'''
        C = self.getContents()
        oW = self.width
        oH = self.height
        drawing = Drawing(oW,oH,*C)
        xL,yL,xH,yH = drawing.getBounds()
        if kind=='fit' or (kind=='expand' and (xL<lpad or xH>oW-rpad or yL<bpad or yH>oH-tpad)):
            drawing.width = xH-xL+lpad+rpad
            drawing.height = yH-yL+tpad+bpad
            drawing.transform = (1,0,0,1,lpad-xL,bpad-yL)
        elif kind=='fitx' or (kind=='expandx' and (xL<lpad or xH>oW-rpad)):
            drawing.width = xH-xL+lpad+rpad
            drawing.transform = (1,0,0,1,lpad-xL,0)
        elif kind=='fity' or (kind=='expandy' and (yL<bpad or yH>oH-tpad)):
            drawing.height = yH-yL+tpad+bpad
            drawing.transform = (1,0,0,1,0,bpad-yL)
        return drawing

其它的源代码,自己去分析的,如有需要,可以留言。

至此,本项目初次实现完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖哥真不错

您的鼓励,将是我最大的坚持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值