0
votes

I am trying to draw an interactive zoom box on an image that will cause zoomed images to appear in other image windows. My issue is that nothing triggers the paintEvent(). It doesn't execute when the object is instantiated, and I can't trigger it manually using update() or repaint().

I put a print() statement inside to make sure paintEvent() is not being executed (it isn't). I know the code for drawing the rectangle on the image works because I tested it by executing it directly in the init() statement. I tried using update() (and forcing execution using QApplication.processEvent()) and repaint().

from math import floor, ceil
from PyQt5.QtWidgets import QLabel, QApplication, QHBoxLayout, QWidget, QGraphicsRectItem
from PyQt5.QtCore import Qt, QSize 
from PyQt5.QtGui import QPixmap, QColor, QPainter, QPolygon, QBrush, QPen
import sys
from RangeSlider import *
from StyleSheet import *
from LayoutDefine import *

class ZoomBox(QLabel):

    def __init__(self, parent, zoomLevel = 100, penWidth = 3):
        super(ZoomBox, self).__init__()
        # zoomLevel specified in pct
        if zoomLevel < 100:
            self.zoom = 100
        else:
            self.zoom = zoomLevel
        self.rectPen = QPen(QColor("#ff1f1f"))
        self.rectPen.setWidth(penWidth)
        self.left, self.top = 0, 0
        self.parent = parent
        self.DefSize()
        self.update()
        QApplication.processEvents()

    def DefSize(self):
        self.width = ceil(self.parent.width() / self.zoom * 100)
        self.height = ceil(self.parent.height() / self.zoom * 100)

    def paintEvent(self, event):
        print("paintEvent")
        self.DefSize()
        img = QPixmap([path/to/image]).scaledToHeight(parent.height(), Qt.SmoothTransformation)
        painter = QPainter(img)
        painter.begin(self.parent)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(self.rectPen)
        painter.drawRect(self.left, self.top, self.width, self.height)
        painter.end()
        parent.setPixmap(img)

class VidWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.InitUI()

    def InitUI(self):

        foo = QLabel()
        foo.setMaximumHeight(500)
        foo.setPixmap(QPixmap([path/to/image]).scaledToHeight(500))
        ZoomBox(foo)

        bar = QHBoxLayout()
        bar.addWidget(foo)
        self.setLayout(bar)
        self.showMaximized()

        foo.update()

if __name__ == '__main__':

    # init application
    app = QApplication(sys.argv)

    # instantiate main window
    ex = VidWindow()

    # end program handler
    sys.exit(app.exec_())

The results are.. nothing. Nothing gets drawn and no error messages are output.

P.S. Apologies for all the imports, I wasn't confident about which ones I could delete, and I'm also allowing for the possibility that there might be a conflict.

1
The reason for the zoomBox not being painted is that you're not assigning it to any persistent object attribute, meaning that it is deleted right after the InitUi returns. Moreover, it has no parent: you're just setting the parent as a local attribute, while you should possibly add that as an argument of the super init); if you don't do that, you have to explicitly call show(). That said, the whole procedure is a bit confused, you might think of clarifying your logic some more. - musicamante
Yes, turns out you're 100% correct about the persistent object. I've restructured the whole thing to dump the parent dependency. Thanks! - Zachary Stamler
I avoided writing it as an answer, as I wasn't sure it was: as said, your code is a bit convoluted, and while my "answer" might help you, it would probably help you alone, without adding much help for future users that might need to find out a solution to a similar problem (SO is not just a "I'm asking/somebody answers" site, its aim is to provide help for anybody facing an issue which might have happened to somebody else in the past). Long story short: I'd suggest you to clarify your example (in the code or in the exposition), and I'll be able to provide a more comprensive answer if you want. - musicamante
Otherwise, it could be a good idea to rewrite your own answer, possibly adding a working example and explaining what you're doing. - musicamante

1 Answers

0
votes

musicamante, 3 hours ago (as a comment):

The reason for the zoomBox not being painted is that you're not assigning it to any persistent object attribute, meaning that it is deleted right after the InitUi returns. Moreover, it has no parent: you're just setting the parent as a local attribute, while you should possibly add that as an argument of the super init); if you don't do that, you have to explicitly call show(). That said, the whole procedure is a bit confused, you might think of clarifying your logic some more.