0

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.

2 Answers 2

1

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()
Sign up to request clarification or add additional context in comments.

2 Comments

Romha thank you for answer and comment. Your suggestions worked. But self.count += 1 break code. What does it mean?
It was a copy/paste from your own code. I removed it.
0

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_())

1 Comment

Recreating all labels each time you add a new one will lead to a memory leak and a lack of efficiency

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.