当前位置: 首页 > news >正文

Python 导出 PDF(ReportLab )

文章目录

  • 1. ReportLab 使用
    • 1.1. 安装 ReportLab
    • 1.2. 创建 PDF 文件
    • 1.3. 使用文档模板 DocTemplate
    • 1.4. 使用页面模板 PageTemplate
    • 1.5. 继承 BaseDocTemplate
    • 1.6. 使用 SimpleDocTemplate
    • 1.7. 继承Canvas
    • 1.8. 直接使用Canvas
  • 2. 字体与编码
  • 3. PLATYPUS - 页面布局和排版
    • 3.1. 设计目标
    • 3.2. 开始
    • 3.3. Flowables
      • 3.3.1. Flowable.draw()
      • 3.3.2. Flowable.drawOn(canvas,x,y)
      • 3.3.3. Flowable.wrap(availWidth, availHeight)
      • 3.3.4. Flowable.split(self, availWidth, availheight)
    • 3.4. 流动定位的准则
    • 3.5. Frames
      • 3.5.1. Frame.addFromList(drawlist, canvas)
      • 3.5.2. Frame.split(flowable,canv)
      • 3.5.3. Frame.drawBoundary(canvas)
    • 3.6. 文档和模板
      • 2.6.1. BaseDocTemplate.addPageTemplates(self,pageTemplates)
      • 3.6.2. BaseDocTemplate.build(self, flowables, filename=None,canvasmaker=canvas.Canvas)
      • 3.6.3. BaseDocTemplate.afterInit(self)
      • 3.6.4. BaseDocTemplate.afterPage(self)
      • 3.6.5. BaseDocTemplate.beforeDocument(self)
      • 3.6.6. BaseDocTemplate.beforePage(self)
      • 3.6.7. BaseDocTemplate.filterFlowables(self,flowables)
      • 3.6.8. BaseDocTemplate.afterFlowable(self, flowable)
  • 4. Paragraph(段落)
  • 5. Table(表格)
  • 6. VerticalBarChart(柱形图表)
    • 7.1. 控制柱形图颜色
  • 7. 饼状图
  • 8. Image(图像)

在 Python 中导出 PDF 文件,你可以使用多种库,其中最流行的是 ReportLab 和 FPDF。下面我将分别介绍如何使用这两个库来生成 PDF 文件。

官网:https://docs.reportlab.com/
英文手册:https://docs.reportlab.com/reportlab/userguide/ch1_intro/
中文手册:https://gitcode.com/Open-source-documentation-tutorial/d25f8/blob/main/reportlab%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C.pdf

1. ReportLab 使用

参考:
https://www.cnblogs.com/windfic/p/17157841.html

https://dev59.com/uF7Va4cB1Zd3GeqPKod0
https://www.jb51.net/article/270782.htm
https://www.osgeo.cn/python-tutorial/pdf-reportlab.html
https://blog.51cto.com/u_14940497/12374520
https://blog.csdn.net/qq_40596572/article/details/102896520
https://www.cnblogs.com/jilingxf/p/15857940.html

1.1. 安装 ReportLab

可以通过pip安装:

pip install reportlab

1.2. 创建 PDF 文件

下面是一个简单的示例,展示如何使用 ReportLab 创建一个包含文本和图像的 PDF 文件:

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics# 注册字体
song = "simsun"
pdfmetrics.registerFont(TTFont(song, "simsun.ttc"))
# pdfmetrics.registerFont(TTFont('MyFont', 'path/to/your/font.ttf'))# 创建一个PDF文件
c = canvas.Canvas("example.pdf", pagesize=letter)
c.setFont('simsun', 12)# 添加文本
# 默认情况下,(0,0)原点在页面的左下角。 此外,第一个坐标x往右走,第二个坐标y往上走,这是默认的。
c.drawString(10, 10, "Hello World!")# # 添加图像
c.drawImage('./image.jpg', 10, 60, width=500, height=500)# 保存PDF文件
c.save()

在这里插入图片描述

1.3. 使用文档模板 DocTemplate

Reportlab 的基础使用方式是创建内容块(Flowable),再使用文档模板(DocTemplate)创建 Pdf 文档。
关注点:
Paragraph(段落)、
Image(图像)、
Table(表格)、
VerticalBarChart(柱形图表)

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFontfrom reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph, SimpleDocTemplate, Image, Table
from reportlab.platypus import Spacer
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.legends import Legend
from reportlab.lib import  colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cmdef draw_text(st, text: str):return Paragraph(text, st)def draw_img(path):img = Image(path)       # 读取指定路径下的图片img.drawWidth = 6*cm    # 设置图片的宽度img.drawHeight = 5*cm   # 设置图片的高度return imgdef draw_table(*args):col_width = 120style = [('FONTNAME', (0, 0), (-1, -1), 'song'),  # 字体('FONTSIZE', (0, 0), (-1, 0), 12),  # 第一行的字体大小('FONTSIZE', (0, 1), (-1, -1), 10),  # 第二行到最后一行的字体大小('BACKGROUND', (0, 0), (-1, 0), '#d5dae6'),  # 设置第一行背景颜色('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 第一行水平居中('ALIGN', (0, 1), (-1, -1), 'LEFT'),  # 第二行到最后一行左右左对齐('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 所有表格上下居中对齐('TEXTCOLOR', (0, 0), (-1, -1), colors.darkslategray),  # 设置表格内文字颜色('GRID', (0, 0), (-1, -1), 0.5, colors.grey),  # 设置表格框线为grey色,线宽为0.5('SPAN', (0, 1), (2, 1)),  # 合并第二行一二三列]table = Table(args, colWidths=col_width, style=style)return tabledef draw_bar(bar_data: list, ax: list, items: list):drawing = Drawing(500, 200)bc = VerticalBarChart()bc.x = 45       # 整个图表的x坐标bc.y = 45      # 整个图表的y坐标bc.height = 150     # 图表的高度bc.width = 350      # 图表的宽度bc.data = bar_databc.strokeColor = colors.black       # 顶部和右边轴线的颜色bc.valueAxis.valueMin = 0           # 设置y坐标的最小值bc.valueAxis.valueMax = 20         # 设置y坐标的最大值bc.valueAxis.valueStep = 5         # 设置y坐标的步长bc.categoryAxis.labels.dx = 2bc.categoryAxis.labels.dy = -8bc.categoryAxis.labels.angle = 20bc.categoryAxis.labels.fontName = 'song'bc.categoryAxis.categoryNames = ax# 图示leg = Legend()leg.fontName = 'song'leg.alignment = 'right'leg.boxAnchor = 'ne'leg.x = 475         # 图例的x坐标leg.y = 140leg.dxTextSpace = 10leg.columnMaximum = 3leg.colorNamePairs = itemsdrawing.add(leg)drawing.add(bc)return drawingdef main(filename):pdfmetrics.registerFont(TTFont('song', 'STSONG.ttf'))style = getSampleStyleSheet()ts = style['Heading1']ts.fontName = 'song'    # 字体名ts.fontSize = 18        # 字体大小ts.leading = 30         # 行间距ts.alignment = 1        # 居中ts.bold = Truehs = style['Heading2']hs.fontName = 'song'    # 字体名hs.fontSize = 15        # 字体大小hs.leading = 20         # 行间距hs.textColor = colors.red  # 字体颜色ns = style['Normal']ns.fontName = 'song'ns.fontSize = 12ns.wordWrap = 'CJK'     # 设置自动换行ns.alignment = 0        # 左对齐ns.firstLineIndent = 32 # 第一行开头空格ns.leading = 20content = []content.append(draw_text(ts, '经典游戏盘点'))content.append(draw_img('./image.jpg'))content.append(Spacer(1, 1*cm))content.append(draw_text(ns, ' 《超级马里奥兄弟》于1985年9月13日发售,这是一款任天堂针对FC主机全力度身订造的游戏,被称为TV游戏奠基之作。这个游戏被赞誉为电子游戏的原始范本,确立了角色、游戏目的、流程分布、操作性、隐藏要素、BOSS、杂兵等以后通用至今的制作概念。《超级马里奥兄弟》成为游戏史首部真正意义上的超大作游戏,游戏日本本土销量总计681万份,海外累计更是达到了3342万份的天文数字。'))content.append(draw_text(hs, '经典游戏列表'))# 添加表格data = [('经典游戏', '发布年代', '发行商'),('TOP100',),('超级马里奥兄弟', '1985年', '任天堂'),('坦克大战', '1985年', '南梦宫'),('魂斗罗', '1987年', '科乐美'),('松鼠大战', '1990年', '卡普空'),]content.append(draw_table(*data))# 生成图表content.append(draw_text(hs, '游戏厂商统计'))b_data = [(2, 4, 6, 12, 8, 16), (12, 14, 17, 9, 12, 7)]ax_data = ['任天堂', '南梦宫', '科乐美', '卡普空', '世嘉', 'SNK']leg_items = [(colors.red, '街机'), (colors.green, '家用机')]content.append(draw_bar(b_data, ax_data, leg_items))# 生成pdf文件doc = SimpleDocTemplate(filename, pagesize=A4, topMargin=35)doc.build(content)if __name__ == '__main__':main(filename='example1.pdf')

