PyQt5中QWidget无法在QMainWindow显示,需单窗口内打开子部件
Got it, let's tackle this problem. The root issue here is that you're likely creating a new QWidget and calling show() on it when clicking that blue area—which is why a separate window pops up instead of loading inside your main window. QMainWindow relies on its central widget to hold the main content, so we need to manage content switching through that.
The best approach here is to use a QStackedWidget as your main window's central widget. This widget acts like a container for multiple pages, letting you switch between them without opening new windows. Here's a step-by-step solution with example code:
Step 1: Define Your Page Widgets
First, create separate QWidget subclasses for each of your interfaces: your home page, the "View/Edit Processed Slices" page (your Figure 1), and the target page you want to load (your Figure 2).
from PyQt5.QtWidgets import ( QMainWindow, QWidget, QStackedWidget, QVBoxLayout, QMenuBar, QMenu, QAction, QLabel, QPushButton, QFrame ) from PyQt5.QtGui import QColor from PyQt5.QtCore import pyqtSignal class HomePage(QWidget): def __init__(self): super().__init__() layout = QVBoxLayout() layout.addWidget(QLabel("This is your main home page")) self.setLayout(layout) class ProcessedSlicesPage(QWidget): # Define a custom signal to notify main window to switch pages switch_to_target = pyqtSignal() def __init__(self): super().__init__() layout = QVBoxLayout() # Your "blue rectangle" area (simulated with a styled button here) blue_area = QPushButton("Click this blue area") blue_area.setStyleSheet("background-color: #4287f5; color: white; padding: 20px;") blue_area.clicked.connect(self.switch_to_target.emit) # Emit signal on click layout.addWidget(QLabel("View/Edit Processed Slices (Figure 1)")) layout.addWidget(blue_area) self.setLayout(layout) class TargetPage(QWidget): def __init__(self): super().__init__() layout = QVBoxLayout() layout.addWidget(QLabel("This is your target page (Figure 2)")) self.setLayout(layout)
Step 2: Set Up Main Window with QStackedWidget
In your main window class, set QStackedWidget as the central widget, add all your page widgets to it, and connect menu actions and page signals to switch between pages.
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Single Window Interface") self.setGeometry(100, 100, 800, 600) # Create stacked widget as central widget self.stacked_widget = QStackedWidget() self.setCentralWidget(self.stacked_widget) # Add all pages to stacked widget self.home_page = HomePage() self.slices_page = ProcessedSlicesPage() self.target_page = TargetPage() self.stacked_widget.addWidget(self.home_page) self.stacked_widget.addWidget(self.slices_page) self.stacked_widget.addWidget(self.target_page) # Set initial page to home self.stacked_widget.setCurrentWidget(self.home_page) # Create menu bar self._create_menu_bar() # Connect the slices page's signal to switch to target page self.slices_page.switch_to_target.connect(self._show_target_page) def _create_menu_bar(self): menu_bar = self.menuBar() view_edit_menu = menu_bar.addMenu("View/Edit") # Add action for "View/Edit Processed Slices" view_slices_action = QAction("View/Edit Processed Slices", self) view_slices_action.triggered.connect(self._show_slices_page) view_edit_menu.addAction(view_slices_action) def _show_slices_page(self): # Switch to the processed slices page self.stacked_widget.setCurrentWidget(self.slices_page) def _show_target_page(self): # Switch to the target page (Figure 2) self.stacked_widget.setCurrentWidget(self.target_page)
Step 3: Run the Application
Finally, set up and run your app:
if __name__ == "__main__": import sys from PyQt5.QtWidgets import QApplication app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
Key Notes to Remember
- Never call
show()on a new QWidget if you want it inside the main window—this creates a separate top-level window. QStackedWidgetis perfect for this use case: it holds multiple widgets but only displays one at a time. You can switch between them using eithersetCurrentIndex()orsetCurrentWidget().- Use custom signals (like
switch_to_targetin the example) to let child pages communicate with the main window. This keeps your code clean and decoupled.
With this setup, clicking the menu will load the Processed Slices page in your main window, and clicking the blue area will switch directly to your target page—all without opening any new windows.
内容的提问来源于stack exchange,提问作者Migui Mag

