Quantcast
Viewing latest article 4
Browse Latest Browse All 58

PyQt6, drawing shapes over loaded PDF file

My goal is to create a PDF viewer that allows to draw a rectangle in front of the text. Right now the viewer part is done as well as the drawing rectangles part. The problem is, they don't work together. As soon as I load a PDF file, I can no longer draw my shapes over it.I highly suspect that the problem is wrong QPixmap or QPainter argument somewhere. Unfortunately, I'm very much nooby with PyQt6, so I don't really understand how those classes work (I've read the docs).I'll be really grateful if some noble soul would help me with this problem.Screenshot - Left: I can draw rectangles. Right: I open PDF and rectangles disappear and I can't draw new ones.

import sysfrom pathlib import Pathfrom PyQt6 import QtWidgetsfrom PyQt6.QtCore import QPointF, QRect, QPoint, Qtfrom PyQt6.QtGui import QAction, QPainter, QPixmapfrom PyQt6.QtPdf import QPdfDocumentfrom PyQt6.QtPdfWidgets import QPdfViewfrom PyQt6.QtWidgets import QFileDialog, QApplicationclass MainWindow(QtWidgets.QMainWindow):    def __init__(self):        super().__init__()        self.init_ui()        # Painting settings        self.pix = QPixmap(self.rect().size())        self.pix.fill(Qt.GlobalColor.transparent)        self.point1, self.point2 = QPoint(), QPoint()        # PDF settings        self.pdf_document = QPdfDocument(self)        self.pdf_view = QPdfView(self)        self.m_fileDialog = None        self.pdf_view.setDocument(self.pdf_document)    def init_ui(self):        self.setGeometry(100, 100, 800, 600)        self.setWindowTitle('RectanglePDF')        # Buttons        open_file = QAction('Open PDF file...', self)        open_file.triggered.connect(self.open_pdf)        close_program = QAction('Exit', self)        close_program.triggered.connect(self.exit_program)        p_page = QAction('Previous Page', self)        p_page.triggered.connect(self.previous_page)        n_page = QAction('Next Page', self)        n_page.triggered.connect(self.next_page)        # Menubar        menubar = self.menuBar()        file_menu = menubar.addMenu('File')        file_menu.addAction(open_file)        file_menu.addAction(close_program)        menubar.addAction(p_page)        menubar.addAction(n_page)        self.show()    def paintEvent(self, event):        painter = QPainter(self)        painter.drawPixmap(QPoint(), self.pix)        if not self.point1.isNull() and not self.point2.isNull():            rect = QRect(self.point1, self.point2)            painter.drawRect(rect.normalized())    def mousePressEvent(self, event):        if event.buttons() & Qt.MouseButton.LeftButton:            self.point1 = event.pos()            self.point2 = self.point1            self.update()    def mouseMoveEvent(self, event):        if event.buttons() & Qt.MouseButton.LeftButton:            self.point2 = event.pos()            self.update()    def mouseReleaseEvent(self, event):        if event.button() & Qt.MouseButton.LeftButton:            rect = QRect(self.point1, self.point2)            painter = QPainter(self.pix)            painter.drawRect(rect.normalized())            self.point1, self.point2 = QPoint(), QPoint()            self.update()    def next_page(self):        nav = self.pdf_view.pageNavigator()        if nav.currentPage() < self.pdf_document.pageCount() - 1:            nav.jump(nav.currentPage() + 1, QPointF(), nav.currentZoom())    def previous_page(self):        nav = self.pdf_view.pageNavigator()        if nav.currentPage() > 0:            nav.jump(nav.currentPage() - 1, QPointF(), nav.currentZoom())    def exit_program(self):        sys.exit(app.exec())    def open_pdf(self):        home_dir = str(Path.home())        doc_location = QFileDialog.getOpenFileName(            self,'Open File',            home_dir,"PDF files (*.pdf)"        )        self.pdf_document.load(doc_location[0])        self.pdf_view.setDocument(self.pdf_document)        self.pdf_view.setPageMode(QPdfView.PageMode.SinglePage)        self.pdf_view.setZoomMode(QPdfView.ZoomMode.FitInView)        self.setCentralWidget(self.pdf_view)        self.update()        self.pdf_view.show()  # oldif __name__ == '__main__':    app = QApplication(sys.argv)    myApp = MainWindow()    myApp.show()    try:        sys.exit(app.exec())    except SystemExit:        print('Closing Window...')

Update. I tried to use Stacked Layout, but result is still unsatisfactory.