在这里插入图片描述

1.4. 使用页面模板 PageTemplate

上述的排版都是线性的,如果要有一些混排,比如列式排版,可以使用BalancedColumns,有一些页面排版比较复杂,那可以使用页面模板(PageTemplate)。
其实还可以用传统Web艺能——Table来做排版,我试了一下,只需要指定BOX,GRID为白色即可,线宽为0不行。
关注点:
PageTemplate(页面模板)
Frame(框架)

from reportlab.lib.colors import Color
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
from reportlab.lib import  colors
from reportlab.platypus import BaseDocTemplate, Frame, Paragraph, NextPageTemplate, PageBreak, PageTemplate, Image
from reportlab.lib.units import inchdef draw_text(st, text: str):return Paragraph(text, st)def draw_img(path):img = Image(path)       # 读取指定路径下的图片img.drawWidth = 5*cm    # 设置图片的宽度img.drawHeight = 4*cm   # 设置图片的高度return imgdef main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))style = getSampleStyleSheet()ts = style['Heading1']ts.fontName = 'simsun'      # 字体名ts.fontSize = 18            # 字体大小ts.leading = 30             # 行间距ts.alignment = 1            # 居中ts.bold = Truehs = style['Heading2']hs.fontName = 'simsun'      # 字体名hs.fontSize = 15            # 字体大小hs.leading = 20             # 行间距hs.textColor = colors.red   # 字体颜色ns = style['Normal']ns.fontName = 'simsun'ns.fontSize = 12ns.wordWrap = 'CJK'     # 设置自动换行ns.alignment = 0        # 左对齐ns.firstLineIndent = 32 # 第一行开头空格ns.leading = 20doc = BaseDocTemplate(filename, showBoundary=0, pagesize=A4)frameT = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal')# 一分为三w = doc.width / 3# 高度等于宽度h = w# 上面一行 底部bm = doc.height - h# 上面一行 左列frame1 = Frame(doc.leftMargin,      bm, w,           h, id='col1')# 上面一行 右列frame2 = Frame(doc.leftMargin + w,  bm, doc.width-w, h, id='col2')# 下面一行frame3 = Frame(doc.leftMargin, doc.bottomMargin, doc.width , bm-doc.topMargin, id='col3')doc.addPageTemplates([PageTemplate(id='TwoCol', frames=[frame1, frame2, frame3]),PageTemplate(id='OneCol', frames=frameT),])elements = []#### 适配 PageTemplate TwoCol# 上面一行 左列elements.append(draw_img("./image.jpg"))# 上面一行 右列elements.append(draw_text(ns, '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 。'))elements.append(draw_text(ns, '22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 。'))elements.append(draw_text(ns, '33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 。'))#### 适配 PageTemplate OneColelements.append(NextPageTemplate('OneCol'))# 强制换页elements.append(PageBreak())elements.append(draw_text(ns, "Frame one column, 44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 。"))#### 适配 PageTemplate TwoColelements.append(NextPageTemplate('TwoCol'))elements.append(PageBreak())elements.append(draw_img("./image.jpg"))elements.append(draw_text(ns, '55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 。'))elements.append(draw_img("./image.jpg"))elements.append(draw_text(ns, '55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 。'))doc.build(elements)if __name__ == '__main__':main(filename='example2.pdf')
-------------------------------------在这里插入图片描述-------------------------------------

1.5. 继承 BaseDocTemplate

前两种方式都不能精确输出,依赖于模板的排版,精确输出需要Canvas接口。
如果你要在每一页上显示页眉和页脚,那么你可以继承文档模板(BaseDocTemplate)。
如果你要添加目录索引,这就是最方便的方式。
覆盖接口:
handle_documentBegin
handle_pageBegin
handle_pageEnd
handle_frameBegin
handle_frameEnd
handle_flowable
handle_nextPageTemplate
handle_currentFrame
handle_nextFrame
或者实现回调函数:
afterInit
beforeDocument
beforePage
afterPage
filterFlowables
afterFlowable
关注点:
BaseDocTemplate(文档模板)
bookmarkPage(书签)
addOutlineEntry(大纲)

from reportlab.lib.styles import ParagraphStyle
from reportlab.platypus import PageBreak
from reportlab.platypus.paragraph import Paragraph
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus.frames import Frame
from reportlab.lib.units import cmclass MyDocTemplate(BaseDocTemplate):def __init__(self, filename, **kw):self.allowSplitting = 0BaseDocTemplate.__init__(self, filename, **kw)template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')])self.addPageTemplates(template)self.chapter = 0self.section = 0def afterFlowable(self, flowable):if isinstance(flowable, Paragraph):text = flowable.getPlainText()style = flowable.style.nameif style == 'Title':self.chapter += 1# # 书签# self.canv.bookmarkPage(f"chapter{self.chapter}")# # 大纲# self.canv.addOutlineEntry(f"Chapter {self.chapter}", f"chapter{self.chapter}", level=0)# 书签 参数为索引(个人理解)self.canv.bookmarkPage(f"chapter{self.chapter}")# self.canv.bookmarkPage(key=)# 目录 参数为 标题、索引、层级self.canv.addOutlineEntry(text, f"chapter{self.chapter}", level=0)# self.canv.addOutlineEntry(title=, key=, level=)elif style == 'Heading1':self.section += 1self.canv.bookmarkPage(f"section{self.section}")self.canv.addOutlineEntry(f"Section {self.section}", f"section{self.section}", level=1)def main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))ts = ParagraphStyle(name = 'Title',fontName = 'simsun',fontSize = 22,leading = 16,alignment = 1,spaceAfter = 20)h1 = ParagraphStyle(name = 'Heading1',fontSize = 14,leading = 16)story = []story.append(Paragraph('继承BaseDocTemplate', ts))story.append(Paragraph('Section 1', h1))story.append(Paragraph('Text in Section 1.1'))# 分页story.append(PageBreak())story.append(Paragraph('Section 2', h1))story.append(Paragraph('Text in Section 1.2'))# 分页story.append(PageBreak())story.append(Paragraph('Chapter 2', ts))story.append(Paragraph('Section 1', h1))story.append(Paragraph('Text in Section 2.1'))doc = MyDocTemplate(filename)doc.build(story)if __name__ == '__main__':main(filename='example3.pdf')

