Overflow Widgets in that rounded corners QFrame

2.4k views Asked by At

I have a problem with QFrame, when i setStyleSheet of QFrame like this;

frame = QFrame(self.window)
frame.setObjectName('Custom_Widget')
frame.setStyleSheet("""
   #Custom_Widget {
     background: #002025;
     border-radius: 20px;
     opacity: 100;
     border: 2px solid #ff2025;                   
        }""")

It's like this; img1

You see corners rounded but widget is not rounded. It's rectangle. This is my first problem.My second problem is img2 You see QMediaPlayer's corners not rounded because it overflows QWidget. How can i solve this problem?

My all code below;

# PyQt5 Video player
#!/usr/bin/env python

from PyQt5.QtCore import QDir, Qt, QUrl,QRect, pyqtSignal
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel,
        QPushButton, QSizePolicy, QSlider, QStyle, QVBoxLayout, QWidget,QProgressBar,QFrame)
from PyQt5.QtWidgets import QMainWindow,QWidget, QPushButton, QAction
from PyQt5.QtGui import QIcon
import sys,os

class VideoWindow(QMainWindow):
    closeSignal = pyqtSignal(int)

    def __init__(self, parent=None):
        super(VideoWindow, self).__init__(parent)

    def setupUi(self,window):
        self.window = window
        self.window.setFixedSize(784,442)
        #self.window.setFixedSize(884,542)
        self.window.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint|Qt.WA_TranslucentBackground)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        widget = QWidget(self.window)

        widget.setObjectName('Custom_Widget')
        widget.setStyleSheet("""
        #Custom_Widget {
            background: #002025;
            border-radius: 20px;
            opacity: 100;
            border: 2px solid #ff2025;
        }
        """)

        videoWidget = QVideoWidget(widget)
        videoWidget.setGeometry(QRect(0,0,784, 442))

        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(os.getcwd() + "\\logo-anim.avi")))
        self.mediaPlayer.play()
        #self.mediaPlayer.stateChanged.connect(lambda x: self.closeSignal.emit(x))
        self.mediaPlayer.stateChanged.connect(lambda x: sys.exit())
        
        self.window.setCentralWidget(widget)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = QMainWindow()
    player = VideoWindow()
    player.setFixedSize(784, 442)
    player.setupUi(w)
    w.show()
    sys.exit(app.exec_())
1

There are 1 answers

3
musicamante On

There are many issues and misconceptions in your code, which is also very confusing.

  • you are creating a QMainWindow (VideoWindow) which you're not using.
  • you are adding the video widget as a child of a QWidget, and setting the same geometry for the QMainWindow, the QWidget and the QVideoWidget; how would you expect to have a border, if they all have the same geometry?
  • if you want a plain widget with borders and without other features, using a QMainWindow is not only unnecessary, but also wrong: QMainWindows provide features like an internal layout, support for status bars, toolbars, dock widgets and menus, which you clearly are not going to use; a QWidget is what is going to be used instead.
  • if a widget is going to have children, fixed geometries should be avoided, while layout managers should always be used instead, even if there's only one widget;
  • setting rounded borders through stylesheets doesn't change the actual shape of the widget (which is always rectangular), and you need to apply a mask instead.
  • you're trying to use a Qt.WidgetAttribute for window flags, which is not only very wrong, but also causes some issues as it's not a window flag; such attributes must be used with setAttribute().
  • setting the frameless flag will probably prevent moving the window in most systems, you should address that by providing appropriate mouse interaction.
  • it's usually better to set a parent for new Qt objects (unless they're widgets), especially when they use threaded/concurrent processing (like QMediaPlayer), so they will be properly removed when the parent is, and system resources are correctly released.

This is a revision of your code.

class VideoWindow(QWidget):
    closeSignal = pyqtSignal(int)

    def __init__(self, parent=None):
        super(VideoWindow, self).__init__(parent)

        self.setFixedSize(784,442)
        self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)

        self.setStyleSheet("""
        VideoWindow {
            background: #002025;
            border-radius: 20px;
            opacity: 100;
            border: 2px solid #ff2025;
        }
        """)

        layout = QHBoxLayout(self)
        videoWidget = QVideoWidget()
        layout.addWidget(videoWidget)

        self.mediaPlayer = QMediaPlayer(self, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(os.getcwd() + "/test.mp4")))
        self.mediaPlayer.play()

        self.startPos = None

    def mousePressEvent(self, event):
        self.startPos = event.pos()

    def mouseMoveEvent(self, event):
        if self.startPos:
            self.move(self.pos() + (event.pos() - self.startPos))

    def mouseReleaseEvent(self, event):
        self.startPos = None

    def resizeEvent(self, event):
        path = QPainterPath()
        path.addRoundedRect(QRectF(self.rect()), 20, 20)
        reg = QRegion(path.toFillPolygon().toPolygon())
        self.setMask(reg)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    player = VideoWindow()
    player.setFixedSize(784, 442)
    player.show()
    sys.exit(app.exec_())