import sysfrom pathlib import Pathfrom PyQt6 import QtCore, QtWidgetsfrom PyQt6.QtCore import QPointF, QRect, QPoint, Qtfrom PyQt6.QtGui import QAction, QPainter, QPixmap, QIconfrom PyQt6.QtPdf import QPdfDocumentfrom PyQt6.QtPdfWidgets import QPdfViewfrom PyQt6.QtWidgets import (QFileDialog,                             QApplication,                             QStackedLayout,                             QVBoxLayout,                             QWidget,                             )class RectWindow(QWidget):    def __init__(self):        super().__init__()        layout = QVBoxLayout()        self.setLayout(layout)        self.pix = QPixmap(self.rect().size())  # TODO get screen resolution        self.pix.fill(Qt.GlobalColor.transparent)        self.begin, self.destination = QPoint(), QPoint()        # TODO Transparent background to reveal PDF underneath        # self.setWindowFlags(Qt.WindowType.FramelessWindowHint)        # self.setWindowFlags(Qt.WindowType.WindowTransparentForInput)        # self.setStyleSheet('QWidget {background: transparent')        # self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)        # self.setWindowOpacity(0.5)    def paintEvent(self, event):        painter = QPainter(self)        painter.drawPixmap(QPoint(), self.pix)        if not self.begin.isNull() and not self.destination.isNull():            rect = QRect(self.begin, self.destination)            painter.drawRect(rect.normalized())    def mousePressEvent(self, event):        if event.buttons() & Qt.MouseButton.LeftButton:            self.begin = event.pos()            self.destination = self.begin            self.update()    def mouseMoveEvent(self, event):        if event.buttons() & Qt.MouseButton.LeftButton:            self.destination = event.pos()            self.update()    def mouseReleaseEvent(self, event):        if event.button() & Qt.MouseButton.LeftButton:            rect = QRect(self.begin, self.destination)            painter = QPainter(self.pix)            painter.drawRect(rect.normalized())            self.begin, self.destination = QPoint(), QPoint()            self.update()class PdfWindow(QWidget):    def __init__(self):        super().__init__()        self.pdf_document = QPdfDocument(self)        self.pdf_view = QPdfView(self)        self.m_fileDialog = None        self.pdf_view.setDocument(self.pdf_document)    def open_pdf(self):        home_dir = str(Path.home())        doc_location = QFileDialog.getOpenFileName(            self,'Open File',            home_dir,"PDF files (*.pdf)"        )        self.pdf_document.load(doc_location[0])        self.pdf_view.setDocument(self.pdf_document)        self.pdf_view.setPageMode(QPdfView.PageMode.SinglePage)        self.pdf_view.setZoomMode(QPdfView.ZoomMode.FitInView)        self.update()        self.pdf_view.showMaximized()    def next_page(self):        nav = self.pdf_view.pageNavigator()        if nav.currentPage() < self.pdf_document.pageCount() - 1:            nav.jump(nav.currentPage() + 1, QPointF(), nav.currentZoom())    def previous_page(self):        nav = self.pdf_view.pageNavigator()        if nav.currentPage() > 0:            nav.jump(nav.currentPage() - 1, QPointF(), nav.currentZoom())class MainWindow(QtWidgets.QMainWindow):    def __init__(self):        super().__init__()        self.setWindowTitle('RectanglePDF')        # Widgets        base_widget = QWidget()        rect_widget = RectWindow()        pdf_widget = PdfWindow()        # Layout settings        main_layout = QVBoxLayout()        self.stacklayout = QStackedLayout()        self.setLayout(main_layout)        base_widget.setLayout(self.stacklayout)        # Layout ordering        self.stacklayout.addWidget(pdf_widget)        self.stacklayout.addWidget(rect_widget)        self.setCentralWidget(base_widget)        # Buttons        open_file = QAction('Open PDF file...', self)        open_file.triggered.connect(pdf_widget.open_pdf)        close_program = QAction('Exit', self)        close_program.triggered.connect(self.exit_program)        p_page = QAction('Previous Page', self)        p_page.triggered.connect(pdf_widget.previous_page)        n_page = QAction('Next Page', self)        n_page.triggered.connect(pdf_widget.next_page)        # Menubar        menubar = self.menuBar()        file_menu = menubar.addMenu('File')        file_menu.addAction(open_file)        file_menu.addAction(close_program)        menubar.addAction(p_page)        menubar.addAction(n_page)        # DEBUG        r_pdf = QAction('Raise PDF', self)        r_pdf.triggered.connect(self.raise_pdf)        menubar.addAction(r_pdf)        r_rect = QAction('Raise Rect', self)        r_rect.triggered.connect(self.raise_rect)        menubar.addAction(r_rect)    def raise_pdf(self):  # for DEBUG        self.stacklayout.setCurrentIndex(0)    def raise_rect(self):  # for DEBUG        self.stacklayout.setCurrentIndex(1)    def exit_program(self):        sys.exit(app.exec())if __name__ == '__main__':    app = QApplication(sys.argv)    mainApp = MainWindow()    mainApp.showMaximized()    try:        sys.exit(app.exec())    except SystemExit:        print('Closing Window...')

Viewing latest article 4
Browse Latest Browse All 58

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>