Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
464 views
in Technique[技术] by (71.8m points)

python - Is it possible to get a Flowable's coordinate position once it's rendered using ReportLab.platypus?

My main goal is to have all the Image flowables on a page to act as though they are clickable links. In order to do this, I would create a canvas.linkRect() and place it over the rendered Image. Here's an example of how I use canvas.linkRect():

canvas.linkURL(
    url='url_goes_here',
    rect=(x1, y1, x2, y2), #(x1, y1) is the bottom left coordinate of the rectangle, (x2, y2) is the top right
    thickness=0, relative=1
)

After looking in the BaseDocTemplate class, I found a method called afterFlowable(self, flowable). I overrode that method and called dir() on the flowable passed in, resulting in this:

['__call__', '__doc__', '__init__', '__module__', '_doctemplateAttr',
'_drawOn', '_fixedHeight', '_fixedWidth', '_frameName', '_hAlignAdjust',
'_showBoundary', '_traceInfo', 'action', 'apply', 'draw', 'drawOn', 'encoding',
'getKeepWithNext', 'getSpaceAfter', 'getSpaceBefore', 'hAlign', 'height',
'identity', 'isIndexing', 'locChanger', 'minWidth', 'split', 'splitOn', 'vAlign',
'width', 'wrap', 'wrapOn', 'wrapped']

It has a width and height attribute I could use to determine how big the linkRect() should be (what x2 and y2 should be), but no information on where the flowable starts (what should x1 and y1 be?).

If all else fails, I thought of somehow pairing a Frame and an Image Flowable together since a Frame has the information I want to create a linkRect(). However, it seems it would be a hassle to know when and how to order a list of Frames with it's respective list of Flowables, on top of having to know exactly where to put those Frames for Images. Is there another way to achieve this or is it not possible?

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After working on this all day today, I finally figured out a nice way to do this! Here's how I did it for anyone else who would like this feature of hyperlinked Image flowables in their PDFs.

Basically, reportlab.platypus.flowables has a class called Flowable that Image inherits from. Flowable has a method called drawOn(self, canvas, x, y, _sW=0) that I override in a new class I created called HyperlinkedImage.

from reportlab.platypus import Image

class HyperlinkedImage(Image, object):

    # The only variable I added to __init__() is hyperlink. I default it to None for the if statement I use later.
    def __init__(self, filename, hyperlink=None, width=None, height=None, kind='direct', mask='auto', lazy=1):
        super(HyperlinkedImage, self).__init__(filename, width, height, kind, mask, lazy)
        self.hyperlink = hyperlink

    def drawOn(self, canvas, x, y, _sW=0):
        if self.hyperlink: # If a hyperlink is given, create a canvas.linkURL()
            x1 = self.hAlignAdjust(x, _sW) # This is basically adjusting the x coordinate according to the alignment given to the flowable (RIGHT, LEFT, CENTER)
            y1 = y
            x2 = x1 + self._width
            y2 = y1 + self._height
            canvas.linkURL(url=self.hyperlink, rect=(x1, y1, x2, y2), thickness=0, relative=1)
        super(HyperlinkedImage, self).drawOn(canvas, x, y, _sW)

Now instead of creating a reportlab.platypus.Image as your image flowable, use the new HyperlinkedImage instead :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...