自定义类中包装的QLabel上的意外填充

时间:2018-04-19 01:28:33

标签: python pyqt pyqt5 padding

我想在包装QLabel的QWidget周围显示一个边框(这是一个更复杂的小部件的练习)。我正在使用setStyleSheet来创建边框。当我手动执行此操作时,它按预期工作。但是,当我将代码移动到自己的类(从QWidget派生)时,填充是不同的,我无法弄清楚为什么。

Output of code example

import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QMainWindow, QVBoxLayout 

class WrappedLabel(QWidget):
    def __init__(self, text=''):
        super().__init__()

        self.text = QLabel(text)
        layout = QVBoxLayout()
        layout.addWidget(self.text)
        self.setLayout(layout)
        self.setStyleSheet('padding: 2px; border: 2px solid red;')


class Shell(QMainWindow):

    def __init__(self):  # constructor
        super().__init__()  # call the parent's constructor

        w = QWidget() # Create the main window content widget
        self.setCentralWidget(w)

        # First label
        unwrapped_label = QLabel('This is a normal QLabel with a border and no padding.')
        unwrapped_label.setStyleSheet('border: 2px solid gray; padding: 2px;')

        # Second label
        wrapped_label = QLabel('This QLabel is manually wrapped in a styled QWidget. ' + 
            'There is a slight indent compared to the normal QLabel due to padding.')
        wrapped_layout = QVBoxLayout()
        wrapped_layout.addWidget(wrapped_label)
        manual_wrapper = QWidget()
        manual_wrapper.setObjectName('wrapper')
        manual_wrapper.setLayout(wrapped_layout)
        self.setStyleSheet('QWidget#wrapper { border: 2px solid gray; padding: 2px; }')

        # Third label
        derived_wrapper = WrappedLabel('This class derives from QWidget and wraps a QLabel like above, but is indented even further and the border is in the wrong spot.')

        vbox = QVBoxLayout()
        vbox.addWidget(unwrapped_label)
        vbox.addWidget(manual_wrapper)
        vbox.addWidget(derived_wrapper)
        vbox.addStretch(1) # Squish them together to better see the spacing

        w.setLayout(vbox)

        # Setup the rest of the main window appearance
        self.setGeometry(300,300,640,180)
        self.setWindowTitle('Testing wrapped labels')

        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    shell = Shell() # create and show the main window
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:2)

首先,自定义类WrappedLabel中的代码与手动窗口小部件中的代码不完全相同。对于手动窗口小部件,您要确保样式表仅应用于窗口小部件本身,而不是应用于QWidget#wrapper的任何子窗口小部件。对于自定义类,您只需将样式表应用于WrappedLabel实例,这将导致它cascade到其所有子窗口小部件(以及QLabel实例)。这就是你的QLabel实例以填充和红色边框结束的原因。

那为什么包装器不会发生同样的情况呢?显然,QWidget的自定义基类默认拒绝所有应用的样式表(请参阅this answer)。您可以在self.setAttribute(QtCore.Qt.WA_StyledBackground)中添加WrappedLabel.__init__来完成此工作。现在,您将看到最终有两个边框,一个用于包装,另一个用于标签。要将样式表限制为包装器,您需要应用与手动窗口小部件类似的标识符:self.setStyleSheet('WrappedLabel { padding: 2px; border: 2px solid red; }')

为了使其有效,您可以将其添加到WrappedLabel.__init__

self.setAttribute(QtCore.Qt.WA_StyledBackground)
self.setStyleSheet('WrappedLabel { padding: 2px; border: 2px solid red; }')