I am trying to build a paint app that has a grid, but I don't want to grid to be included in the saved photo.
I tried to draw on a transparent image, but I got a black background instead!
Here is the full code:
import sys
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import QPoint, Qt
from PyQt5.QtGui import QBrush, QGuiApplication, QImage, QPainter, QPen, QIcon, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QTextEdit, QAction, QFileDialog,
QGraphicsScene, QGraphicsProxyWidget, QGraphicsView
import pyautogui
import matplotlib.pyplot as plt
class Drawer(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self._drawing = False
self.last_point = QPoint()
self.image_layer = QImage(self.size(), QImage.Format_RGB32)
self.image_layer.fill(Qt.gray)
self.brushSize = 2
self.brushColor = Qt.black
#paint = QPainter(self.image_layer)
#paint.setCompositionMode(QtGui.QPainter.CompositionMode_Clear)
# paint.drawLine(0,0,self.size().width(),0)
# paint.drawLine(0,10,200,10)
#paint.drawLine(0,0,0,200)
#paint.drawLine(10,0,10,200)
self.update()
def mousePressEvent(self, event):
self._drawing = True
self.last_point = event.pos()
def mouseMoveEvent(self, event):
if self._drawing and event.buttons() & Qt.LeftButton:
painter = QPainter(self.image_layer)
painter.setPen(
QPen(
self.brushColor,
self.brushSize,
Qt.SolidLine,
Qt.RoundCap,
Qt.RoundJoin,
)
)
painter.drawLine(self.last_point, event.pos())
self.last_point = event.pos()
self.update()
def paintEvent(self, event):
painter = QPainter(self)
painter.drawImage(QPoint(), self.image_layer)
painter.end()
def resizeEvent(self, event):
if (
self.size().width() > self.image_layer.width()
or self.size().height() > self.image_layer.height()
):
qimg = QImage(
max(self.size().width(), self.image_layer.width()),
max(self.size().height(), self.image_layer.height()),
QImage.Format_RGB32,
)
qimg.fill(Qt.gray)
painter = QPainter(qimg)
painter.drawImage(QPoint(), self.image_layer)
painter.drawLine(0, 0, qimg.size().width(), 0)
painter.drawLine(0, 10, qimg.size().width(), 10)
painter.drawLine(0, 600, qimg.size().width(), 600)
print(qimg.size().height())
painter.end()
self.image_layer = qimg
self.update()
class Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
[x, y] = pyautogui.size()
self.setGeometry(0, 0, x, y)
self.drawer = Drawer()
textbox = QTextEdit("Converted text will show here")
central_widget = QWidget()
self.setCentralWidget(central_widget)
vlay = QVBoxLayout(central_widget)
vlay.addWidget(textbox)
vlay.addWidget(self.drawer, stretch=1)
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("File")
saveAction = QAction(QIcon("icons/save.png"), "Save", self)
saveAction.setShortcut("Ctrl+S")
fileMenu.addAction(saveAction)
saveAction.triggered.connect(self.save)
def save(self):
filePath, _ = QFileDialog.getSaveFileName(self.drawer, "Save Image", "",
"PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")
if filePath == "":
return
self.drawer.image_layer.save(filePath)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
Note: there are only two lines that mimics the grid, I can draw it later, but for now I want the saved image to not include the grind lines.
You should paint the grid in the paintEvent, instead of continuously painting it onto the image.
def paintEvent(self, event):
painter = QPainter(self)
painter.drawImage(QPoint(), self.image_layer)
gridSize = 10
x = y = 0
width = self.width()
height = self.height()
while y <= height:
# draw horizontal lines
painter.drawLine(0, y, width, y)
y += gridSize
while x <= width:
# draw vertical lines
painter.drawLine(x, 0, x, height)
x += gridSize
Related
The code below sketches a polygon on an image. I would like to draw a second identical shape inside the primary one with a gap of 0.3m. I have tried a couple of solutions but none of them worked in all use cases.
Please refer to the attached screenshot.
Context: The shape is drawn by combining a group of selected points using the QPolygon class.
import sys
from sympy import Polygon
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import QLine, Qt, QPoint, QRect
from PyQt5.QtGui import QPixmap, QPainter,QColor,QPolygon
from PyQt5 import QtCore, QtGui, QtWidgets, uic
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.window_width, self.window_height =1200,800
self.setMinimumSize(self.window_width,self.window_height)
layout= QVBoxLayout()
self.setLayout(layout)
self.pix = QPixmap('image.jpg')
self.resize(self.pix.width(),self.pix.height())
# self.pix.fill(Qt.white)
# tableau
self.point = QPoint()
self.tab =[]
def paintEvent(self,event):
painter = QPainter(self)
pen = QtGui.QPen()
pen.setColor(QtGui.QColor('red'))
pen.setWidth(3)
painter.setPen(pen)
painter.drawPixmap(QPoint(),self.pix)
if not self.point.isNull():
# rect = QRect(self.begin,self.destination)
# painter.drawRect(rect.normalized())
line = QPoint(self.point)
painter.drawPoint(line)
def mousePressEvent(self,event):
if event.buttons() & Qt.LeftButton:
self.point = event.pos()
# self.destination = self.begin
self.update()
# def mouseMoveEvent(self,event):
# if event.buttons() & Qt.LeftButton:
# self.point = event.pos()
# self.update()
def mouseReleaseEvent(self,event):
pen = QtGui.QPen()
painter = QPainter(self.pix)
if event.button() == Qt.LeftButton:
# rect = QRect(self.begin,self.destination)
line = QPoint(self.point)
pen.setColor(QtGui.QColor('red'))
pen.setWidth(3)
painter.setPen(pen)
painter.drawPoint(line)
painter.setPen(QColor(168, 34, 3))
self.tab.append(self.point)
print(self.point.x,self.point.y)
self.point = QPoint()
# w = (rect.width()*12.5)/1056
# h = (rect.height()*12.5/1056)
# a=w*h
# print(w, h,a)
self.update()
if event.button() == Qt.RightButton:
points = QPolygon(self.tab)
pen.setColor(QtGui.QColor('red'))
painter.setPen(pen)
painter.drawPolygon(points)
#print(self.tab[0])
polytab=[]
for i in self.tab:
polytab.append((i.x(),i.y()))
print(Polygon(*polytab).area*(12.5/1056)*(12.5/1056))
print((self.tab[0].x()-self.tab[1].x())*(12.5/1056))
self.tab=[]
self.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet('''QWidget{font-size:30px}''')
myAPP = MyApp()
myAPP.show()
try:
sys.exit(app.exec_())
except SystemExit:
print('Closing Window...')
The algorithm is given a vertex so the associated edges must be translated in a parallel way and the intersection of these lines is a point of the desired polygon.
import sys
from PyQt5.QtCore import QLineF
from PyQt5.QtGui import QColor, QPainter, QPen, QPolygonF
from PyQt5.QtWidgets import QApplication, QWidget
def calculate_inner_polygon(polygon, offset):
if polygon.count() < 3:
return QPolygonF()
points = []
for i in range(polygon.count()):
pp = polygon[(i - 1 + polygon.count()) % polygon.count()]
pc = polygon[i]
pn = polygon[(i + 1 + polygon.count()) % polygon.count()]
line_0 = QLineF(pp, pc)
normal_0 = line_0.normalVector()
normal_0.setLength(offset)
line_0.translate(normal_0.dx(), normal_0.dy())
line_1 = QLineF(pc, pn)
normal_1 = line_1.normalVector()
normal_1.setLength(offset)
line_1.translate(normal_1.dx(), normal_1.dy())
t, point = line_0.intersects(line_1)
if t != QLineF.NoIntersection:
points.append(point)
return QPolygonF(points)
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.setMinimumSize(1200, 800)
self._points = list()
def paintEvent(self, event):
painter = QPainter(self)
painter.fillRect(self.rect(), QColor("white"))
if not self._points:
return
pen_width = 3
offset = -8
pen = QPen(QColor("red"))
outer_polygon = QPolygonF(self._points)
inner_polygon = calculate_inner_polygon(outer_polygon, offset)
for polygon in (outer_polygon, inner_polygon):
pen.setWidth(pen_width)
painter.setPen(pen)
painter.drawPolygon(polygon)
pen.setWidth(2 * pen_width)
painter.setPen(pen)
for point in polygon:
painter.drawPoint(point)
def mouseReleaseEvent(self, event):
self._points.append(event.pos())
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MyApp()
w.show()
sys.exit(app.exec_())
I'm trying to rotate a background image with a button and trim the image over the window, but it doesn't work and I don't know why it is not working.
But when I hit the button my image just fades away...
And here is my code:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QGridLayout, QPushButton
from PyQt5.QtGui import QPixmap
class myApplication(QtWidgets.QWidget):
def __init__(self, parent=None):
super(myApplication, self).__init__(parent)
self.img = QtGui.QImage()
pixmap = QtGui.QPixmap("ola.png")
self.label = QLabel(self)
self.label.setMinimumSize(600, 600)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setPixmap(pixmap)
grid = QGridLayout()
button = QPushButton('Rotate 15 degrees')
button.clicked.connect(self.rotate_pixmap)
grid.addWidget(self.label, 0, 0)
grid.addWidget(button, 1, 0)
self.setLayout(grid)
self.rotation = 0
def rotate_pixmap(self):
pixmap = QtGui.QPixmap(self.img)
self.rotation += 15
transform = QtGui.QTransform().rotate(self.rotation)
pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation)
self.label.setPixmap(pixmap)
if __name__ == '__main__':
app = QApplication([])
w = myApplication()
w.show()
sys.exit(app.exec_())
"self.img" is an empty QImage and you are rotating that element. The idea is to rotate the QPixmap:
class myApplication(QtWidgets.QWidget):
def __init__(self, parent=None):
super(myApplication, self).__init__(parent)
self.rotation = 0
self.pixmap = QtGui.QPixmap("ola.png")
self.label = QLabel()
self.label.setMinimumSize(600, 600)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setPixmap(self.pixmap)
button = QPushButton("Rotate 15 degrees")
button.clicked.connect(self.rotate_pixmap)
grid = QGridLayout(self)
grid.addWidget(self.label, 0, 0)
grid.addWidget(button, 1, 0)
def rotate_pixmap(self):
pixmap = self.pixmap.copy()
self.rotation += 15
transform = QtGui.QTransform().rotate(self.rotation)
pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation)
self.label.setPixmap(pixmap)
I want to draw a line (or paint) on an image that I already opened. I can open the image, but I can't draw on the image. But if I don't open any image, I can draw anything I want on blank space.
So, How can I draw with a brush on an image ? For now eraser or etc. It's not important. I just want to do something with a brush on an image, which image I already open in my computer.
I didn't get any error or something. So I can't search specifically.
Here is my code;
from PyQt5.QtWidgets import QMainWindow, QApplication, QMenu, QMenuBar, QAction, QFileDialog, QLabel
from PyQt5.QtGui import QIcon, QImage, QPainter, QPen, QBrush, QPixmap
from PyQt5.QtCore import Qt, QPoint
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
title = "Paint Application"
top = 400
left = 400
width = 800
height = 600
icon = "icons/pain.png"
self.setWindowTitle(title)
self.setGeometry(top, left, width, height)
self.setWindowIcon(QIcon(icon))
self.image = QImage(self.size(), QImage.Format_RGB32)
self.image.fill(Qt.white)
self.drawing = False
self.brushSize = 2
self.brushColor = Qt.black
self.lastPoint = QPoint()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("File")
brushSize = mainMenu.addMenu("Brush Size")
brushColor = mainMenu.addMenu("Brush Color")
openAction = QAction('Open Image', self)
openAction.triggered.connect(self.openImage)
fileMenu.addAction(openAction)
closeAction = QAction('Exit', self)
closeAction.triggered.connect(self.close)
fileMenu.addAction(closeAction)
self.label = QLabel()
self.setCentralWidget(self.label)
saveAction = QAction(QIcon("icons/save.png"), "Save",self)
saveAction.setShortcut("Ctrl+S")
fileMenu.addAction(saveAction)
saveAction.triggered.connect(self.save)
clearAction = QAction(QIcon("icons/clear.png"), "Clear", self)
clearAction.setShortcut("Ctrl+C")
fileMenu.addAction(clearAction)
clearAction.triggered.connect(self.clear)
threepxAction = QAction( QIcon("icons/threepx.png"), "3px", self)
brushSize.addAction(threepxAction)
threepxAction.triggered.connect(self.threePixel)
fivepxAction = QAction(QIcon("icons/fivepx.png"), "5px", self)
brushSize.addAction(fivepxAction)
fivepxAction.triggered.connect(self.fivePixel)
sevenpxAction = QAction(QIcon("icons/sevenpx.png"),"7px", self)
brushSize.addAction(sevenpxAction)
sevenpxAction.triggered.connect(self.sevenPixel)
ninepxAction = QAction(QIcon("icons/ninepx.png"), "9px", self)
brushSize.addAction(ninepxAction)
ninepxAction.triggered.connect(self.ninePixel)
blackAction = QAction(QIcon("icons/black.png"), "Black", self)
blackAction.setShortcut("Ctrl+B")
brushColor.addAction(blackAction)
blackAction.triggered.connect(self.blackColor)
whitekAction = QAction(QIcon("icons/white.png"), "White", self)
whitekAction.setShortcut("Ctrl+W")
brushColor.addAction(whitekAction)
whitekAction.triggered.connect(self.whiteColor)
redAction = QAction(QIcon("icons/red.png"), "Red", self)
redAction.setShortcut("Ctrl+R")
brushColor.addAction(redAction)
redAction.triggered.connect(self.redColor)
greenAction = QAction(QIcon("icons/green.png"), "Green", self)
greenAction.setShortcut("Ctrl+G")
brushColor.addAction(greenAction)
greenAction.triggered.connect(self.greenColor)
yellowAction = QAction(QIcon("icons/yellow.png"), "Yellow", self)
yellowAction.setShortcut("Ctrl+Y")
brushColor.addAction(yellowAction)
yellowAction.triggered.connect(self.yellowColor)
def openImage(self):
imagePath, _ = QFileDialog.getOpenFileName()
pixmap = QPixmap(imagePath)
self.label.setPixmap(pixmap)
self.resize(pixmap.size())
self.adjustSize()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.drawing = True
self.lastPoint = event.pos()
#print(self.lastPoint)
def mouseMoveEvent(self, event):
if(event.buttons() & Qt.LeftButton) & self.drawing:
painter = QPainter(self.image)
painter.setPen(QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.lastPoint, event.pos())
self.lastPoint = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.drawing = False
def paintEvent(self, event):
canvasPainter = QPainter(self)
canvasPainter.drawImage(self.rect(),self.image, self.image.rect() )
def save(self):
filePath, _ = QFileDialog.getSaveFileName(self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")
if filePath == "":
return
self.image.save(filePath)
def clear(self):
self.image.fill(Qt.white)
self.update()
def threePixel(self):
self.brushSize = 3
def fivePixel(self):
self.brushSize = 5
def sevenPixel(self):
self.brushSize = 7
def ninePixel(self):
self.brushSize = 9
def blackColor(self):
self.brushColor = Qt.black
def whiteColor(self):
self.brushColor = Qt.white
def redColor(self):
self.brushColor = Qt.red
def greenColor(self):
self.brushColor = Qt.green
def yellowColor(self):
self.brushColor = Qt.yellow
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec()
Instead of constructing a QPixmap from the filepath, construct a QImage and assign it to the variable self.image. You won't have to change anything else as the paintEvent will draw the QImage object that pointed to by self.image.
def openImage(self):
imagePath, _ = QFileDialog.getOpenFileName()
self.image = QImage(imagePath)
self.resize(self.image.size())
I can add QWidget to QMainWindow and set its position to cursor position.
But every single time, I want to add new QWidget to QMainWindow. I don't maybe given codes add new QWidget but at canvas, I see just one QWidget. Here my codes:
from PyQt5.QtWidgets import QMainWindow, QApplication, QMenu, QMenuBar, QAction, QFileDialog, QWidget, QLabel
from PyQt5.QtGui import QIcon, QImage, QPainter, QPen, QBrush
from PyQt5.QtCore import Qt, QPoint
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
title = "Paint Application"
top = 400
left = 400
width = 800
height = 600
self.objStr = "berkayy"
self.count = 0
# icon = "icons/pain.png"
self.setAcceptDrops(True)
self.setWindowTitle(title)
self.setGeometry(top, left, width, height)
# self.setWindowIcon(QIcon(icon))
self.image = QImage(self.size(), QImage.Format_RGB32)
self.image.fill(Qt.white)
self.drawing = False
self.brushSize = 2
self.brushColor = Qt.black
self.lastPoint = QPoint()
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu("File")
brushSize = mainMenu.addMenu("Brush Size")
brushColor = mainMenu.addMenu("Brush Color")
saveAction = QAction(QIcon("icons/save.png"), "Save",self)
saveAction.setShortcut("Ctrl+S")
fileMenu.addAction(saveAction)
saveAction.triggered.connect(self.save)
clearAction = QAction(QIcon("icons/clear.png"), "Clear", self)
clearAction.setShortcut("Ctrl+C")
fileMenu.addAction(clearAction)
clearAction.triggered.connect(self.clear)
threepxAction = QAction( QIcon("icons/threepx.png"), "3px", self)
brushSize.addAction(threepxAction)
threepxAction.triggered.connect(self.threePixel)
fivepxAction = QAction(QIcon("icons/fivepx.png"), "5px", self)
brushSize.addAction(fivepxAction)
fivepxAction.triggered.connect(self.fivePixel)
sevenpxAction = QAction(QIcon("icons/sevenpx.png"),"7px", self)
brushSize.addAction(sevenpxAction)
sevenpxAction.triggered.connect(self.sevenPixel)
ninepxAction = QAction(QIcon("icons/ninepx.png"), "9px", self)
brushSize.addAction(ninepxAction)
ninepxAction.triggered.connect(self.ninePixel)
blackAction = QAction(QIcon("icons/black.png"), "Black", self)
blackAction.setShortcut("Ctrl+B")
brushColor.addAction(blackAction)
blackAction.triggered.connect(self.blackColor)
whitekAction = QAction(QIcon("icons/white.png"), "White", self)
whitekAction.setShortcut("Ctrl+W")
brushColor.addAction(whitekAction)
whitekAction.triggered.connect(self.whiteColor)
redAction = QAction(QIcon("icons/red.png"), "Red", self)
redAction.setShortcut("Ctrl+R")
brushColor.addAction(redAction)
redAction.triggered.connect(self.redColor)
greenAction = QAction(QIcon("icons/green.png"), "Green", self)
greenAction.setShortcut("Ctrl+G")
brushColor.addAction(greenAction)
greenAction.triggered.connect(self.greenColor)
yellowAction = QAction(QIcon("icons/yellow.png"), "Yellow", self)
yellowAction.setShortcut("Ctrl+Y")
brushColor.addAction(yellowAction)
yellowAction.triggered.connect(self.yellowColor)
def rectangle(self, e, pos):
print(pos)
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
painter.setBrush(QBrush(Qt.green, Qt.DiagCrossPattern))
painter.drawRect(100, 15, 400, 200)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.drawing = True
self.lastPoint = event.pos()
#print(self.lastPoint)
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
newAct = contextMenu.addAction("New")
openAct = contextMenu.addAction("Open")
closeAct = contextMenu.addAction("Close")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == closeAct:
self.close()
elif action == openAct:
self.berkay(event.pos())
def mouseMoveEvent(self, event):
if(event.buttons() & Qt.LeftButton) & self.drawing:
painter = QPainter(self.image)
painter.setPen(QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.lastPoint, event.pos())
self.lastPoint = event.pos()
self.update()
def berkay(self, pos):
wid = QWidget(self)
btn = QLabel(wid)
btn.setText("skjdf")
btn.setObjectName(self.objStr + str(self.count) )
btn.move(pos)
self.setCentralWidget(wid)
self.count += 1
# btn.setDragEnabled(True)
print(btn.objectName())
# self.show()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.drawing = False
def paintEvent(self, event):
canvasPainter = QPainter(self)
canvasPainter.drawImage(self.rect(),self.image, self.image.rect() )
def save(self):
filePath, _ = QFileDialog.getSaveFileName(self, "Save Image", "", "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")
if filePath == "":
return
self.image.save(filePath)
def clear(self):
self.image.fill(Qt.white)
self.update()
def threePixel(self):
self.brushSize = 3
def fivePixel(self):
self.brushSize = 5
def sevenPixel(self):
self.brushSize = 7
def ninePixel(self):
self.brushSize = 9
def blackColor(self):
self.brushColor = Qt.black
def whiteColor(self):
self.brushColor = Qt.white
def redColor(self):
self.brushColor = Qt.red
def greenColor(self):
self.brushColor = Qt.green
def yellowColor(self):
self.brushColor = Qt.yellow
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec()
I want to create new QWidget when user clicked context menu item every single time.
A QMainWindow can have only one central widget. So, adding the new QLabel as central widget will remove the previous. That's why you can see only the last label.
Create a single widget and define it as central widget. Then, add the label as child of the central widget:
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.area = QWidget(self)
self.setCentralWidget(self.area)
def berkay(self, pos):
btn = QLabel("BOOH", self.area)
btn.move(self.area.mapFromParent(pos)) # Map the pos in the coord system of self.area
btn.show()
First, for every single widget, store x and y value in a list. After that, adding new and current widgets to window central widget.
Edit
We do not need store widget x and y, anymore.
Thank you Romha for optimisation suggestion.
import sys
from PyQt5.QtWidgets import QMainWindow, QMenu, QApplication, QWidget, QPushButton, qApp
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import Qt
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.area = QWidget(self)
self.setCentralWidget(self.area)
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Context menu')
self.setStyleSheet("QMainWindow {background: 'white';}")
self.show()
def contextMenuEvent(self, event):
cmenu = QMenu(self)
addBtnAct = cmenu.addAction("Add Button")
quitAct = cmenu.addAction("Quit")
action = cmenu.exec_(self.mapToGlobal(event.pos()))
if action == quitAct:
qApp.quit()
elif action == addBtnAct:
self.addLabel(event.pos())
def addLabel(self, pos):
btn = QLabel("BOOH", self.area)
btn.move(self.area.mapFromParent(pos)) # Map the pos in the coord system of self.area
btn.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
I'm trying to re-implement the scribble demo app for multiple layers of images. I am struggling to draw into the pixmap within the scene as the Painter complains that is being destroyed to early.
QPaintDevice: Cannot destroy paint device that is being painted
Could you please help me fix my code such that you can draw on to the roilayer pixmap with the red pen and that this layer starts transparent.
#!/usr/bin/python3
import sys
import os
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
from PyQt5.QtGui import QPixmap, QImage, QPainter, QPen
from PyQt5.QtCore import Qt, QRect
class Main(QGraphicsView):
def __init__(self):
super().__init__()
self.setWindowTitle("Scribble with layers")
self.scene = QGraphicsScene()
self.setScene(self.scene)
self.image = QImage('sample/test.bmp')
self.imlayer = QGraphicsPixmapItem(QPixmap.fromImage(self.image))
self.roilayer = QGraphicsPixmapItem(QPixmap(self.image.size()))
self.addlayer(self.imlayer)
self.addlayer(self.roilayer)
self.drawing = False
self.lastPoint = None
self.pencolour = Qt.red
self.penwidth = 2
self.show()
def addlayer(self, layer):
self.scene.addItem(layer)
self.updateviewer()
def updateviewer(self):
self.fitInView(self.sceneRect(), Qt.KeepAspectRatio)
def mousePressEvent(self, event):
# print(event.modifiers())
if event.button() == Qt.LeftButton:
self.lastPoint = event.pos()
self.drawing = True
def mouseMoveEvent(self, event):
if (event.buttons() & Qt.LeftButton) and self.drawing:
self.drawlineto(event.pos())
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton and self.drawing:
self.drawlineto(event.pos())
self.drawing = False
def drawlineto(self, position):
pixmap = self.roilayer.pixmap()
painter = QPainter(pixmap)
painter.setPen(QPen(self.pencolour, self.penwidth, Qt.SolidLine,
Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.lastPoint, position)
self.imlayer.setPixmap(pixmap)
self.modified = True
rad = self.penwidth / 2 + 2
self.update(QRect(self.lastPoint, position).normalized().adjusted(-rad, -rad, +rad, +rad))
self.lastPoint = position
if __name__ == '__main__':
app = QApplication([])
main = Main()
sys.exit(app.exec_())
I had the same problem. The solution is to do the following to this part of your code:
def drawlineto(self, position):
pixmap = self.roilayer.pixmap()
painter = QPainter()
painter.begin(pixmap)
painter.setPen(QPen(self.pencolour, self.penwidth, Qt.SolidLine,
Qt.RoundCap, Qt.RoundJoin))
painter.drawLine(self.lastPoint, position)
painter.end()
self.imlayer.setPixmap(pixmap)
self.modified = True