Search code examples
pyqtpyqt5qpainterqt-signalsqtwidgets

how to display a textlabel as well as draw a circle on clicking a pushbutton "ADD"


I have read all related article of multiple slots with one signal but I am unable to display at the time of drawing a circle both trigerred by a push button "ADD". I can display the text label near the circle before clicking the button but i want it to dislay only after clicking the button. Please Help. Also, i want the text label to be near circle and can be modified anytime on clicking

import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow,QPushButton,QWidget
from PyQt5 import QtGui
from PyQt5.QtCore import QRect,Qt
from PyQt5.QtGui import QPainter,QBrush, QPen
from PyQt5 import QtCore


class Window(QMainWindow):
   def __init__(self):
        super(Window,self).__init__()
        title="layout management"
        left=500
        top=200
        width=500
        height=400
        iconName="fosseeicon.jpg"
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon(iconName))
        self.setGeometry(left, top, width, height)
        self.should_paint_circle = False
        self.windowcomponents()
        self.initUI()
        self.show()
   def initUI(self):
       if self.should_paint_circle:
           self.label=QtWidgets.QLabel(self)
           self.label.setText('<h2>circle<h2>')
   def windowcomponents(self):
       button=QPushButton("Add", self)
       button.setGeometry(QRect(0, 0, 50, 28))
       button.setIcon(QtGui.QIcon("addbutton.png"))
       button.setToolTip("<h3>This is for creating random circles<h3>")
       button.clicked.connect(self.paintcircle)
       button=QPushButton("Generate Report", self)
       button.setGeometry(QRect(49,0,150,28))
       button.setIcon(QtGui.QIcon("generatereport.png"))
       button.setToolTip("This is for generating pdf report of connection between two circles")
       button=QPushButton("Save", self)
       button.setGeometry(QRect(199,0,120,28))
       button.setIcon(QtGui.QIcon("saveicon.png"))
       button.setToolTip("This is for saving an image of canvas area")

   def paintEvent(self, event):
       super().paintEvent(event)
       if self.should_paint_circle:
           painter = QtGui.QPainter(self)
           painter.setRenderHint(QPainter.Antialiasing)
           painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
           painter.drawEllipse(100, 100, 100, 100)
           self.initUI()
           self.label.move(60,100)
   def paintcircle(self, painter):
       self.should_paint_circle = True
       self.update()
app = QApplication(sys.argv)
circle=Window()
circle.show()
sys.exit(app.exec_())

Solution

  • Widgets that are created with a parent, outside their __init__ (or their parent's), but not added to a layout, have to be explicitly shown; you're missing this:

        self.label.show()
    

    Besides that, you MUST NOT create new widgets within the paintEvent.

    Painting is something that happens often, usually in the following situations (which happen very often:

    • when the widget is shown the first time
    • whenever the widget is hidden and shown again (for example, after minimizing and restoring the window)
    • whenever the mouse enters or exits it and/or its children
    • when the widget or any of its parents are resized
    • when a new children is shown

    The result is that if you add a widget for each paint event, you'll probably end up with dozens (if not hundreds or thousands) of widgets, and, most importantly if you also show it, it will cause an infinite recursion.

    class Window(QMainWindow):
        def __init__(self):
            super(Window,self).__init__()
            title="layout management"
            left=500
            top=200
            width=500
            height=400
            iconName="fosseeicon.jpg"
            self.setWindowTitle(title)
            self.setWindowIcon(QtGui.QIcon(iconName))
            self.setGeometry(left, top, width, height)
            self.should_paint_circle = False
            self.windowcomponents()
            self.label = QtWidgets.QLabel(self)
            self.label.hide()
    
        # ...
    
        def paintEvent(self, event):
            super().paintEvent(event)
            if self.should_paint_circle:
                painter = QtGui.QPainter(self)
                painter.setRenderHint(QPainter.Antialiasing)
                painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
                painter.drawEllipse(100, 100, 100, 100)
    
        def paintcircle(self, painter):
            self.should_paint_circle = True
            self.label.setText('<h2>circle<h2>')
            self.label.move(60,100)
            self.label.show()
            self.update()
    

    That said, based on this question and the previous one, I suggest you to study the documentation more carefully, especially what is related to the QMainWindow, the Layout management, painting in Qt and the related QPainter documentation.