PAYATHON 2026

PySide6 中如何按 QFrame 高度设置百分比内边距?

数据阿明

结论

Qt 样式表中的 padding: 10% 无法可靠地按外层 QFrame 高度的 10% 设置内边距。可以在外层 QFrame 的 resizeEvent() 中读取当前高度,换算成像素,再通过布局的 setContentsMargins() 更新四边边距。

为什么 margin: 0 没有改变布局边距

样式表中的 margin 是控件的样式属性,QVBoxLayout.setContentsMargins() 设置的则是布局内容区域与布局边缘之间的空间。它们作用于不同层面,因此子控件样式表里的 margin: 0 不会自动改变布局的内容边距。

原代码将外层布局的边距设为零:

outerLayout.setContentsMargins(0, 0, 0, 0)

这样布局的四周就不会预留空间。若要根据外层框的高度设置留白,应更新这个布局的边距。

按高度比例设置边距

下面的示例将四边边距设为外层 QFrame 当前高度的 10%。窗口或外层框大小改变时,代码会重新计算边距:

from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QFrame


class PaddedFrame(QFrame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._layout = QVBoxLayout(self)
        self._layout.setContentsMargins(0, 0, 0, 0)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        padding = round(self.height() * 0.10)
        self._layout.setContentsMargins(padding, padding, padding, padding)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        outer_frame = PaddedFrame()
        outer_frame.setStyleSheet("QFrame { background-color: green; }")

        inner_frame = QFrame()
        inner_frame.setStyleSheet(
            "QFrame { background-color: red; border: 1px inset black; }"
        )

        outer_frame.layout().addWidget(inner_frame)
        self.setCentralWidget(outer_frame)


app = QApplication([])
window = MainWindow()
window.show()
app.exec()

round(self.height() * 0.10) 会将高度换算为整数像素,再传给 setContentsMargins(left, top, right, bottom)。若只需上下留白,可以将计算结果用于第二和第四个参数。若希望水平间距随宽度变化,则应根据宽度单独计算左右边距。

注意事项

这种写法通过布局边距模拟外层框的内边距。边距会占用子控件的可用空间,也可能影响布局的最小尺寸。内容尺寸较大时,可能需要结合布局约束调整窗口的实际高度和预期比例。

备注:内容仅供参考。