QSS 未应用于 QVBoxLayout 中(复合小部件)中的第一个 QSizeGrip
QSS not applied to first QSizeGrip in (composite widget) in QVBoxLayout
如下所示,小部件 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_())
如下图,QVBoxLayout
中第一个TestWidget
的大小控制只有当TestWidget
是布局中的唯一元素时才会出现。
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
观察到的是预定行为但没有记录,如果 source code 被修改,它将被观察到:
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 位于 window 的上部,则观察到它位于上部,这就是它观察到的行为的原因。
解决方法是覆盖QSizeGrip的paintEvent方法:
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_())
如下所示,小部件 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_())
如下图,QVBoxLayout
中第一个TestWidget
的大小控制只有当TestWidget
是布局中的唯一元素时才会出现。
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
观察到的是预定行为但没有记录,如果 source code 被修改,它将被观察到:
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 位于 window 的上部,则观察到它位于上部,这就是它观察到的行为的原因。
解决方法是覆盖QSizeGrip的paintEvent方法:
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_())