You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5中QGridLayout布局比例异常问题求助

解决QGridLayout中PyQtGraph PlotWidget高度比例异常问题

你试图通过QGridLayout的行跨度设置让包含5个绘图的self.p1高度为仅含1个绘图的self.p2的5倍,但实际效果完全相反。问题出在QGridLayout的行高不会自动均等分配,直接依赖行跨度无法保证比例,必须显式设置行的拉伸因子。

解决方案

使用QGridLayout.setRowStretch()方法指定行的拉伸比例,强制布局按设定的比例分配垂直空间:

  • 将两个PlotWidget分别放在同一列的不同行,各占1行;
  • 为对应行设置拉伸因子,比例为5:1;
  • 调整左侧布局的行跨度,让它覆盖两个PlotWidget所在的行。

修改后的关键代码

# 左侧布局占用第0、1行,共2行
grid_layout.addLayout(vlayout_signals, 0, 0, 2, 1)
# 将self.p1放在第0行第1列,self.p2放在第1行第1列
grid_layout.addWidget(self.p1, 0, 1)
grid_layout.addWidget(self.p2, 1, 1)
# 设置行拉伸比例:第0行占5份,第1行占1份
grid_layout.setRowStretch(0, 5)
grid_layout.setRowStretch(1, 1)

完整修改后的代码

NFRAME = 200 * 6

import sys
import numpy as np
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QVBoxLayout, QHBoxLayout, QPushButton, QWidget, QGridLayout, QComboBox, QSlider
from PyQt5.QtGui import QColor
import pyqtgraph as pg

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

        grid_layout = QGridLayout()

        self.p1 = pg.PlotWidget()
        self.p2 = pg.PlotWidget()
        self.p1.plotItem.addLegend()
        self.p2.plotItem.addLegend()
        x = np.linspace(0, 2 * np.pi * 2, NFRAME)
        y1 = np.sin(2 * np.pi * 1 * x)
        y2 = 10 * np.sin(2 * np.pi * 2 * x) + 50
        y3 = 20 * np.sin(2 * np.pi * 3 * x) + 200
        y4 = 30 * np.sin(2 * np.pi * 4 * x) + 300
        y5 = 40 * np.sin(2 * np.pi * 5 * x) + 400

        self.ph1_y1 = self.p1.plot(x, y1, pen=pg.mkPen(QColor(255, 0, 0)), name="y1")
        self.ph1_y2 = self.p1.plot(x, y2, pen=pg.mkPen(QColor(255, 255, 0)), name="y2")
        self.ph1_y3 = self.p1.plot(x, y3, pen=pg.mkPen(QColor(0, 255, 255)), name="y3")
        self.ph1_y4 = self.p1.plot(x, y4, pen=pg.mkPen(QColor(255, 0, 255)), name="y4")
        self.ph1_y5 = self.p1.plot(x, y5, pen=pg.mkPen(QColor(102, 102, 255)), name="y5")
        self.ph2_y1 = self.p2.plot(x, 0 * x + 6)

        signal_select = QComboBox(self)
        signal_select.addItem("Item1")
        signal_select.addItem("Item2")

        signal_offset = QSlider(Qt.Orientation.Vertical)
        signal_gain = QSlider(Qt.Orientation.Vertical)
        hlayout_sliders = QHBoxLayout()
        hlayout_sliders.addWidget(signal_offset)
        hlayout_sliders.addWidget(signal_gain)

        hlayout_sliders_labels = QHBoxLayout()
        signal_offset_label = QLabel()
        signal_gain_label = QLabel()
        signal_offset_label.setText("Offset")
        signal_offset_label.setAlignment(Qt.AlignCenter)
        signal_gain_label.setText("Gain")
        signal_gain_label.setAlignment(Qt.AlignCenter)
        hlayout_sliders_labels.addWidget(signal_offset_label)
        hlayout_sliders_labels.addWidget(signal_gain_label)

        arduino_signal_reset = QPushButton("Reset")

        vlayout_signals = QVBoxLayout()
        vlayout_signals.addWidget(signal_select)
        vlayout_signals.addLayout(hlayout_sliders)
        vlayout_signals.addLayout(hlayout_sliders_labels)
        vlayout_signals.addWidget(arduino_signal_reset)

        # 修正布局设置
        grid_layout.addLayout(vlayout_signals, 0, 0, 2, 1)
        grid_layout.addWidget(self.p1, 0, 1)
        grid_layout.addWidget(self.p2, 1, 1)
        grid_layout.setRowStretch(0, 5)
        grid_layout.setRowStretch(1, 1)

        widget = QWidget()
        widget.setLayout(grid_layout)
        self.setCentralWidget(widget)
        self.setWindowTitle('My software')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    windowExample = MainWindow()
    windowExample.show()
    sys.exit(app.exec_())

原理说明

QGridLayout默认会根据控件的最小尺寸分配行高,直接让控件占用多行时,这些行的高度会被控件的内容撑开,无法保证比例。通过setRowStretch()设置的拉伸因子,会在布局有额外空间时,按比例分配给对应行,从而强制实现你需要的5:1高度比。

内容的提问来源于stack exchange,提问作者shashashamti2008

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:45:37