在这里插入图片描述

在这里插入图片描述--------------------------------------------------------------------------

1.6. 使用 SimpleDocTemplate

SimpleDocTemplate就是继承BaseDocTemplate的一种简单实现,它覆盖了接口handle_pageBegin,重载了build接口。
它把页面分成两种:首页和后续页,对应回调两个过程onFirstPage=, onLaterPages=,只需要实现这两个回调过程即可。
适用显示页眉和页脚,其它的功能就有限了。
关注点:
SimpleDocTemplate(文档模板)
QrCode(二维码)
drawOn(显示Flowable)

from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.platypus import PageBreak
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.colors import Color
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.graphics.barcode import qr#首页
def myFirstPage(canvas, doc):canvas.saveState()canvas.setFillColorRGB(0, 0, 0)canvas.setFont('simsun',12)str="(内部资料)"canvas.drawCentredString(doc.width/2, 25*mm, str)myLaterPages(canvas, doc)canvas.restoreState()#页眉页脚
def myLaterPages(canvas, doc):canvas.saveState()canvas.setStrokeColorRGB(0.8, 0.8, 0.8)canvas.line(0, 32, doc.width, 32)canvas.line(0, A4[1]-45, doc.width, A4[1]-45)canvas.setFillColorRGB(0, 0, 0)canvas.setFont('simsun',10)str=f"Page {doc.page}"canvas.drawCentredString(doc.width/2, 5*mm, str)canvas.setFillColorRGB(1, 0, 0)canvas.drawCentredString(doc.width/2, A4[1]-9*mm, "XX有限公司版权所有")qr_code = qr.QrCode('https://www.cnblogs.com/windfic', width=45, height=45)canvas.setFillColorRGB(0, 0, 0)qr_code.drawOn(canvas, 0, A4[1]-45)canvas.restoreState()def main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))doc = SimpleDocTemplate(filename, pagesize=A4, leftMargin=10, rightMargin=10)title = ParagraphStyle(name = 'Title',fontName = 'simsun',fontSize = 22,leading = 16,alignment = 1,spaceAfter = 20)contents = []contents.append(Paragraph('使用SimpleDocTemplate', title))contents.append(Paragraph('Hello'))contents.append(PageBreak())contents.append(Paragraph('World'))contents.append(PageBreak())contents.append(Paragraph('World2'))doc.build(contents, onFirstPage=myFirstPage, onLaterPages=myLaterPages)if __name__ == '__main__':main(filename='example4.pdf')
---------------------------------------------------------------------------------------------------------------

1.7. 继承Canvas

控制Canvas的另一种方法是继承Canvas。
与继承文档模板(DocTemplate)类似,不过网上能找到的例子也就是显示页码,不是很实用。

from reportlab.platypus import SimpleDocTemplate, Image, Paragraph, PageBreak
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from reportlab.lib.colors import Color
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.styles import ParagraphStyleclass NumberedCanvas(canvas.Canvas):def __init__(self, *args, **kwargs):canvas.Canvas.__init__(self, *args, **kwargs)self._saved_page_states = []def showPage(self):self._saved_page_states.append(dict(self.__dict__))self._startPage()def save(self):"""add page info to each page (page x of y)"""num_pages = len(self._saved_page_states)for state in self._saved_page_states:self.__dict__.update(state)self.draw_page_number(num_pages)canvas.Canvas.showPage(self)canvas.Canvas.save(self)def draw_page_number(self, page_count):self.setFont("Helvetica", 9)self.setStrokeColor(Color(0, 0, 0, alpha=0.5))self.line(10*mm, 15*mm, A4[0] - 10*mm, 15*mm)self.setFillColor(Color(0, 0, 0, alpha=0.5))self.drawCentredString(A4[0]/2, 10*mm, "Page %d of %d" % (self._pageNumber, page_count))def main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))title = ParagraphStyle(name = 'Title',fontName = 'simsun',fontSize = 22,leading = 16,alignment = 1,spaceAfter = 20)image = Image("image.jpg")image.drawWidth = 160# image.drawHeight = 160*(image.imageHeight/image.imageWidth)# image.drawHeight = 160*(image.imageWidth/image.imageHeight)image.drawHeight = 160elements = [Paragraph('继承Canvas', title),Paragraph("Hello"),image,PageBreak(),Paragraph("world"),PageBreak(),image,]doc = SimpleDocTemplate(filename)doc.build(elements, canvasmaker=NumberedCanvas)if __name__ == "__main__":main(filename='example5.pdf')
---------------------------------------------------------------------------------------------------------------

1.8. 直接使用Canvas

当PDF内容非常复杂,难以用以上的方法实现,可以直接使用Canvas创建PDF
直接使用Canvas类,可以精确输出,但需要自己排版,而且它的坐标原点在左下角。
其中也可以放置Flowable,需要排版的Flowable,如Table等,调用warp函数即可自动排版。
如果是内容已经排版的格式转换程序,非常推荐使用这种方式。

