[Python] export a window in pdf [closed]

Discussão em 'Python' iniciado por Stack, Julho 29, 2025.

  1. Stack

    Stack Membro Participativo

    i got this code to export a window in pdf,it's just a sample and i will change it

    the problem is that i just cannot avoid the content to overlap the footer, the first table goes on the footer and overlap. Can someone help me? maybe giving me some tutorial to export in pdf if exists? this stuff is mostly AI, and i will study all this, but a tutorial could be better

    import sys
    from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QLabel,
    QTableWidget, QTableWidgetItem, QScrollArea, QHeaderView
    )
    from PySide6.QtPrintSupport import QPrinter
    from PySide6.QtGui import QPainter, QColor, QPageLayout, QPageSize
    from PySide6.QtCore import QRect, Qt, QPoint, QMarginsF
    import math

    class ReportCandidato(QMainWindow):
    def __init__(self):
    super().__init__()
    self.setWindowTitle("Generatore PDF con Widget Visibili")
    self.setGeometry(100, 100, 800, 600)

    self.scroll = QScrollArea()
    self.central_widget = QWidget()
    self.central_widget.setStyleSheet("background-color: white; color: black;")
    self.layout = QVBoxLayout(self.central_widget)

    # Bottone per generare PDF
    btn_pdf = QPushButton("Genera PDF")
    btn_pdf.clicked.connect(self.generate_pdf)
    self.layout.addWidget(btn_pdf)

    # Aggiungi 20 label
    for i in range(20):
    label = QLabel(f"Label {i + 1}: Questo è un testo di esempio per la label numero {i + 1}")
    label.setStyleSheet("""
    background-color: #f8f8f8;
    color: black;
    padding: 8px;
    border: 1px solid #ddd;
    margin: 2px;
    """)
    self.layout.addWidget(label)

    # Aggiungi 2 tabelle
    self.add_table(5, 4, "Tabella 1 - Dati Esempio")
    self.add_table(8, 5, "Tabella 2 - Altri Dati")

    self.scroll.setWidget(self.central_widget)
    self.scroll.setWidgetResizable(True)
    self.setCentralWidget(self.scroll)

    def add_table(self, rows, cols, title):
    title_label = QLabel(title)
    title_label.setStyleSheet("""
    font-weight: bold;
    font-size: 14px;
    margin-top: 20px;
    margin-bottom: 5px;
    color: black;
    """)
    self.layout.addWidget(title_label)

    table = QTableWidget(rows, cols)
    table.setStyleSheet("""
    QTableWidget {
    background-color: white;
    color: black;
    gridline-color: #ccc;
    }
    QHeaderView::section {
    background-color: #e0e0e0;
    color: black;
    padding: 5px;
    border: 1px solid #ccc;
    }
    """)

    for col in range(cols):
    table.setHorizontalHeaderItem(col, QTableWidgetItem(f"Colonna {col + 1}"))

    for row in range(rows):
    for col in range(cols):
    item = QTableWidgetItem(f"R{row + 1}C{col + 1}")
    item.setForeground(QColor(0, 0, 0))
    item.setBackground(QColor(255, 255, 255))
    table.setItem(row, col, item)

    table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

    table.resizeRowsToContents()
    total_height = table.verticalHeader().length() + table.horizontalHeader().height() + 2 * table.frameWidth()
    table.setFixedHeight(total_height)


    self.layout.addWidget(table)

    def generate_pdf(self):
    filename = "report_candidato.pdf"
    printer = QPrinter(QPrinter.HighResolution)
    printer.setOutputFormat(QPrinter.PdfFormat)
    printer.setOutputFileName(filename)

    # Margini in mm
    margin_left = 15
    margin_top = 15
    margin_right = 15
    margin_bottom = 25

    page_layout = QPageLayout()
    page_layout.setPageSize(QPageSize(QPageSize.A4))
    page_layout.setOrientation(QPageLayout.Portrait)
    page_layout.setMargins(QMarginsF(margin_left, margin_top, margin_right, margin_bottom))
    printer.setPageLayout(page_layout)

    painter = QPainter()
    if not painter.begin(printer):
    print("Errore nell'inizializzazione del QPainter")
    return

    try:
    dpi = printer.resolution()
    page_rect = printer.pageRect(QPrinter.DevicePixel)
    content = self.central_widget
    content_rect = content.rect()

    def mm_to_px(mm):
    return mm / 25.4 * dpi

    usable_width = page_rect.width()
    usable_height = page_rect.height()

    # Scala per adattare la larghezza alla pagina
    scale = usable_width / content_rect.width()

    total_scaled_height = content_rect.height() * scale
    pages_needed = max(1, math.ceil(total_scaled_height / usable_height))

    painter.setRenderHint(QPainter.Antialiasing)
    painter.setRenderHint(QPainter.TextAntialiasing)
    painter.setRenderHint(QPainter.SmoothPixmapTransform)

    for page in range(pages_needed):
    if page > 0:
    printer.newPage()

    painter.save()

    # Clip all'area della pagina (utile per non disegnare fuori pagina)
    painter.setClipRect(QRect(0, 0, usable_width, usable_height))

    # Sposta il contenuto verso l'alto per mostrare la pagina giusta
    painter.translate(0, -page * usable_height)

    # Scala in base alla larghezza
    painter.scale(scale, scale)

    # Renderizza il contenuto: usa tutta l'altezza, ma solo la parte visibile sarà mostrata grazie al clipping
    content.render(
    painter,
    QPoint(0, 0),
    QRect(0, 0, content_rect.width(), content_rect.height()),
    QWidget.RenderFlag.DrawWindowBackground | QWidget.RenderFlag.DrawChildren
    )

    painter.restore()

    # Disegna footer in basso (rispetto alla pagina intera)
    font = painter.font()
    font.setPointSize(10)
    painter.setFont(font)

    footer_y = usable_height - mm_to_px(0.3) # 10 mm sopra il bordo inferiore

    # Linea separatrice
    painter.drawLine(
    10, footer_y - 15,
    usable_width - 10, footer_y - 15
    )

    # Testo footer sinistra
    painter.drawText(
    15, footer_y,
    "Azienda sita in Via Roma 123, Milano"
    )

    # Numero pagina destra
    page_text = f"Pagina {page + 1} di {pages_needed}"
    text_width = painter.fontMetrics().horizontalAdvance(page_text)
    painter.drawText(
    usable_width - text_width - 15,
    footer_y,
    page_text
    )

    print(f"PDF generato correttamente in {pages_needed} pagine: {filename}")

    finally:
    painter.end()

    def draw_footer(self, painter, page_rect, full_page_height, current_page, total_pages):
    """Disegna il footer nell'area visibile del margine inferiore"""
    footer_text = "Azienda sita in Via Roma 123, Milano"
    page_text = f"Pagina {current_page} di {total_pages}"

    painter.save()

    # Imposta font per il footer
    font = painter.font()
    font.setPointSize(9)
    painter.setFont(font)

    # Posizione Y del testo footer (dentro il margine inferiore visibile)
    footer_y = page_rect.bottom() - 15 # 15px dal fondo utile (NON fondo pagina fisica)

    # Linea separatrice (10-12px sopra il testo)
    line_y = footer_y - 12
    painter.setPen(QColor(150, 150, 150)) # Colore grigio tenue per la linea
    painter.drawLine(
    page_rect.left() + 10,
    line_y,
    page_rect.right() - 10,
    line_y
    )

    # Testo azienda (allineato a sinistra)
    painter.drawText(
    page_rect.left() + 15,
    footer_y,
    footer_text
    )

    # Numero pagina (allineato a destra)
    text_width = painter.fontMetrics().horizontalAdvance(page_text)
    painter.drawText(
    page_rect.right() - text_width - 15, # 15px dal margine destro
    footer_y,
    page_text
    )

    painter.restore()


    if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = ReportCandidato()
    window.show()
    sys.exit(app.exec())

    Continue reading...

Compartilhe esta Página