为什么带有边框和背景图像样式的QWidget行为不同于QLabel, QDialog,…



我使用Qt4.8 Python绑定PySide (Windows上Python 3.3的版本1.2.2),我看到QWidget的行为不同于QWidget派生的小部件,如QDialog, QLabelQMainWindow使用样式表进行样式化。

我特别注意到属性WA_StyledBackground必须设置为显示边框或背景图像,而背景颜色是独立设置的。相反,对于其他小部件,此属性没有影响,始终显示边框或背景图像。重写paintEvent方法也是一种可能。

示例代码:

from PySide import QtGui, QtCore
class MyWidget(QtGui.QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    def paintEvent(self, event):
        opt = QtGui.QStyleOption()
        opt.initFrom(self)
        painter = QtGui.QStylePainter(self)
        painter.drawPrimitive(QtGui.QStyle.PE_Widget, opt)
def display(w):
    print(w.__class__.__name__)
    w.setWindowTitle(w.__class__.__name__)
    print(' WA_StyledBackground is {}'.format(w.testAttribute(QtCore.Qt.WA_StyledBackground)))
    print(' autoFillBackground is {}'.format(w.autoFillBackground()))
    w.setStyleSheet('border: 4px inset #515c84; border-radius: 9px; background-color: blue; background-image: url(test.png);')
    w.resize(400, 400)
    w.show()
app = QtGui.QApplication([])
w1 = QtGui.QMainWindow(flags=QtCore.Qt.Window)
display(w1) # works
w2 = QtGui.QDialog(f=QtCore.Qt.Window)
display(w2) # works
w3 = QtGui.QWidget(f=QtCore.Qt.Window)
w3.setAttribute(QtCore.Qt.WA_StyledBackground)
display(w3) # works only with the previous line uncommented
w4 = QtGui.QLabel('Text', f=QtCore.Qt.Window)
display(w4) # works
w5 = MyWidget(f=QtCore.Qt.Window)
display(w5) # works
app.exec_()

这个话题已经在StackOverflow上部分讨论过了。关于QWidget的边框和背景没有被样式表设置的公认答案建议重写paintEvent,如何设置QWidget背景颜色的公认答案?建议设置setAutoFillBackground,如果使用调色板和PySide: QWidget不绘制背景颜色,建议只设置上面提到的WA_StyledBackground。缺少的是QWidget和派生小部件之间差异的原因。

我发现这些差异有点令人困惑:

  • 为什么QWidget的行为不同于QLabel等衍生小部件,…?
  • 为什么QWidget在自然状态下不显示边框或背景图像,但它显示背景颜色?
  • 设置属性WA_StyledBackground和重写属性paintEvent有区别吗?你更喜欢哪种方法?

使用QFrame

我不会试图猜测这个设计决策的原因,但一般来说,QWidget被认为是无边界的。如果您希望您的小部件有漂亮的样式边框,那么您可能应该使用QFrame,它本质上只是一个具有您正在寻找的边框样式功能的QWidget

您会注意到,许多小部件(例如您提到的QLabel)实际上继承自QFrame,而不是直接继承自QWidget

关于WA_StyledBackground属性,我不能权威地说话。

最新更新