es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

PYQT5 – Enlace a la página en el PDF exportado.

Estoy creando una aplicación para dibujar instrucciones para un usuario.
El que crea las instrucciones puede agregar varias páginas y luego exportarlas a .pdf.
Todo eso funciona bien, excepto que no puedo obtener enlaces entre las diferentes páginas.

Quiero agregar una página inicial que muestre todas las páginas y tenga enlaces a ellas (tabla de contenido) y agregar un botón en cada página que enlace a la página siguiente / anterior.

Lo que actualmente tengo para exportar es esto:

def exportar_pagina_a_pdf(self):
    """Exportar las páginas actuales a pdf."""
    impresora = QtPrintSupport.QPrinter()
    impresora.setFormatoSalida(QtPrintSupport.QPrinter.PdfFormat)
    impresora.setNombreArchivoSalida("instrucciones.pdf")
    impresora.setTamañoPagina(QtGui.QPageSize(self.tamaño_página, QtGui.QPageSize.Píxel))

painter = QtGui.QPainter(impresora)
for número_página in rango(self.__cantidad_páginas):
    self.establecer_página(número_página)

    escala_x = self.__página.ancho() / self.ancho()
    escala_y = self.__página.alto() / self.alto()
    painter.escalar(escala_x, escala_y)

    self.renderizar(painter)

    if número_página < self.__cantidad_páginas - 1:
        painter.restablecerTransformación()
        impresora.páginaNueva()
painter.finalizar()

self.establecer_página(número_página) cambia la página actual para que se pueda renderizar la solicitada. self.establecer_página(0) contiene la página con la tabla de contenido.

Todas las páginas se muestran en una QGraphicsScene.
Agradecería cualquier sugerencia sobre cómo crear los enlaces entre estas páginas.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para crear enlaces entre páginas en un PDF, puedes utilizar la biblioteca PyPDF2 en Python. Puedes crear una instancia de la clase PdfFileWriter, y para cada página, crear un diccionario con el tipo de acción establecido en “GoTo” y el destino establecido en el número de página. Luego, agrega este diccionario a la clave /Annots del objeto de la página.

    Para la tabla de contenidos, puedes crear una página separada y agregar objetos de texto con enlaces, cada uno con un diccionario de acción que apunte al número de página correspondiente.

    Para agregar un botón en cada página que enlace a la página siguiente o anterior, puedes agregar anotaciones clicables a la página actual con el tipo de acción establecido en “Named” y el destino establecido en “/Next” o “/Prev”.

    Para implementar esta funcionalidad en PyQt5, puedes conectar las señales apropiadas (por ejemplo, linkActivated) a las ranuras correspondientes en tu código de aplicación.

    Aquí tienes un ejemplo de implementación:

    import PyPDF2
    
    def create_links(pdf_path):
        with open(pdf_path, 'rb') as pdf_file:
            reader = PyPDF2.PdfFileReader(pdf_file)
            writer = PyPDF2.PdfFileWriter()
    
            # Crear página de tabla de contenidos con objetos de texto enlazados
            toc_page = PyPDF2.pdf.PageObject.createBlankPage(None, 72, 72)
            toc_page.drawText(50, 750, 'Página 1', '/Link')
            toc_page.drawText(50, 700, 'Página 2', '/Link')
            toc_page.drawText(50, 650, 'Página 3', '/Link')
            toc_page.compressContentStreams()
            writer.addPage(toc_page)
    
            # Crear enlaces entre páginas
            for i in range(reader.getNumPages()):
                page = reader.getPage(i)
                link_dest = PyPDF2.pdf.Destination(i+1)
                link_annotation = PyPDF2.pdf.DictionaryObject({
                    '/Type': '/Annot',
                    '/Subtype': '/Link',
                    '/Rect': [0, 0, 0, 0],  # Establecer las dimensiones correctas
                    '/Border': [0, 0, 0],  # Sin borde
                    '/A': PyPDF2.pdf.DictionaryObject({
                        '/S': '/GoTo',
                        '/D': link_dest
                    })
                })
                page['/Annots'] = [link_annotation]
                writer.addPage(page)
    
                # Agregar anotaciones de botón para la página siguiente/anterior
                if i < reader.getNumPages() - 1:
                    next_dest = PyPDF2.pdf.Destination(i+2)
                    next_annotation = PyPDF2.pdf.DictionaryObject({
                        '/Type': '/Annot',
                        '/Subtype': '/Link',
                        '/Rect': [0, 0, 0, 0],  # Establecer las dimensiones correctas
                        '/Border': [0, 0, 0],  # Sin borde
                        '/A': PyPDF2.pdf.DictionaryObject({
                            '/S': '/Named',
                            '/N': '/Next',
                            '/D': next_dest
                        })
                    })
                    page['/Annots'].append(next_annotation)
                if i > 0:
                    prev_dest = PyPDF2.pdf.Destination(i)
                    prev_annotation = PyPDF2.pdf.DictionaryObject({
                        '/Type': '/Annot',
                        '/Subtype': '/Link',
                        '/Rect': [0, 0, 0, 0],  # Establecer las dimensiones correctas
                        '/Border': [0, 0, 0],  # Sin borde
                        '/A': PyPDF2.pdf.DictionaryObject({
                            '/S': '/Named',
                            '/N': '/Prev',
                            '/D': prev_dest
                        })
                    })
                    page['/Annots'].append(prev_annotation)
    
            # Escribir el archivo de salida
            with open('output.pdf', 'wb') as out_file:
                writer.write(out_file)
    

    Puedes llamar a esta función con la ruta al archivo PDF de entrada para crear un nuevo archivo con enlaces y botones clicables. Ten en cuenta que tendrás que ajustar las dimensiones y la posición de las anotaciones para que se adapten a tu caso de uso específico.

Comments are closed.