如何在PySide2的QWidget中添加QMenuBar?菜单栏不显示问题
问题背景
你在Python3的PySide2环境中尝试给QWidget添加QMenuBar,代码运行无报错但菜单栏完全不显示——毕竟QMainWindow集成菜单栏要简单得多,你甚至临时套了一层QMainWindow来绕开问题,但更想找到直接适配QWidget的解决方案。
运行效果截图:
问题根源
QMenuBar在QMainWindow中会被自动绑定到窗口顶部的专属区域,但在QWidget里它只是个普通控件,尤其在macOS系统中,QMenuBar默认开启nativeMenuBar属性,会把菜单栏放到系统顶部而非窗口内;Windows/Linux虽然默认关闭这个属性,但布局设置不当也会导致它被其他控件挤压或隐藏。
轻量修复方案
不需要额外嵌套QMainWindow,只需要给你的代码做两处小调整:
1. 强制菜单栏显示在窗口内
创建QMenuBar后添加一行代码,禁用系统原生菜单栏模式:
self.menubar.setNativeMenuBar(False)
2. 优化布局拉伸策略
给菜单栏所在的布局项设置stretch=0,确保它不会被下方控件挤压变形;同时给右侧的视图设置stretch=1,让它占满剩余窗口空间。
完整修复后的代码
from PySide2.QtWidgets import (QWidget, QApplication, QGraphicsView, QGridLayout) from PySide2 import QtCore, QtWidgets, QtGui from PySide2.QtOpenGL import * from PySide2.QtCore import * from PySide2.QtGui import * image_path_str='image.jpg' class View(QGraphicsView): photo_clicked = QtCore.Signal(QtCore.QPoint) def __init__(self, parent): super(View, self).__init__() self.scene = QtWidgets.QGraphicsScene(self) self.photo = QtWidgets.QGraphicsPixmapItem() self.scene.addItem(self.photo) self.pixmap = QtGui.QPixmap(image_path_str) self.photo.setPixmap(self.pixmap) self.setScene(self.scene) self.setDragMode(QGraphicsView.ScrollHandDrag) class Window(QWidget): def __init__(self): super(Window, self).__init__() self.view = View(self) # 修复核心:配置菜单栏 self.menubar = QtWidgets.QMenuBar() self.menubar.setNativeMenuBar(False) # 强制显示在窗口内 self.archive = self.menubar.addMenu("archive") self.menubar.setObjectName("menubar") # 原有控件布局 self.layout_contain_P1_P2 = QtWidgets.QGridLayout() self.checkbox_P1= QtWidgets.QCheckBox("P1",self) self.line_edit_P1_x = QtWidgets.QLineEdit(self) self.line_edit_P1_x.setReadOnly(True) self.line_edit_P1_y = QtWidgets.QLineEdit(self) self.line_edit_P1_y.setReadOnly(True) self.layout_contain_P1_P2.addWidget(self.checkbox_P1, 0, 0, Qt.AlignLeft) self.grid_layout_P1_x_y = QtWidgets.QGridLayout() self.grid_layout_P1_x_y.addWidget(self.line_edit_P1_x, 1, 0, Qt.AlignLeft) self.grid_layout_P1_x_y.addWidget(self.line_edit_P1_y, 2, 0, Qt.AlignLeft) self.layout_contain_P1_P2.addLayout(self.grid_layout_P1_x_y, 0, 1, 1, 1) self.checkbox_P2 = QtWidgets.QCheckBox("P2",self) self.line_edit_P2_x = QtWidgets.QLineEdit(self) self.line_edit_P2_x.setReadOnly(True) self.line_edit_P2_y = QtWidgets.QLineEdit(self) self.line_edit_P2_y.setReadOnly(True) self.layout_contain_P1_P2.addWidget(self.checkbox_P2, 1, 0, Qt.AlignLeft) self.grid_layout_P2_x_y = QtWidgets.QGridLayout() self.grid_layout_P2_x_y.addWidget(self.line_edit_P2_x, 0, 0, Qt.AlignLeft) self.grid_layout_P2_x_y.addWidget(self.line_edit_P2_y, 1, 0, Qt.AlignLeft) self.layout_contain_P1_P2.addLayout(self.grid_layout_P2_x_y, 1, 1, Qt.AlignLeft) self.combo_box1 = QtWidgets.QComboBox(self) self.combo_box1.addItem("measurements set 1") self.combo_box1.addItem("measurements set 1") self.combo_box2 = QtWidgets.QComboBox(self) self.combo_box2.addItem("P1-P2") self.combo_box2.addItem("P3-P4") # 优化布局拉伸权重 self.vertical1= QtWidgets.QVBoxLayout() self.vertical1.addWidget(self.menubar, stretch=0) # 菜单栏不拉伸 self.vertical1.addWidget(self.combo_box1, stretch=0) self.vertical1.addWidget(self.combo_box2, stretch=0) self.vertical1.addLayout(self.layout_contain_P1_P2, stretch=0) self.vertical2= QtWidgets.QVBoxLayout() self.vertical2.addWidget(self.view, stretch=1) # 视图占满剩余空间 self.horizontal= QtWidgets.QHBoxLayout() self.horizontal.addLayout(self.vertical1, stretch=0) self.horizontal.addLayout(self.vertical2, stretch=1) self.setLayout(self.horizontal) self.setWindowTitle("Image viewer") self.setGeometry(200, 200, 1000, 800) app = QApplication.instance() if app is None: app = QApplication([]) w = Window() w.show() w.raise_() QApplication.setOverrideCursor(QCursor(Qt.CrossCursor)) app.exec_()
额外优化(可选)
如果想让菜单栏横跨整个窗口顶部,可以调整布局结构:把最外层的QHBoxLayout改成先放一个QVBoxLayout,顶部放menubar,下面再放原来的左右分栏布局。
内容的提问来源于stack exchange,提问作者ecjb
相关产品推荐
相关产品推荐


