QSS не применяется к первому QSizeGrip в (составной виджет) в QVBoxLayout - PullRequest
1 голос
/ 20 марта 2019

Как показано ниже, виджет TestWidget содержит QFrame и CSS-стиль QSizeGrip.Несколько экземпляров TestWidget помещаются в QVBoxLayout

from PySide import QtGui, QtCore
import sys

class TestWidget(QtGui.QWidget):
    def __init__(self , parent=None):
        super(TestWidget , self).__init__(parent)

        layout = QtGui.QVBoxLayout()
        layout.setContentsMargins( 0 , 0 , 0 , 0 )

        frame = QtGui.QFrame()
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setMinimumHeight( 100 )

        grip = QtGui.QSizeGrip(self)
        grip.setStyleSheet( "QSizeGrip { image: url(dots.png); }")
        grip.setCursor(QtCore.Qt.SplitVCursor)

        layout.addWidget(frame)
        layout.addWidget( grip , 0 , QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight )

        self.setLayout(layout)

class TestApp(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(TestApp, self).__init__(parent)

        track1 = TestWidget()
        track2 = TestWidget()
        track3 = TestWidget()

        centralWidget = QtGui.QWidget()
        layout = QtGui.QVBoxLayout(centralWidget)

        layout.addWidget(track1)
        layout.addWidget(track2)
        layout.addWidget(track3)

        self.setCentralWidget(centralWidget)
        self.show() 

if __name__=="__main__":
    app=QtGui.QApplication(sys.argv)
    myapp = TestApp();
    sys.exit(app.exec_())   

. Как показано ниже, размерный захват первого TestWidget в QVBoxLayout отображается только в том случае, если TestWidget является единственным элементом.в макете.

enter image description here enter image description here enter image description here

Qt версия 4.8.7

PySide версия 1.2.2


Версия программы PySide2 (ниже) имеет ту же проблему

from PySide2 import QtCore
from PySide2.QtWidgets import QApplication, QWidget , QMainWindow , QGraphicsView , QVBoxLayout , QFrame , QSizeGrip , QWidget

import sys

class TestWidget(QWidget):
    def __init__(self , parent=None):
        super(TestWidget , self).__init__(parent)

        layout = QVBoxLayout()
        layout.setContentsMargins( 0 , 0 , 0 , 0 )

        frame = QFrame()
        frame.setFrameShape(QFrame.StyledPanel)
        frame.setMinimumHeight( 100 )

        grip = QSizeGrip(self)
        grip.setStyleSheet( "QSizeGrip { image: url(dots.png); }")
        grip.setCursor(QtCore.Qt.SplitVCursor)

        layout.addWidget(frame)
        layout.addWidget( grip , 0 , QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight )

        self.setLayout(layout)

class TestApp(QMainWindow):
    def __init__(self, parent=None):
        super(TestApp, self).__init__(parent)

        track1 = TestWidget()
        track2 = TestWidget()
        track3 = TestWidget()

        centralWidget = QWidget()
        layout = QVBoxLayout(centralWidget)

        layout.addWidget(track1)
        layout.addWidget(track2)
        layout.addWidget(track3)

        self.setCentralWidget(centralWidget)
        self.show() 

if __name__=="__main__":
    app = QApplication(sys.argv)
    myapp = TestApp();
    sys.exit(app.exec_())   

PySide2 версия 5.12.1

1 Ответ

1 голос
/ 21 марта 2019

То, что наблюдается, является предопределенным поведением, но не задокументировано, если исходный код будет изменен, будет наблюдаться:

Qt::Corner QSizeGripPrivate::corner() const
{
    Q_Q(const QSizeGrip);
    QWidget *tlw = qt_sizegrip_topLevelWidget(const_cast<QSizeGrip *>(q));
    const QPoint sizeGripPos = q->mapTo(tlw, QPoint(0, 0));
    bool isAtBottom = sizeGripPos.y() >= tlw->height() / 2;
    bool isAtLeft = sizeGripPos.x() <= tlw->width() / 2;
    if (isAtLeft)
        return isAtBottom ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
    else
        return isAtBottom ? Qt::BottomRightCorner : Qt::TopRightCorner;
}

Если наблюдается, что sizeGrip помещается вверхняя часть, если она находится в верхней части окна, и это является причиной поведения, которое оно наблюдает.

Обходной путь должен переписать метод paintEvent QSizeGrip:

PySide2:

import sys
from PySide2 import QtCore, QtGui, QtWidgets

class SizeGrip(QtWidgets.QSizeGrip):
    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        opt = QtWidgets.QStyleOptionSizeGrip()
        opt.initFrom(self)
        opt.corner = QtCore.Qt.BottomRightCorner
        self.style().drawControl(QtWidgets.QStyle.CE_SizeGrip, opt, painter, self)

class TestWidget(QtWidgets.QWidget):
    def __init__(self , parent=None):
        super(TestWidget , self).__init__(parent)
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins( 0 , 0 , 0 , 0 )
        frame = QtWidgets.QFrame()
        frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        frame.setMinimumHeight( 100 )
        grip = SizeGrip(self)
        grip.setStyleSheet('''QSizeGrip { 
            image: url(dots.png);
        }''')
        layout.addWidget(frame)
        layout.addWidget(grip , 0 , QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight )

class TestApp(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(TestApp, self).__init__(parent)
        centralWidget = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout(centralWidget)
        for _ in range(3):
            layout.addWidget(TestWidget())
        self.setCentralWidget(centralWidget)
        self.show()

if __name__=="__main__":
    app = QtWidgets.QApplication(sys.argv)
    myapp = TestApp();
    sys.exit(app.exec_())   

PySide:

import sys
from PySide import QtCore, QtGui

class SizeGrip(QtGui.QSizeGrip):
    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        opt = QtGui.QStyleOptionSizeGrip()
        opt.initFrom(self)
        opt.corner = QtCore.Qt.BottomRightCorner
        self.style().drawControl(QtGui.QStyle.CE_SizeGrip, opt, painter, self)

class TestWidget(QtGui.QWidget):
    def __init__(self , parent=None):
        super(TestWidget , self).__init__(parent)
        layout = QtGui.QVBoxLayout(self)
        layout.setContentsMargins( 0 , 0 , 0 , 0 )
        frame = QtGui.QFrame()
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setMinimumHeight( 100 )
        grip = SizeGrip(self)
        grip.setStyleSheet('''QSizeGrip { 
            image: url(dots.png);
        }''')
        grip.setCursor(QtCore.Qt.SplitVCursor)
        layout.addWidget(frame)
        layout.addWidget(grip , 0 , QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight )

class TestApp(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(TestApp, self).__init__(parent)
        centralWidget = QtGui.QWidget()
        layout = QtGui.QVBoxLayout(centralWidget)
        for _ in range(3):
            layout.addWidget(TestWidget())
        self.setCentralWidget(centralWidget)
        self.show()

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = TestApp();
    sys.exit(app.exec_())   

enter image description here

...