【问题标题】:Message with rounded corners with Qt带有 Qt 的圆角消息
【发布时间】:2020-02-25 19:15:09
【问题描述】:

我正在尝试创建一个类似于这张图片底部的消息框的小部件:

它应该覆盖主小部件。我有两种方法可以做到这一点:

  • 带有 QFrame 和圆角
  • 带着面具

但是他们每个人都有一个问题:

  • QFrame 方法似乎是一个更好的主意,但背景不透明。这意味着即使边框有一个半径,背景仍然使它成为一个矩形。在图片中有点明显。不幸的是,this 似乎不起作用。 self.setStyleSheet("background:transparent") 也一样。

  • 蒙版看起来非常像素化,这不是预期的行为,因为使用的蒙版只能是一个简单的 QRegion。这些没有松鼠,这将是理想的。

代码如下:

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

为 S. Nick 编辑:仅当消息小部件是应用程序中的唯一小部件时,您的解决方案才有效。预期用途是这样的:

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)

其中player 是主要小部件,消息在出现时会覆盖它。想象它是一个被消息覆盖的图像。很抱歉没有正确解释自己。

【问题讨论】:

    标签: python qt pyqt5 qt5 pyside2


    【解决方案1】:

    试试看:

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


    更新

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


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

    【讨论】:

    • 感谢 S. Nick 的建议。但我没有正确解释自己。仅当 Message 小部件是应用程序中唯一的小部件时才有效。请查看编辑后的帖子以获取更多信息。
    • @Dewamuval 我更新了答案,将消息移动到任何你想要的地方。
    • 但问题是它应该在主小部件内部,覆盖player 小部件。就像示例图片一样。
    • @Dewamuval 我正在更新答案,将消息放置在您想要的任何位置。
    • 你这个摇滚人。感谢您的坚持和帮助,祝您有美好的一天:)
    猜你喜欢
    • 1970-01-01
    • 2019-05-28
    • 1970-01-01
    • 2022-01-12
    • 2015-11-09
    • 1970-01-01
    • 2012-09-12
    • 2014-09-02
    相关资源
    最近更新 更多