Issue
I am trying to:
- Display an image which is bigger than the window size;
- Make the window scrollable, so I can roll through the whole image;
- Draw over the image;
Problem is:
- As soon as I make the window scrollable, I can't see the drawing anymore;
How can I solve it?
Minimal example:
class DocumentWindow(QWidget):
def __init__(self, main_obj):
super().__init__()
self.WIDTH = 500
self.HEIGHT = 500
self.resize(self.WIDTH, self.HEIGHT)
file_path = 'invoice_example.jpeg'
self.pages = {0: Image.open(file_path)}
image = QImage(file_path)
self.doc_original_width = image.width()
self.doc_original_height = image.height()
self.doc_new_width = image.width()
self.doc_new_height = image.height()
palette = QPalette()
palette.setBrush(QPalette.Window, QBrush(image))
self.setPalette(palette)
label = QLabel(None, self)
label.setGeometry(0, 0, self.WIDTH, self.HEIGHT)
conWin = QWidget()
conLayout = QVBoxLayout(self)
conLayout.setContentsMargins(0, 0, 0, 0)
conWin.setLayout(conLayout)
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(True)
scroll.setWidget(conWin)
scrollLayout = QVBoxLayout(self)
# When I enable these lines, I got no visible drawing
scrollLayout.addWidget(scroll)
scrollLayout.setContentsMargins(0, 0, 0, 0)
self.begin = QtCore.QPoint()
self.end = QtCore.QPoint()
self.show()
def paintEvent(self, event):
qp = QtGui.QPainter(self)
br = QtGui.QBrush(QtGui.QColor(100, 10, 10, 40))
qp.setBrush(br)
qp.drawRect(QtCore.QRect(self.begin, self.end))
rect = QtCore.QRect(self.begin, self.end)
self.coordinates = rect.getCoords()
def mousePressEvent(self, event):
self.begin = event.pos()
self.end = event.pos()
self.update()
def mouseMoveEvent(self, event):
self.end = event.pos()
self.update()
def mouseReleaseEvent(self, event):
x1, y1, x2, y2 = self.coordinates
if x1 == x2 or y1 == y2:
return
self.width_factor = self.doc_original_width / self.doc_new_width
self.height_factor = self.doc_original_height / self.doc_new_height
self.normalized_coordinates = [
int(x1*self.width_factor), int(y1*self.height_factor),
int(x2*self.width_factor), int(y2*self.height_factor) ]
self.update()
Solution
The issue is you are placing the scroll area on top of your DocumentWindow
widget (where your event handlers are reimplemented), so the drawing is hidden underneath it. You can still see the image because QScrollArea (and other widgets) inherit their parent's backgroundRole
if not explicitly set (and you are displaying the image via a palette).
The drawing needs to be implemented inside the QScrollArea's widget
, which right now is an empty QWidget conWin
. For your example this can be simplified by making QScrollArea the top level widget and setting a DocumentWindow
instance as the scroll area's widget
.
minimumSizeHint
is added to support the scrolling functionality by setting a recommended minimum size for the widget.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class DocumentWindow(QWidget):
def __init__(self):
super().__init__()
file_path = 'invoice_example.jpeg'
self.image = QImage(file_path)
palette = QPalette()
palette.setBrush(QPalette.Window, QBrush(self.image))
self.setPalette(palette)
self.begin = QPoint()
self.end = QPoint()
def minimumSizeHint(self):
return self.image.size()
def mousePressEvent(self, event):
self.begin = event.pos()
self.end = event.pos()
self.update()
def mouseMoveEvent(self, event):
self.end = event.pos()
self.update()
def mouseReleaseEvent(self, event):
x1, y1, x2, y2 = QRect(self.begin, self.end).getCoords()
if x1 == x2 or y1 == y2:
return
self.update()
def paintEvent(self, event):
qp = QPainter(self)
br = QBrush(QColor(100, 10, 10, 40))
qp.setBrush(br)
qp.drawRect(QRect(self.begin, self.end))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(True)
scroll.setWidget(DocumentWindow())
scroll.resize(500, 500)
scroll.show()
sys.exit(app.exec_())
Answered By - alec
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.