Dewamuval
Dewamuval

Reputation: 497

Message with rounded corners with Qt

I'm trying to create a widget like the message box at the bottom in this picture:

img

It should overlay the main widget. I have 2 ways to do this:

But there's a problem with each of them:

img

img

Here's what the code looks like:

class Message(QFrame):
    """
    A temporary message to show information in the GUI.
    """

    def __init__(self, msg: str, *args, destroy_time: int = None):
        super().__init__(*args)

        # Main layout
        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)

        # The label
        label = QLabel(msg)
        label.setFont(Fonts.text)
        label.setStyleSheet(f"color: {Colors.fg};"
                            "padding: 20px;")
        self.layout.addWidget(label)
        self.setStyleSheet(f"background-color: {Colors.bg};"
                           "border-radius: 30px;")

        #  region = QRegion(self.x(), self.y(), self.sizeHint().width(),
                         #  self.sizeHint().height(), QRegion.Ellipse)
        #  self.setMask(region)

        self.adjustSize()

Edit for S. Nick: Your solution only works if the Message widget is the only widget in the application. The intended usage is this:

class MainWindow(QWidget):
    def __init__(self, player: QWidget):
        super().__init__()

        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(player)

        msg = Message("I can't make this work", self)

where player is the main widget, and the message overlays it when it appears. Imagine it being an image, which is overlayed by the message. Sorry for not explaining myself correctly.

Upvotes: 2

Views: 3142

Answers (1)

S. Nick
S. Nick

Reputation: 13681

Try it:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *


class Message(QWidget):   #(QFrame): #
    def __init__(self, msg: str, *args, destroy_time: int = None):
        super().__init__(*args)

        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint) # <---
        self.setAttribute(Qt.WA_TranslucentBackground)                   # <---

        Colors_fg = "#fa0"
        Colors_bg = "rgba( 155, 155, 155, 150)"                          # <---

        # Main layout
        self.layout = QVBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)

        # The label
        label = QLabel(msg, alignment=Qt.AlignCenter)
        label.setFont(QFont("Times", 17, QFont.Bold, italic=True))       #(Fonts.text)
        label.setStyleSheet(f"color: {Colors_fg};"
                             "padding: 0px;")
        self.layout.addWidget(label)

# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv        
        self.setStyleSheet(f"background-color: {Colors_bg};"  
                            "min-height: 70px;"
                            "max-height: 70px;"
                            "width: 200px;"
                            "border-radius: 30px;"
                           )
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self.adjustSize()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Message("Hello \nWorld")
    w.resize(400, 200)
    w.show()
    sys.exit(app.exec_())

enter image description here


Update

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *


class Message(QDialog):      #(QFrame):
    def __init__(self, msg: str, *args, destroy_time: int = None):
        super().__init__(*args)
        self.setWindowFlags(self.windowFlags() | 
                            Qt.FramelessWindowHint |
                            Qt.WindowStaysOnTopHint) 
        self.setAttribute(Qt.WA_TranslucentBackground)                   

        self.widget = QWidget(self)
        self.widget.setObjectName('Custom_Widget')
        layout = QVBoxLayout(self)
        layout.addWidget(self.widget)

        self.layout = QGridLayout(self.widget)
        self.layout.addItem(QSpacerItem(
            40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum), 0, 0)
        self.layout.addWidget(QPushButton('r', self, 
                                          clicked=self.accept, 
                                          objectName='closeButton'), 0, 1)
        # The label
        label = QLabel(msg)
        label.setFont(QFont("Times", 17, QFont.Bold, italic=True))         #((Fonts.text)
        self.layout.addWidget(label, 2, 0, 5, 2, alignment=Qt.AlignCenter)                           
        self.adjustSize()

    def mousePressEvent(self, event):
        self.old_Pos    = event.globalPos()
        self.old_width  = self.width()
        self.old_height = self.height()

    def mouseMoveEvent(self, event):
        if (event.buttons() == Qt.LeftButton): 
            delta = QPoint (event.globalPos() - self.old_Pos)
            if (self.old_Pos.x() > self.x() + self.old_width - 20) or \
               (self.old_Pos.y() > self.y() + self.old_height - 20):
                w = self.old_width+delta.x()  if self.old_width+delta.x()  > 500 else 500
                h = self.old_height+delta.y() if self.old_height+delta.y() > 400 else 400
                self.setFixedSize(w, h)
            else:
                self.move(self.x() + delta.x(), self.y() + delta.y())
                self.old_Pos = event.globalPos()


class MainWindow(QWidget):
    def __init__(self, player: QWidget):
        super().__init__()

        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(player)

        self.msg = Message("I can't make this work")#, self)        
        self.msg.show()


Stylesheet = """
#Custom_Widget {
    background: rgba( 155, 155, 155, 150);
    border-radius: 20px;
    border: 2px solid #ff2025;                   
}
#closeButton {
    min-width: 36px;
    min-height: 36px;
    font-family: "Webdings";
    qproperty-text: "r";
    border-radius: 10px;
}
#closeButton:hover {
    color: #ccc;
    background: red;
}
"""

if __name__ == '__main__':
    app = QApplication(sys.argv)

    app.setStyleSheet(Stylesheet)

    w = MainWindow(QPushButton("player"))
    w.resize(400, 200)
    w.show()
    sys.exit(app.exec_())

enter image description here


Update 2

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *


class Message(QFrame):      # QDialog
    def __init__(self, msg: str, *args, destroy_time: int = None):
        super().__init__(*args)
#        self.setWindowFlags(self.windowFlags() | 
#                            Qt.FramelessWindowHint #|Qt.WindowStaysOnTopHint) 
        self.setAttribute(Qt.WA_TranslucentBackground)                   

        self.widget = QWidget(self)
        self.widget.setObjectName('Custom_Widget')
        layout = QVBoxLayout(self)
        layout.addWidget(self.widget)

        self.layout = QGridLayout(self.widget)
        self.layout.addItem(QSpacerItem(
            40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum), 0, 0)
        self.layout.addWidget(QPushButton('r', self, 
#                                          clicked=self.accept, 
                                          clicked=self.close, 
                                          objectName='closeButton'), 0, 1)
        # The label
        label = QLabel(msg)
        label.setFont(QFont("Times", 15, QFont.Bold, italic=True))         #((Fonts.text)
        self.layout.addWidget(label, 2, 0, 5, 2, alignment=Qt.AlignCenter)                           
        self.adjustSize()


class MainWindow(QWidget):
    def __init__(self, player: QWidget):
        super().__init__()

        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(player)
        player.clicked.connect(self._msg)

    def _msg(self):
        self.msg = Message("I can't make this work\nself.msg.setGeometry(10, 10, 480, 150)", self)        
        self.msg.setGeometry(10, 10, 480, 150)
        self.msg.show()


Stylesheet = """
#Custom_Widget {
    background: rgba( 155, 155, 155, 150);
    border-radius: 20px;
    border: 2px solid #ff2025;                   
}
#closeButton {
    min-width: 36px;
    min-height: 36px;
    font-family: "Webdings";
    qproperty-text: "r";
    border-radius: 10px;
}
#closeButton:hover {
    color: #ccc;
    background: red;
}
"""

if __name__ == '__main__':
    app = QApplication(sys.argv)

    app.setStyleSheet(Stylesheet)

    w = MainWindow(QPushButton("player"))
    w.resize(500, 400)
    w.show()
    sys.exit(app.exec_())

enter image description here

Upvotes: 4

Related Questions