from reportlab.pdfgen import canvas
from reportlab.platypus import Image, Table
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.colors import Color
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib import  colors
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.legends import Legend
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph
from reportlab.graphics.barcode import qrdef draw_bar(bar_data: list, ax: list, items: list):drawing = Drawing(500, 200)bc = VerticalBarChart()bc.x = 45           # 整个图表的x坐标bc.y = 45           # 整个图表的y坐标bc.height = 150     # 图表的高度bc.width = 350      # 图表的宽度bc.data = bar_databc.strokeColor = colors.black       # 顶部和右边轴线的颜色bc.valueAxis.valueMin = 0           # 设置y坐标的最小值bc.valueAxis.valueMax = 20          # 设置y坐标的最大值bc.valueAxis.valueStep = 5          # 设置y坐标的步长bc.categoryAxis.labels.dx = 2bc.categoryAxis.labels.dy = -8bc.categoryAxis.labels.angle = 20bc.categoryAxis.labels.fontName = 'simsun'bc.categoryAxis.categoryNames = ax# 图示leg = Legend()leg.fontName = 'simsun'leg.alignment = 'right'leg.boxAnchor = 'ne'leg.x = 475         # 图例的x坐标leg.y = 140leg.dxTextSpace = 10leg.columnMaximum = 3leg.colorNamePairs = itemsdrawing.add(leg)drawing.add(bc)return drawingdef draw_table(*args):col_width = 120style = [('FONTNAME', (0, 0), (-1, -1), 'simsun'),  # 字体('FONTSIZE', (0, 0), (-1, 0), 12),  # 第一行的字体大小('FONTSIZE', (0, 1), (-1, -1), 10),  # 第二行到最后一行的字体大小('BACKGROUND', (0, 0), (-1, 0), '#d5dae6'),  # 设置第一行背景颜色('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 第一行水平居中('ALIGN', (0, 1), (-1, -1), 'LEFT'),  # 第二行到最后一行左右左对齐('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 所有表格上下居中对齐('TEXTCOLOR', (0, 0), (-1, -1), colors.darkslategray),  # 设置表格内文字颜色('GRID', (0, 0), (-1, -1), 0.5, colors.grey),  # 设置表格框线为grey色,线宽为0.5('SPAN', (0, 1), (2, 1)),  # 合并第二行一二三列]table = Table(args, colWidths=col_width, style=style)return tabledef draw_page_number(c, page, count):c.setFillColorRGB(1, 0, 0)c.setFont("simsun", 9)c.drawCentredString(A4[0]/2, A4[1]-9*mm, "XX有限公司版权所有")qr_code = qr.QrCode('https://www.cnblogs.com/windfic', width=45, height=45)c.setFillColorRGB(0, 0, 0)qr_code.drawOn(c, 0, A4[1]-45)c.line(10*mm, A4[1]-45, A4[0], A4[1]-45)c.setFont("simsun", 9)c.setStrokeColor(Color(0, 0, 0, alpha=0.5))c.line(10*mm, 15*mm, A4[0] - 10*mm, 15*mm)c.setFillColor(Color(0, 0, 0, alpha=0.5))c.drawCentredString(A4[0]/2, 10*mm, "Page %d of %d" % (page, count))def main(filename):# pdfmetrics.registerFont(TTFont('微软雅黑', 'msyh.ttf'))pdfmetrics.registerFont(TTFont('simsun', "simsun.ttc"))c = canvas.Canvas(filename)c.bookmarkPage("title")c.addOutlineEntry("my book", "title", level=0)c.setFont("simsun", 16)c.setFillColor(Color(0, 0, 1, alpha=0.9))c.drawString(320, A4[1] - 95, "超级马里奥兄弟")c.setFont("simsun", 12)c.setFillColor(Color(0, 0, 0, alpha=0.7))c.drawString(320, A4[1] - 125, "SUPER MARIO BROS.")c.drawString(320, A4[1] - 195, "1985年9月13日发售")img = Image("./image.jpg")img.drawWidth = 160# img.drawHeight = 160*(img.imageHeight/img.imageWidth)# img.drawHeight = int(160*(img.imageHeight/img.imageWidth))img.drawHeight = 160# print("image", img.imageHeight, img.imageWidth, (img.imageHeight/img.imageWidth), 160*(img.imageHeight/img.imageWidth), img.drawHeight)img.drawOn(c, 150, A4[1]-200)data = [('经典游戏', '发布年代', '发行商'),('TOP100',),('超级马里奥兄弟', '1985年', '任天堂'),('坦克大战', '1985年', '南梦宫'),('魂斗罗', '1987年', '科乐美'),('松鼠大战', '1990年', '卡普空'),]t = draw_table(*data)t.wrap(800, 600)t.drawOn(c, 50, A4[1] - 400)styleSheet = getSampleStyleSheet()style = styleSheet['BodyText']style.fontName = "simsun"p=Paragraph(' 《超级马里奥兄弟》于1985年9月13日发售,这是一款任天堂针对FC主机全力度身订造的游戏,被称为TV游戏奠基之作。这个游戏被赞誉为电子游戏的原始范本,确立了角色、游戏目的、流程分布、操作性、隐藏要素、BOSS、杂兵等以后通用至今的制作概念。《超级马里奥兄弟》成为游戏史首部真正意义上的超大作游戏,游戏日本本土销量总计681万份,海外累计更是达到了3342万份的天文数字。',style)p.wrap(A4[0]-100, 100)p.drawOn(c, 50, A4[1] - 280)b_data = [(2, 4, 6, 12, 8, 16), (12, 14, 17, 9, 12, 7)]ax_data = ['任天堂', '南梦宫', '科乐美', '卡普空', '世嘉', 'SNK']leg_items = [(colors.red, '街机'), (colors.green, '家用机')]d = draw_bar(b_data, ax_data, leg_items)d.drawOn(c, 50, A4[1] - 620)draw_page_number(c, 1, 2)c.bookmarkPage("section1")c.addOutlineEntry("first section", "section1", level=1)c.showPage()c.drawString(50, A4[1] - 70, "World")draw_page_number(c, 2, 2)c.bookmarkPage("section2")c.addOutlineEntry("second section", "section2", level=1)c.showPage()c.showOutline()c.save()if __name__ == "__main__":main(filename='example6.pdf')

在这里插入图片描述

2. 字体与编码

https://blog.csdn.net/qq_40596572/article/details/102896520
字体
https://blog.csdn.net/qtlyx/article/details/99653081

3. PLATYPUS - 页面布局和排版

3.1. 设计目标

Platypus 是"Page Layout and Typography Using Scripts"的缩写。它是一个高水平的页面布局库, 让你可以用最少的努力以编程方式创建复杂的文档。
Platypus 的设计力求将 "高层次 "的布局决定与文档内容尽可能分开 。例如,段落使用段落样式,页面使用页面模板,目的是让数百个有数千页的文件可以按照不同的样式规格重新格式化,只需在一个包含段落样式和页面布局规格的共享文件中修改几行即可。
Platypus的整体设计可以认为有几个层次,自上而下,这些是:
DocTemplates 作为文档的最外层容器。
PageTemplates 作为各种页面布局的规格。
Frames 页面中可包含流动文本或图形的区域规格。
Flowables 对应"flowed into the document"流入文档的文本或图形元素(即图像、段落和表格等内容,但不包括页脚或固定页面图形等内容)。
pdfgen.Canvas 为最终从其他图层接收文档绘画的最低层。
在这里插入图片描述
上面的插图形象地说明了 DocTemplate、PageTemplate 和 Flowables 的概念 。然而,它具有欺骗性,因为每一个 PageTemplate 实际上可以指定任何数量的页面的格式(而不是像从图中推断的那样只指定一个)。
DocTemplate 包含一个或多个 PageTemplate,每个 PageTemplate 包含一个或多个Frame。
Flowables 是指可以 flowed(流入) Frame的东西,例如 Paragraph 或 Table。
要使用 platypus,你需要从 DocTemplate 类中创建一个文档,并向其 build 方法传递一个 Flowables列表。document 的 build 方法知道如何将 flowable 列表处理成合理的东西。
在内部,DocTemplate 类使用各种事件来实现页面布局和格式化。每个事件都有一个对应的处理方法,称为 handle_XXX ,其中 XXX 是事件名称。一个典型的事件是 frameBegin,它发生在机械开始第一次使用一个框架的时候。
Platypus 故事由一系列基本元素组成,这些元素被称为 Flowables,它们驱动着数据驱动的 Platypus格式化引擎。为了修改引擎的行为,一种特殊的可流式元素 ActionFlowables 告诉布局引擎,例如,跳到下一列或者换成另一个 PageTemplate。

3.2. 开始

考虑以下代码序列,它为 Platypus 提供了一个非常简单的 "hello world "例子。

from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize
from reportlab.lib.units import inchPAGE_HEIGHT=defaultPageSize[1]
PAGE_WIDTH=defaultPageSize[0]styles = getSampleStyleSheet()
Title = "Hello world"
pageinfo = "platypus example"# 首页
def myFirstPage(canvas, doc):canvas.saveState()# 标题canvas.setFont('Times-Bold',16)canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, Title)# 页脚 填充固定字符canvas.setFont('Times-Roman',9)canvas.drawString(inch, 0.75 * inch, "First Page / %s" % pageinfo)canvas.restoreState()# 非首页
def myLaterPages(canvas, doc):canvas.saveState()# 页脚 填充页码canvas.setFont('Times-Roman',9)canvas.drawString(inch, 0.75 * inch, "Page %d %s" % (doc.page, pageinfo))canvas.restoreState()def main(filename: str):doc = SimpleDocTemplate(filename)# 与标题间隔Story = [Spacer(1, 2*inch)]style = styles["Normal"]for i in range(100):bogustext = ("This is Paragraph number %s. " % i) * 5p = Paragraph(bogustext, style)Story.append(p)# 段落之间间隔Story.append(Spacer(1, 0.2*inch))# 添加doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)if __name__ == '__main__':main(filename='example.pdf')

我们创建一个"store"并构建文档。请注意,我们在这里使用的是"canned"(罐头)文档模板,它是预建的页面模板。
我们还使用了预建的段落样式 。
我们在这里只使用了两种类型的"flowables"–Spacers和Paragraphs 。第一个Spacer确保段落跳过标题字符串。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

