pythonpyqtpyqt4qwidgetqframe

QFrame is not taking QWidget as parent?


what i am trying in here is Make CancelCross child of Notifier class but when i do that the cross of CancelCross is not visible. But if i unparent it then it visible fine. I tried parenting it with QMainWindow as well but no luck. Is there something wrong in my code ?

class CloseCrosss(QtGui.QFrame):
    def __init__(self, QWidgetparent = None):
        QtGui.QFrame.__init__(self, parent=QWidgetparent)


    def paintEvent(self, e):
        qp = QtGui.QPainter()
        pen = QtGui.QPen(Qt.red)
        qp.begin(self)
        qp.setPen(pen)
        qp.drawLine(460, 10, 470, 20)
        qp.drawLine(470, 10, 460, 20)
        qp.end()


class Notifier(QtGui.QWidget):
    def __init__(self, message=None):
        QtGui.QWidget.__init__(self)
        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        _desktop = QtGui.QApplication.desktop()
        size = _desktop.screenGeometry()

        self.resize(size.width() * 25 / 100, size.height() * 3 / 100)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)

        self.main_layout = QtGui.QVBoxLayout()
        self.move(size.width() - (size.width() * 25 / 100) - 10, 50)

        self.main_layout.setContentsMargins(0, 0, 0, 0)
        self.main_layout.setSpacing(0)

        self.label = QtGui.QLabel(message)
        self.label.setStyleSheet("color: lightgreen; font: 14px;")
        self.label.setIndent(20)
        self.main_layout.addWidget(self.label)
        self.setLayout(self.main_layout)


    def paintEvent(self, event):
        s = self.size()
        qp = QtGui.QPainter()
        qp.begin(self)
        qp.setRenderHint(QtGui.QPainter.Antialiasing, True)
        qp.setPen(QtGui.QColor(255, 255, 255, 200))
        qp.setBrush(QtGui.QColor(0, 0, 0, 200))
        qp.drawRoundedRect(0, 0, s.width(), s.height(), 5, 5)
        qp.end()


    def closeEvent(self):
        self.kill()


if __name__ == "__main__":
    QApp = QtGui.QApplication(sys.argv)
    window = Notifier()
    cross = CloseCrosss(QWidgetparent=window)
    window.show()
    cross.show()
    QApp.exec_()

Solution

  • The positions of the children are relative to their parent, if a widget does not have a father then its position is relative to the screen. And that coordinate system is used to paint, for example in your case qp.drawLine(460, 10, 470, 20) is indicating that you are going to paint the line that goes from (460, 10) to (470, 20) to the Notifier. The height of Notifier is 3% of the screen, and for my 3% of the screen it is much less than 470, so the painting is discarded.

    In your case I understand that you want to draw a cross of 10x10, then just draw that cross and then move it to the upper left corner.

    import sys
    from PyQt4 import QtCore, QtGui
    
    
    class CloseCrosss(QtGui.QFrame):
        clicked = QtCore.pyqtSignal()
    
        def __init__(self, side=10, parent=None):
            QtGui.QFrame.__init__(self, parent)
            self._side = side
            self.setFixedSize(side, side)
            if parent:
                parent.installEventFilter(self)
    
        def mouseReleaseEvent(self, event):
            self.clicked.emit()
            QtGui.QFrame.mouseReleaseEvent(self, event)
    
        def paintEvent(self, e):
            qp = QtGui.QPainter(self)
            qp.setPen(QtCore.Qt.red)
            qp.drawLine(0, 0, self._side, self._side)
            qp.drawLine(self._side, 0, 0, self._side)
    
        def eventFilter(self, watched, event):
            if watched == self.parentWidget() and self.parentWidget():
                if event.type() == QtCore.QEvent.Resize:
                    self.adjustSize()
            return QtGui.QFrame.eventFilter(self, watched, event)
    
        def adjustSize(self):
            # move widget to topright
            self.move(self.parentWidget().width() -self.width()-5, 5)
    
    
    class Notifier(QtGui.QWidget):
        def __init__(self, message=None):
            QtGui.QWidget.__init__(self, flags=QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint)
            _desktop = QtGui.QApplication.desktop()
            size = _desktop.screenGeometry().size()
    
            self.resize(size.width() * 25 / 100, size.height() * 3 / 100)
            self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
    
            self.main_layout = QtGui.QVBoxLayout(self)
            self.move(size.width() - (size.width() * 25 / 100) - 10, 50)
    
            self.main_layout.setContentsMargins(0, 0, 0, 0)
            self.main_layout.setSpacing(0)
    
            self.label = QtGui.QLabel(message)
            self.label.setStyleSheet("color: lightgreen; font: 14px;")
            self.label.setIndent(20)
            self.main_layout.addWidget(self.label)
            cross = CloseCrosss(parent=self)
            cross.clicked.connect(self.close)
    
    
        def paintEvent(self, event):
            qp = QtGui.QPainter(self)
            qp.setRenderHint(QtGui.QPainter.Antialiasing, True)
            qp.setPen(QtGui.QColor(255, 255, 255, 200))
            qp.setBrush(QtGui.QColor(0, 0, 0, 200))
            qp.drawRoundedRect(QtCore.QRect(QtCore.QPoint(), self.size()), 5, 5)
    
    
    if __name__ == "__main__":
        QApp = QtGui.QApplication(sys.argv)
        window = Notifier("Hello World")
        window.show()
        sys.exit(QApp.exec_())
    

    enter image description here