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

PySide6(QT6)布局压缩问题:如何实现预期界面布局?

问题描述

我试图实现一个包含标签页区域和底部右侧操作按钮的界面布局,但尝试多种布局方式后,最终得到的却是界面被压缩的效果。以下是可复现该问题的最小代码示例,请问我遗漏了什么?

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QTabWidget
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QFormLayout
from PySide6.QtWidgets import QLabel, QPushButton
from PySide6.QtCore import Qt


class CommandWidget(QWidget):

    def __init__(self, parent: QWidget, save_function, cancel_function) -> None:
        super().__init__(parent)

        self.save_button = QPushButton('Save')
        self.quit_button = QPushButton('Quit')

        self.save_button.clicked.connect(save_function)
        self.quit_button.clicked.connect(cancel_function)

        self.layout = QHBoxLayout(self)

        self.layout.addWidget(self.save_button)
        self.layout.addWidget(self.quit_button)


class AboutTab(QWidget):

    def __init__(self, parent: QWidget) -> None:
        super().__init__(parent)

        settings = {
            'Name': 'Test',
            'Version': '1.0.0',
            'Release Type': 'Test'
            }
  
        self.layout = QFormLayout(self)

        self.__add_settings_labels(settings)

    def __add_settings_labels(self, settings: dict[str,str]) -> None:
        for key, value in settings.items():
            key_label = QLabel(f'{key}:')
            key_label.setStyleSheet('font-weight: bold')
            value_label = QLabel(value)

            self.layout.addRow(key_label, value_label)


class SettingsTabDialog(QWidget):

    def __init__(self, parent: QWidget=None, configurations=None) -> None:
        super().__init__(parent)

        tab_widget = QTabWidget()
        tab_widget.addTab(AboutTab(self), 'About')

        widget_layout = QVBoxLayout()
        widget_layout.addWidget(tab_widget)

        self.setLayout(widget_layout)


class MainWindow(QMainWindow):
    def __init__(self, parent: QWidget, configuration=None) -> None:
        super().__init__(parent)

        self.setWindowTitle('Demo')

        self.settingsTabs = SettingsTabDialog(parent=self, configurations=configuration)
        self.command_buttons = CommandWidget(parent=self, save_function=self.save_configuration, cancel_function=self.quit_app)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.settingsTabs)
        self.layout.addWidget(self.command_buttons, alignment=Qt.AlignmentFlag.AlignRight)
        
    def save_configuration(self):
        print('save')
        
    def quit_app(self):
        print('quit')

if __name__ == '__main__':

    config = None
    app = QApplication(sys.argv)
    t = MainWindow(None, configuration=config)
    t.show()

    sys.exit(app.exec())

requirements.txt

pyside6==6.6.0

解决方案

核心问题

QMainWindow是Qt预定义结构的窗口类,不能直接给它设置布局。正确用法是通过setCentralWidget()设置一个中心部件,所有内容布局都应放在这个中心部件内部。直接给QMainWindow设置布局会导致布局逻辑异常,出现界面元素被压缩的问题。

另外,底部按钮栏的对齐需要优化:给按钮栏的布局添加拉伸因子,让左侧自动填充空白空间,确保按钮靠右对齐。

修改后的完整代码

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QTabWidget
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QFormLayout
from PySide6.QtWidgets import QLabel, QPushButton
from PySide6.QtCore import Qt


class CommandWidget(QWidget):

    def __init__(self, parent: QWidget, save_function, cancel_function) -> None:
        super().__init__(parent)

        self.save_button = QPushButton('Save')
        self.quit_button = QPushButton('Quit')

        self.save_button.clicked.connect(save_function)
        self.quit_button.clicked.connect(cancel_function)

        self.layout = QHBoxLayout(self)
        # 添加拉伸因子,让按钮自动靠右
        self.layout.addStretch()
        self.layout.addWidget(self.save_button)
        self.layout.addWidget(self.quit_button)


class AboutTab(QWidget):

    def __init__(self, parent: QWidget) -> None:
        super().__init__(parent)

        settings = {
            'Name': 'Test',
            'Version': '1.0.0',
            'Release Type': 'Test'
            }
  
        self.layout = QFormLayout(self)

        self.__add_settings_labels(settings)

    def __add_settings_labels(self, settings: dict[str,str]) -> None:
        for key, value in settings.items():
            key_label = QLabel(f'{key}:')
            key_label.setStyleSheet('font-weight: bold')
            value_label = QLabel(value)

            self.layout.addRow(key_label, value_label)


class SettingsTabDialog(QWidget):

    def __init__(self, parent: QWidget=None, configurations=None) -> None:
        super().__init__(parent)

        tab_widget = QTabWidget()
        tab_widget.addTab(AboutTab(self), 'About')

        widget_layout = QVBoxLayout()
        widget_layout.addWidget(tab_widget)
        self.setLayout(widget_layout)


class MainWindow(QMainWindow):
    def __init__(self, parent: QWidget, configuration=None) -> None:
        super().__init__(parent)

        self.setWindowTitle('Demo')

        # 创建中心部件,所有布局放在这里
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        self.settingsTabs = SettingsTabDialog(parent=central_widget, configurations=configuration)
        self.command_buttons = CommandWidget(parent=central_widget, save_function=self.save_configuration, cancel_function=self.quit_app)

        # 给中心部件设置布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.addWidget(self.settingsTabs)
        main_layout.addWidget(self.command_buttons)
        
    def save_configuration(self):
        print('save')
        
    def quit_app(self):
        print('quit')

if __name__ == '__main__':

    config = None
    app = QApplication(sys.argv)
    t = MainWindow(None, configuration=config)
    # 设置初始窗口大小,让布局效果更明显
    t.resize(400, 300)
    t.show()

    sys.exit(app.exec())

关键修改点

  1. QMainWindow的正确用法:创建central_widget并通过setCentralWidget()设置,所有布局基于这个中心部件构建,不再直接给MainWindow设置布局。
  2. 按钮栏对齐优化:在CommandWidget的QHBoxLayout中添加addStretch(),让左侧填充空白,按钮自动靠右。
  3. 窗口初始大小:添加t.resize(400, 300),避免窗口默认太小导致布局效果不明显。

内容的提问来源于stack exchange,提问作者Lars Kakavandi-Nielsen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 22:13:13