3.3. Flowables

Flowables 是可以被绘制的东西,它有wrap, draw和可能的split方法。Flowable 是一个抽象的基类,用于绘制事物,一个实例知道它的大小,并在它自己的坐标系中绘制(这需要基 API 在调用 Flowable.draw方法时提供一个绝对坐标系)。要获得一个实例,使用 f=Flowable()。
注意: Flowable 类是一个抽象类,通常只作为基类使用.
为了说明使用 Flowables 的一般方式,我们将展示如何在画布上使用和绘制衍生类 Paragraph。

def main(filename):from reportlab.lib.styles import getSampleStyleSheetfrom reportlab.platypus import Paragraphfrom reportlab.pdfgen.canvas import CanvasstyleSheet = getSampleStyleSheet()style = styleSheet['BodyText']P=Paragraph('This is a very silly example',style)canv = Canvas(filename)aW = 460 # available width and heightaH = 800w,h = P.wrap(aW, aH) # find required spaceif w<=aW and h<=aH:P.drawOn(canv,0,aH)aH = aH - h # reduce the available heightcanv.save()else:raise ValueError("Not enough room")if __name__ == '__main__':main(filename='example.pdf')

在这里插入图片描述

3.3.1. Flowable.draw()

这将被调用来要求 flowable 实际渲染自己。Flowable类没有实现draw。调用代码应该确保 flowable 有一个属性canv,它pdfgen.Canvas,它应该被绘制到Canvas上,并且Canvas处于一个适当的状态(就翻译、旋转等而言)。通常这个方法只在内部被drawOn方法调用,派生类必须实现这个方法。派生类必须实现这个方法。

3.3.2. Flowable.drawOn(canvas,x,y)

这是控制引擎用来将flowable渲染到特定画布的方法。它处理转换为画布坐标(x,y),并确保flowable有一个canv属性,这样draw方法(在基类中没有实现)就可以在一个绝对坐标框架中渲染。

3.3.3. Flowable.wrap(availWidth, availHeight)

在询问对象的大小、绘制或其他什么之前,这个函数将被包围的框架调用。它返回实际使用的尺寸。

3.3.4. Flowable.split(self, availWidth, availheight)

当wrap失败时,更复杂的框架会调用这个函数。愚蠢的flowables应该返回[],这意味着它们无法拆分。聪明的flowables应该自己拆分并返回一个flowables列表。客户端代码要确保避免重复尝试拆分。如果空间足够,拆分方法应该返回[self]。否则,flowable应该重新排列,并返回一个按顺序考虑的flowable列表[f0,…]。实现的拆分方法应该避免改变self,因为这将允许复杂的布局机制在一个可流动的列表上进行多次递。

3.4. 流动定位的准则

有两种方法,默认情况下返回零,为可流动物的垂直间距提供指导。
Flowable.getSpaceAfter(self):
Flowable.getSpaceBefore(self):
这些方法会返回flowable后面或前面应该有多少空间。这些空间不属于flowable本身,也就是说,flowable的draw方法在渲染时不应该考虑它。控制程序将使用返回的值来确定上下文中特定flowable需要多少空间。
所有的flowables都有一个hAlign属性:(‘LEFT’,‘RIGHT’,‘CENTER’或’CENTRE’)。对于占满整个框架宽度的段落,这个属性没有影响。对于小于框架宽度的表格、图像或其他对象,这决定了它们的水平位置。
下面的章节将涵盖最重要的特定类型的可流动文件,段落和表格。

3.5. Frames

Frames是活动的容器,它本身就包含在PageTemplate中,Frames有一个位置和大小,并保持一个剩余可绘制空间的概念。如:

Frame(x1, y1, width, height, leftPadding=6, bottomPadding=6, rightPadding=6, topPadding=6, id=None, showBoundary=0)

创建一个左下角坐标为(x1,y1)的Frame实例(在使用时相对于画布),尺寸为 width x height。Padding参数是用于减少绘画空间的正量。参数id是运行时使用的标识符,例如"LeftColumn"或"RightColumn"等。如果showBoundary参数是非零,那么框架的边界将在运行时被绘制出来(这有时很有用)。
Frames可以直接与canvases和flowables一起使用来创建文档。Frame.addFromList方法为你处理wrap 和 drawOn调用。你不需要所有的Platypus引擎来获得有用的东西到PDF中。

def main(filename): from reportlab.pdfgen.canvas import Canvasfrom reportlab.lib.styles import getSampleStyleSheetfrom reportlab.lib.units import inchfrom reportlab.platypus import Paragraph, Framestyles = getSampleStyleSheet()styleN = styles['Normal']styleH = styles['Heading1']story = []#add some flowablesstory.append(Paragraph("This is a Heading",styleH))story.append(Paragraph("This is a paragraph in <i>Normal</i> style.",styleN))c = Canvas(filename)f = Frame(inch, inch, 6*inch, 9*inch, showBoundary=1)f.addFromList(story,c)c.save()if __name__ == '__main__':main(filename='example.pdf')

在这里插入图片描述

3.5.1. Frame.addFromList(drawlist, canvas)

消耗drawlist前面的Flowables,直到帧满为止。如果不能容纳一个对象,则引发一个异常。

3.5.2. Frame.split(flowable,canv)

要求flowable使用可用空间进行分割,并返回flowable的列表。

3.5.3. Frame.drawBoundary(canvas)

将框架边界画成一个矩形(主要用于调试)。

3.6. 文档和模板

BaseDocTemplate类
实现了文档格式化的基本机制。该类的一个实例包含了一个或多个PageTemplate的列表,这些PageTemplate可用于描述单页信息的布局。build方法可用于处理Flowables列表,以生成一个PDF文档。

