Why is QWidget with border and background image st

2019-08-26 12:57发布

I use the Qt4.8 Python binding PySide (version 1.2.2 on Python 3.3 on Windows) and I see that QWidget behaves different from QWidgetderived widgets like QDialog, QLabel or QMainWindow when styling with stylesheets.

In particular I observe that the attribute WA_StyledBackground must be set to show a border or a background image while a background color is set independently. In contrast for the other widgets this attribute has no influence, a border or background image is always shown. Overriding the paintEvent method is also a possibility.

Example code:

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

This topic is already discussed partly on StackOverflow. The accepted answer on Borders and background of QWidget aren't set by stylesheet suggests overriding paintEvent, the accepted answer of How to set QWidget background color? suggests to set setAutoFillBackground in case one uses the palette and PySide: QWidget does not draw background color suggests to just set the above mentioned WA_StyledBackground. What is missing is the reason for the differences between QWidget and derived widgets.

I find these differences a bit confusing:

  • Why is QWidget behaving different from derived widgets like QLabel,...?
  • Why can QWidget in the natural state not display borders or background images but it does diplay background colors?
  • Is there a difference between setting attribute WA_StyledBackground and overridding paintEvent in the described way? Which method would be preferred?

1条回答
倾城 Initia
2楼-- · 2019-08-26 13:12

tl;dr - Use QFrame

I won't attempt to guess at the reasoning that went into this design decision, but generally speaking QWidget is considered to be borderless. If you want your widget to have nice styled borders, then you should probably be using a QFrame, which essentially just a QWidget with the border styling capabilities that you're looking for.

You'll note that a lot of widgets (such as the QLabel you've mentioned) actually inherit from QFrame rather than directly from QWidget.

I can't speak authoritatively in regards to the WA_StyledBackground property.

查看更多
登录 后发表回答