1

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_()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
laslavinco
  • 344
  • 4
  • 14

1 Answers1

2

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

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • thanks i understood the problem now. your answer is also correct but i found a shortcut. So I just added `` `if QWidgetparent: size = self.parent().size() self.resize(size)` – laslavinco Sep 03 '18 at 04:54
  • @laslavinco If my answer helps you, do not forget to mark it as correct, if you do not know how to do it, review the [tour], that is the best way to thank. – eyllanesc Sep 03 '18 at 04:55
  • @laslavinco your solution is the same as mine but it has a disadvantage if you change the size of your window it will generate a problem, instead my solution will automatically be corrected. – eyllanesc Sep 03 '18 at 04:57
  • yeah true i completely forgot that. Thanks for the help :) – laslavinco Sep 03 '18 at 04:58