from reportlab.lib.pagesizes import A4
from reportlab.platypus import BaseDocTemplate
from reportlab.lib.units import inchBaseDocTemplate(filename,pagesize=A4,pageTemplates=[],showBoundary=0,		# 控制是否绘制Frame的边界,这对于调试来说是很有用的leftMargin=inch,rightMargin=inch,topMargin=inch,bottomMargin=inch,allowSplitting=1,	# allowSplitting参数决定了内置方法是否应该尝试split单个Flowables跨越Frametitle=None,author=None,_pageBreakQuick=1,	# 参数决定了在结束页面之前,是否应该尝试结束页面上的所有框架encrypt=None		# encrypt 参数决定了是否对文档进行加密,以及如何加密)

创建一个适合创建基本文档的文档模板。它带有相当多的内部机制,但没有默认的页面模板。所需的filename可以是一个字符串,一个用于接收创建的PDF文档的文件名;也可以是一个有write方法的对象,如 BytesIO 或 file 或 socket。
showBoundary控制是否绘制Frame的边界,这对于调试来说是很有用的。
allowSplitting参数决定了内置方法是否应该尝试split单个Flowables跨越Frame。
_pageBreakQuick参数决定了在结束页面之前,是否应该尝试结束页面上的所有框架。
encrypt 参数决定了是否对文档进行加密,以及如何加密。默认情况下,文档是不加密的。如果encrypt是一个字符串对象,那么它将作为pdf的用户密码。如果encrypt是一个reportlab.lib.pdfencrypt.StandardEncryption的实例,那么这个对象就被用来加密pdf。这允许对加密设置进行更精细的控制。

PageTemplate类
是一个语义相当简单的容器类。每个实例都包含一个Frames的列表,并且有一些方法应该在每个页面的开始和结束时被调用。

PageTemplate(id=None, frames=[], onPage=_doNothing, onPageEnd=_doNothing)

用于初始化一个实例,frames参数应该是一个Frames的列表,而可选的onPageonPageEnd参数是可调用的,它们的签名应该是 def XXX(canvas,document),其中canvas和document是正在绘制的画布和文档。这些例程的目的是用来绘制页面的非流动(即标准)部分。
这些属性函数与纯虚拟方法 PageTemplate.beforPage 和 PageTemplate.afterPage完全平行,这两个方法的签名是 beforPage(self,canvas,document)。这些方法允许使用类派生来定义标准行为,而属性则允许改变实例。在运行时,id 参数用于执行 PageTemplate 的切换,所以 id=‘FirstPage’ 或 id='TwoColumns’是典型的。

2.6.1. BaseDocTemplate.addPageTemplates(self,pageTemplates)

此方法用于在现有文档中添加一个或一系列PageTemplate。

3.6.2. BaseDocTemplate.build(self, flowables, filename=None,canvasmaker=canvas.Canvas)

这是应用程序程序员感兴趣的主要方法。假设文档实例被正确设置,build方法将story以flowables
列表的形式接收(flowables参数),并在列表中循环,将flowables列表一次一个地强制通过格式化
机制。实际上,这使得BaseDocTemplate实例发出对实例handle_XXX方法的调用来处理各种事件。

3.6.3. BaseDocTemplate.afterInit(self)

这个方法在基类初始化后被调用;派生类可以覆盖该方法来添加默认的PageTemplates。

3.6.4. BaseDocTemplate.afterPage(self)

这是在页面处理后,紧接着当前页面模板的afterDrawPage方法被调用。一个派生类可以使用这个方
法来做一些依赖于页面信息的事情,比如字典页面上的首字和尾字。

3.6.5. BaseDocTemplate.beforeDocument(self)

在对文档进行任何处理之前,但在处理机制准备好之后,就会调用这个函数,因此它可以用来对实
例的pdfgen.canvas等进行处理。因此,它可以用来对实例的pdfgen.canvas等进行操作。

3.6.6. BaseDocTemplate.beforePage(self)

这是在页面处理开始时,在当前页面模板的beforeDrawPage方法之前调用的。它可以用来重置页面
特定的信息持有者。

3.6.7. BaseDocTemplate.filterFlowables(self,flowables)

在主 handle_flowable 方法开始时,调用这个函数来过滤flowables。在返回时,如果flowables[0]
被设置为None,则会被丢弃,主方法立即返回。

3.6.8. BaseDocTemplate.afterFlowable(self, flowable)

在flowable被渲染后调用。有兴趣的类可以使用这个钩子来收集特定页面或框架上存在的信息。

4. Paragraph(段落)

5. Table(表格)

https://www.cnblogs.com/jilingxf/p/15857940.html

6. VerticalBarChart(柱形图表)

7.1. 控制柱形图颜色

https://dev59.com/uF7Va4cB1Zd3GeqPKod0

7. 饼状图

8. Image(图像)

相关文章:

Python 导出 PDF(ReportLab )

文章目录 1. ReportLab 使用1.1. 安装 ReportLab1.2. 创建 PDF 文件1.3. 使用文档模板 DocTemplate1.4. 使用页面模板 PageTemplate1.5. 继承 BaseDocTemplate1.6. 使用 SimpleDocTemplate1.7. 继承Canvas1.8. 直接使用Canvas 2. 字体与编码3. PLATYPUS - 页面布局和排版3.1. 设…...

私域运营的底层逻辑:从流量到留存的进阶之路

私域流量已成为企业营销的新战场&#xff0c;但盲目跟风只会事倍功半。 接下来&#xff0c;我将深入剖析私域运营的底层逻辑&#xff0c;从几个关键环节&#xff0c;助你构建高效稳定的私域体系。 一、价值优先&#xff1a;以用户需求为核心 私域运营并非简单的粉丝积累&…...

【数据结构 · 初阶】- 带头双向循环链表

目录 1.尾插 2.初始化 3.尾删、头插、头删 4.查找&#xff0c;返回 pos 指针 5.pos 前插入 优化头插&#xff0c;直接复用 优化尾插&#xff0c;直接复用 6.pos 位删除 头删尾删简化 7.销毁 整体代码 List.h List.c Test.c 循环&#xff1a;1.尾 next 指向哨兵位…...

Cube IDE常用快捷键

STM32CubeIDE常用快捷键 STM32CubeIDE快捷键很多&#xff0c;可以通过 Help > Show Active Keybindings… 查看当前可用快捷键&#xff1b;也可以在 Window > Preferences > General > Keys 中查看修改快捷键 快捷键快捷键说明Ctrl/注释行/取消注释行CtrlD删除行…...

C++开发中的DUMP文件:解决崩溃与性能问题的利器(全文字数2w+)

[外链图片转存中…(img-mf6LznjF-1744717065188)] 文章目录 前言为什么需要了解DUMPDUMP在C开发中的重要性 一、DUMP基础概念1. 什么是DUMP文件2. DUMP文件的类型3. DUMP文件的作用&#xff08;1&#xff09;调试程序崩溃&#xff08;2&#xff09;分析程序性能&#xff08;3&a…...

Golang|接口并发测试和压力测试

文章目录 这里出现某些奖品和数据库中库存量不一致的问题原因就是在并发的情况下&#xff0c;sync.Map仍然会出现脏写问题&#xff0c;就是在同时操作下的操作覆盖问题可以先把数据放到channel里&#xff0c;然后用一个单一的协程负责读取channel并写入map...

解决 Maven 500 错误:无法传输 maven-metadata.xml 文件

在使用 Maven 构建和管理 Java 项目时&#xff0c;可能会遇到类似以下的错误信息&#xff1a; [WARNING] Could not transfer metadata com.ha:xxx-model:2025.0.1.SNAPSHOT/maven-metadata.xml from/to public (http://xxx.xx.xx.xx/repository/maven-public): status code: …...

鸿蒙应用开发—鸿蒙app一键安装脚本

背景 当鸿蒙App开发完后需要提测&#xff0c;如何将App文件发给QA安装测试&#xff0c;是一件麻烦事&#xff0c;因为鸿蒙App并不能像Android Apk那样可以直接安装到设备中&#xff0c;能想到的方式有&#xff1a; 直接叫测试拿手机过来安装让测试安装DevEco Studio 拉代码编…...

opencv二值化实验

二值化实验 1二值化说明2 阈值法&#xff08;THRESH_BINARY&#xff09;3.反阈值法&#xff08;THRESH_BINARY_INV&#xff09;4截断阈值法&#xff08;THRESH_TRUNC&#xff09;5 低阈值零处理&#xff08;THRESH_TOZERO&#xff09;6 超阈值零处理&#xff08;THRESH_TOZERO_…...

3DGS之渲染管线

渲染管线&#xff08;Rendering Pipeline&#xff09;是计算机图形学中将三维场景转换为二维屏幕图像的核心流程&#xff0c;涉及CPU与GPU的分工协作。计算机图形学把渲染管线分为三个阶段&#xff1a;应用程序阶段、几何阶段、光栅化阶段。渲染管线的一般流程是&#xff1a;顶…...

C#设计模式-状态模式

状态模式案例解析&#xff1a;三态循环灯的实现 案例概述 本案例使用 状态模式&#xff08;State Pattern&#xff09; 实现了一个 三态循环灯 的功能。每点击一次按钮&#xff0c;灯的状态会按顺序切换&#xff08;状态1 → 状态2 → 状态3 → 状态1...&#xff09;&#xff…...

泛微相关文档以及相关安装包下载

泛微相关文档以及相关安装包下载 泛微相关安装包下载泛微相关安装包下载 泛微E10登录网址:https://www.e-cology.com.cn/login?service=https%3A%2F%2Fwww.e-cology.com.cn%2F Ecode使用说明:https://e-cloudstore.com/doc.html 泛微组件库:https://cloudstore.e-cology…...

软件包安装管理Gitlab

官方提供了非常详尽的系统及自动化脚本安装教程 Gitlab官网下载地址&#xff1a;https://gitlab.cn/install/ 1、安装配置 今天我们说一下包安装管理&#xff0c;这样方便我们自己更精确的制定符合我们自己需要的Gitlab仓库 配置&#xff1a;ubuntu2004(focal) 4C8G 下载程…...

在Java使用rest Client操作ES

1. 导入restClient依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.12.1</version></dependency> 2. 了解ES核心客户端API 核心区别…...

深入解析Linux软件包管理:apt/yum源配置与Vim编辑器高效使用指南

一、Linux软件包管理与开发工具 1.软件包管理器与Linux软件生态 软件包管理器的作用与分类 什么是软件包&#xff1f; 在Linux下安装软件&#xff0c;一个通常的办法是下载到程序的源代码&#xff0c;并进行编译&#xff0c;得到可执行程序。但是这样太麻烦了&#xff0c;于…...

小程序css实现容器内 数据滚动 无缝衔接 点击暂停

<view class"gundongBox"><!-- 滚动展示信息的模块 --><image class"imgWid" :src"imgurlgundong.png" mode"widthFix"></image><view class"gundongView"><view class"container&qu…...

记录 | Pycharm中如何调用Anaconda的虚拟环境

目录 前言一、步骤Step1 查看anaconda 环境名Step2 Python项目编译器更改 更新时间 前言 参考文章&#xff1a; 参考视频&#xff1a;如何在pycharm中使用Anaconda创建的python环境 自己的感想 这里使用的Pycharm 2024专业版的。我所使用的Pycharm专业版位置&#xff1a;【仅用…...

静态站点生成

以下是关于 静态站点生成(SSG) 的系统知识梳理,涵盖核心概念、核心实现、数据管理与优化等内容: 一、核心概念与优势 定义 静态站点生成(SSG)是在构建阶段预生成所有静态HTML文件的技术,用户访问时直接获取预渲染内容,无需服务器动态生成。 核心优势 性能卓越:CDN缓存…...

Android Jni(二)加载调用第三方 so 库

文章目录 Android Jni&#xff08;二&#xff09;加载调用第三方 so 库前置知识CPU架构 ABI 基本步骤1、将第三方 SO 库文件放入项目中的正确位置&#xff1a;2. 创建 JNI 接口3. 实现 JNI 层代码4、配置 CMake 常见问题解决1、UnsatisfiedLinkError&#xff1a;2、函数找不到&…...

解锁元生代:ComfyUI工作流与云原生后端的深度融合

目录 蓝耘元生代&#xff1a;智算新势力崛起​ ComfyUI 工作流创建详解​ ComfyUI 初印象​ 蓝耘平台上搭建 ComfyUI 工作流​ 构建基础工作流实操​ 代码示例与原理剖析​ 云原生后端技术全景 云原生后端概念解析​ 核心技术深度解读​ 蓝耘元生代中两者的紧密联系​…...

LeetCode算法题(Go语言实现)_47

题目 给你一个 m x n 的迷宫矩阵 maze &#xff08;下标从 0 开始&#xff09;&#xff0c;矩阵中有空格子&#xff08;用 ‘.’ 表示&#xff09;和墙&#xff08;用 ‘’ 表示&#xff09;。同时给你迷宫的入口 entrance &#xff0c;用 entrance [entrancerow, entrancecol…...

树莓派_利用Ubuntu搭建gitlab

树莓派_利用Ubuntu搭建gitlab 一、给树莓派3A搭建基本系统 1、下载系统镜像 https://cdimage.ubuntu.com/ubuntu/releases/18.04/release/ 2、准备系统SD卡 二、给树莓派设备联网 1、串口后台登录 使用串口登录后台是最便捷的&#xff0c;因为前期网络可能不好直接成功 默…...

vi(vim)编辑器和root用户与普通用户之间的转换

vim编辑器是vi编辑器的加强版&#xff0c;以vi为例&#xff1a; vi编辑器&#xff1a; vi编辑器可以编辑文件内容 如何进入vi编辑器&#xff1f; 语法&#xff1a; vi 文件路径 如何退出&#xff1f; 语法&#xff1a; wq&#xff1a;保存退出 w&#xff1a;保存 q&…...

【vscode】vscode链接关联github/gitlab

一、windows下载安装git Git - Downloading Package 二、配置Git的用户名和邮箱 Git Bash运行以下命令来配置Git的用户名和邮箱&#xff1a; git config --global user.name "你的用户名" git config --global user.email "你的邮箱地址" 生成本机秘钥…...

Redis面试问题缓存相关详解

Redis面试问题缓存相关详解 一、缓存三兄弟&#xff08;穿透、击穿、雪崩&#xff09; 1. 穿透 问题描述&#xff1a; 缓存穿透是指查询一个数据库中不存在的数据&#xff0c;由于缓存不会保存这样的数据&#xff0c;每次都会穿透到数据库&#xff0c;导致数据库压力增大。例…...

Web三漏洞学习(其一:文件上传漏洞)

靶场:云曦历年考核题 一、文件上传 在此之前先准备一个一句话木马 将其命名为muma.txt 23年秋期末考 来给师兄上个马 打开环境以后直接上传muma.txt&#xff0c;出现js弹窗&#xff0c;说明有前端验证 提示只能上传.png .jpg 和 .gif文件&#xff0c;那就把muma.txt的后缀…...

冲刺高分!挑战7天一篇nhanes机器学习SCI!DAY1-7

医学生集合啦&#xff0c;继续挑战 7天一篇nhanes机器学习SCI&#xff01; Day 1 进展&#xff1a;确定选题、期刊、文献 前面挑战了一期NHANES机器学习&#xff0c;大家使用NHANES的发文章的热情&#xff0c;火爆程度远超想象&#xff01;我在下面的评论区看到大家的学习欲…...

高并发三剑客-本地缓存之王Caffeine-01缓存应用

1 分布式缓存使用及导致的问题 1.1 hotkey典型业务场景 常规性hotkey&#xff1a;可以提前评估出hotkey的场景&#xff0c;比如&#xff1a;重要节假日、促销活动等 突发性hotkey&#xff1a;没法提前评估&#xff0c;突发性行为&#xff0c;比如&#xff1a;突然新闻、爆炸信息…...

基于Java,SpringBoot,Vue,HTML家政服务预约系统设计

摘要 本文聚焦于基于Java、SpringBoot、Vue和HTML技术的家政服务预约系统的设计与实现。该系统旨在为家政服务的供需双方搭建一个便捷、高效的在线交互平台。后端采用Java语言结合SpringBoot框架&#xff0c;充分利用SpringBoot的自动配置和快速开发特性&#xff0c;实现系统业…...

系统架构设计师:系统架构概述知识体系、考点详解、高效记忆要点、练习题并提供答案与解析

一、系统架构概述知识体系、考点详解 系统架构概述、定义与作用 1. 系统架构的定义与核心要素 系统架构是复杂系统的高层次组织结构&#xff0c;包含硬件/软件组件、交互关系、设计原则及演进策略。其核心要素包括&#xff1a; 构件与模式&#xff1a;现代架构三要素为构件…...

汽配快车道解决chrome backgroud.js(Service Worker) XMLHttpRequest is not defined问题

Chrome 扩展开发&#xff1a;Service Worker 中如何优雅地发送 HTTP 请求 在 Chrome 扩展开发中&#xff0c;Service Worker 是一个非常重要的部分&#xff0c;它可以帮助我们实现很多强大的功能。然而&#xff0c;如果你在 Service Worker 中尝试使用 XMLHttpRequest 来发送 …...

VMware Ubuntu挂载Windows机器的共享文件

https://www.dong-blog.fun/post/2029 在VMware Ubuntu中访问Windows共享文件夹&#xff1a;完整指南 在使用VMware运行Ubuntu虚拟机时&#xff0c;访问Windows主机上的文件是常见需求。本文将详细介绍如何通过网络共享方式&#xff0c;让Ubuntu虚拟机直接访问Windows主机的文…...

LeNet神经网络

一、LeNet概述 1. 历史地位 开创性模型&#xff1a;首个成功应用的卷积神经网络&#xff08;1998年&#xff09;应用场景&#xff1a;手写数字识别&#xff08;MNIST数据集&#xff09;、银行支票识别提出者&#xff1a;Yann LeCun团队&#xff08;论文《Gradient-Based Lear…...

Visio绘图工具全面科普:解锁专业图表绘制新境界[特殊字符]

Visio绘图工具全面科普&#xff1a;解锁专业图表绘制新境界&#x1f31f; 在信息爆炸的时代&#xff0c;清晰、直观地呈现复杂信息变得至关重要。无论是绘制流程图&#x1f4ca;、组织结构图&#x1f465;&#xff0c;还是规划网络拓扑&#x1f5a7;&#xff0c;一款强大的绘图…...

ECharts散点图-散点图3,附视频讲解与代码下载

引言&#xff1a; ECharts散点图是一种常见的数据可视化图表类型&#xff0c;它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图&#xff0c;包括图表效果预览、视频讲解及代码下载&#xff0c;让你轻松掌握…...

D3路网图技术文档

在本文档中&#xff0c;我们将探讨如何使用 D3.js&#xff0c;结合 SVG&#xff08;可缩放矢量图形&#xff09;和 Canvas&#xff0c;来实现高效、交互性强的路网图效果。D3.js 是一个强大的 JavaScript 数据可视化库&#xff0c;可以基于数据驱动文档对象模型&#xff08;DOM…...

Unity 一些小功能(屏幕画画,)

利用 Line Renderer 实现屏幕画画并保存图片 // 当前正在绘制的 LineRendererprivate LineRenderer currentLineRenderer;// 用于保存所有笔触的列表private List<LineRenderer> allLineRenderers new List<LineRenderer>();// 当前笔触顶点计数器private int ve…...

列表、字符串、heapq堆对列算法

1、列表 1.1 访问最后一个元素 list [1, 2, 3, 4, 5, 6] print(list[-1]) # 61.2 访问列表指定范围&#xff0c;例如第1-4个元素 print(list[0, 4]) # [1, 2, 3, 4]1.3 将字符列表以字符串形式输出 list [h, e, l, l, o] ls "".join(list) print(ls) # "…...

实战指南:封装Whisper为FastAPI接口并实现高并发处理

下面给出一个详细的示例&#xff0c;说明如何使用 FastAPI 封装 OpenAI 的 Whisper 模型&#xff0c;提供一个对外的 REST API 接口&#xff0c;并支持一定的并发请求。 下面是主要步骤和示例代码。 1. 环境准备 Python 环境&#xff1a; 建议使用 Python 3.8。依赖库&#x…...

Arm系统ubuntu20.04中自带的火狐浏览器打开网页B站视频和百度网盘网页视频,视频无法打开,并且没有声音——(本质上解决)

自己工作过程中有一台Orin nx arm设备&#xff0c;所以希望能够用这台设备看视频学习&#xff0c;发现自带的firefox打开网页版百度网盘和B站的时候无法打开视频&#xff0c;而且用有线耳机发现没有声音&#xff0c;最后换掉浏览器&#xff0c;用Chromium。 1、如果还想继续用…...

Qt 自定义控件

在 Qt 中&#xff0c;自定义控件是通过继承现有的 Qt 控件类&#xff08;如 QWidget、QPushButton、QLabel 等&#xff09;并重载相关的事件处理函数或绘制函数来实现的。自定义控件允许你根据需求添加特定的功能或样式。 自定义控件的基本步骤 1. 继承 Qt 控件类&#xff1a…...

Java使用WebSocket视频拆帧进度处理与拆帧图片推送,结合Apipost进行调试

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>Configuration public class WebSocketConfig {/*** 启动 WebSocket 服务器*/Beanpublic ServerEndpointE…...

Java项目之基于ssm的QQ村旅游网站的设计(源码+文档)

项目简介 QQ村旅游网站实现了以下功能&#xff1a; 管理员权限操作的功能包括管理景点路线&#xff0c;板块信息&#xff0c;留言板信息&#xff0c;旅游景点信息&#xff0c;酒店信息&#xff0c;对景点留言&#xff0c;景点路线留言以及酒店留言信息等进行回复&#xff0c;…...

《 Reinforcement Learning for Education: Opportunities and Challenges》全文阅读

Reinforcement Learning for Education: Opportunities and Challenges 面向教育的强化学习&#xff1a;机遇与挑战 摘要 本综述文章源自作者在 Educational Data Mining (EDM) 2021 会议期间组织的 RL4ED 研讨会。我们组织了这一研讨会&#xff0c;作为一项社区建设工作的组…...

Apache Kafka UI :一款功能丰富且美观的 Kafka 开源管理平台!!

Apache Kafka UI 是一个免费的开源 Web UI&#xff0c;用于监控和管理 Apache Kafka 集群&#xff0c;可方便地查看 Kafka Brokers、Topics、消息、Consumer 等情况&#xff0c;支持多集群管理、性能监控、访问控制等功能。 1 特征 多集群管理&#xff1a; 在一个地方监控和管理…...

无参数RCE

无参数RCE&#xff08;Remote Code Execution&#xff0c;远程代码执行&#xff09; 是一种通过利用目标系统中的漏洞&#xff0c;在不直接传递用户可控参数的情况下&#xff0c;实现远程执行任意代码的攻击技术。与传统的RCE攻击不同&#xff0c;无参数RCE不依赖外部输入参数…...

设计模式之状态模式:优雅管理对象行为变化

引言 状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在其内部状态改变时改变它的行为&#xff0c;使对象看起来似乎修改了它的类。状态模式将状态转移逻辑和状态相关行为封装在独立的状态类中&#xff0c;完美解决了复杂条件判断问…...

拖动滑块 代替验证码,识别机器人的方式,实验原理

拖动滑块验证是一种常见的人机验证技术&#xff0c;用于区分真实用户和自动化程序&#xff08;如机器人&#xff09;。其核心原理不仅在于用户是否能将滑块移动到正确位置&#xff0c;还包括对拖动行为的轨迹、速度、加速度等特征的分析。以下是其实现原理及识别机器人的方式&a…...

深度访谈:数据中台的本质不是技术堆砌,而是业务引擎的重构

在数字化转型进入深水区的今天&#xff0c;企业逐渐意识到单纯的技术堆砌无法解决业务核心痛点。数据的割裂、重复建设的烟囱式系统、滞后于业务的分析能力&#xff0c;正迫使企业寻找“系统性解法”。 “未来的竞争&#xff0c;本质是数据响应速度的竞争。当竞争对手还在讨论‘…...

Spark中Maven的用法

在IDEA中去创建项目&#xff0c;并编写java代码来操作集群中的文件 1.IDEA 中创建 Maven 项目 步骤一&#xff1a;点击 File -> New -> Project&#xff0c;在弹出的窗口左侧选择 Maven&#xff0c;点击 Next&#xff1a; 步骤二&#xff1a;填写项目的 GroupId、Arti…...