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

QMainWindow中Frame与Toolbar重叠问题排查求助

QMainWindow工具栏与Frame重叠问题解决

问题原因

QMainWindow是具有固定结构的特殊窗口,它的顶层布局负责管理工具栏、状态栏等系统组件的位置,不能直接在这个顶层布局中添加业务内容组件。你直接调用self.layout().addWidget(frame)将Frame加入顶层布局,会导致内容与工具栏区域重叠;添加的QSpacerItem也因为作用于顶层布局,无法起到分隔工具栏和内容的作用。

解决办法

必须通过QMainWindow的**中央部件(Central Widget)**来承载所有业务内容,QMainWindow会自动维护工具栏与中央部件的位置关系,避免重叠。具体步骤:

  • 创建一个QWidget作为中央部件,通过setCentralWidget()绑定到主窗口
  • 给中央部件设置一个布局(如QVBoxLayout)
  • 将所有动态生成的Frame添加到中央部件的布局中

修改后的完整代码

class MainWindow(QMainWindow):
    """ Main application window """
    def __init__(self, settings):
        try:
            QMainWindow.__init__(self)
            self.settings_window = None
            self.settings = settings

            self.setMinimumSize(QSize(700, 700))
            self.setWindowTitle("Titan Quest Modding Advanced - TQMA")

            # 创建工具栏并添加到主窗口
            toolbar = QToolBar("Main toolbar")
            self.addToolBar(toolbar)

            # 设置中央部件及布局
            central_widget = QWidget(self)
            self.setCentralWidget(central_widget)
            self.central_layout = QVBoxLayout(central_widget)

            # 添加设置动作
            settings_action = QAction("Settings", self)
            settings_action.setStatusTip("Edit settings")
            settings_action.triggered.connect(self.get_settings_window)
            toolbar.addAction(settings_action)

            # 动态创建Frame及对应动作
            for frame_name in ["Mod merge", "Mod manager"]:
                frame = QFrame(self, objectName=frame_name)
                layout = QVBoxLayout(frame)
                test_button = QPushButton(frame_name, frame)
                layout.addWidget(test_button)
                frame.setLayout(layout)
                frame.hide()

                frame_action = QAction(frame_name, self)
                frame_action.setStatusTip(frame_name)
                frame_action.triggered.connect(
                    lambda checked, frame_name=frame_name: self.show_frame_by_name(frame_name)
                )
                toolbar.addAction(frame_action)

                # 将Frame添加到中央部件的布局中
                self.central_layout.addWidget(frame)

        except Exception as exc:
            traceback_formatted = traceback.format_exc()
            logger.info(traceback_formatted)
            raise RuntimeError(traceback_formatted) from exc

    def get_settings_window(self):
        """ Generates and shows settings window from which the settings can be edited """
        self.settings_window = SettingsWindow(self.settings)
        self.settings_window.setWindowModality(Qt.WindowModality.ApplicationModal)
        self.settings_window.show()

    def show_frame_by_name(self, frame_name):
        """ Takes a frame name as an input parameter. Searches main window for that frame and returns it """
        frames_to_hide = self.findChildren(QFrame)
        for frame in frames_to_hide:
            frame.hide()
        frame_to_show = self.findChild(QFrame, frame_name)
        logger.debug(f"Found frame: {frame_to_show}")
        if frame_to_show:
            frame_to_show.show()

额外说明

  • 中央部件的布局会自动填充工具栏下方的整个内容区域,窗口大小变化时也会自动适配
  • 原有的show_frame_by_name方法逻辑无需修改,依然可以正常切换Frame的显示状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:35:13