Understanding Why setCentralWidget Places Your Widget in the Top-Left

When working with QMainWindow in PyQt6, calling self.setCentralWidget(widget) tells the window to assign that widget to occupy the main area. However, if you explicitly set a fixed width and height on that central widget (for example, using main.setFixedWidth(500) and main.setFixedHeight(250)) while the parent window is larger (e.g., 1000x500), PyQt default behavior is to anchor the fixed-size widget to the top-left corner (position 0,0).

Because QMainWindow does not automatically center central widgets that do not expand to fill the available space, relying solely on setCentralWidget() won't position your UI in the middle.

The Solution: Wrap the Widget or Use Layout Alignment

To center a fixed-size container in PyQt6, the recommended approach is to use a outer container widget as the central widget, apply a layout (such as QGridLayout or QVBoxLayout) to it, and center your content widget inside that layout.

Method 1: Use a Wrapper Central Widget (Recommended)

Create a outer dummy QWidget to serve as the actual central widget, set its layout, and add your inner content widget using Qt.AlignmentFlag.AlignCenter.

from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QWidget, QGridLayout

# Create the container widget
container = QWidget()
container_layout = QGridLayout(container)

# Create your fixed-size content widget
main = QWidget()
main.setFixedHeight(250)
main.setFixedWidth(500)
main.setLayout(v_layout)

# Add the main content widget to the container with alignment
container_layout.addWidget(main, 0, 0, Qt.AlignmentFlag.AlignCenter)

# Set container as the central widget
self.setCentralWidget(container)

Method 2: Remove Fixed Sizes and Use Layout Stretches

Instead of hardcoding fixed sizes like 250x500 on the inner widget, let the PyQt layout system handle sizing dynamically. Adding stretch spaces before and after layout items will center your components cleanly across all display resolutions.

Complete Fixed PyQt6 Code

Here is the updated, working version of your guessing game with proper widget centering:

import sys
import random
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QPushButton,
    QLabel, QLineEdit, QHBoxLayout, QVBoxLayout, QGridLayout
)

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

        self.setWindowTitle("Guess the number!")
        self.setGeometry(100, 100, 1000, 500)

        # Create elements
        self.number_input = QLineEdit(self)
        self.number_input.setFixedHeight(50)
        self.submit_btn = QPushButton("Submit", self)
        self.submit_btn.setFixedHeight(50)
        self.reset_btn = QPushButton("Play Again?", self)
        self.reset_btn.setFixedHeight(50)
        self.reset_btn.hide()
        self.instruct_lbl = QLabel("Enter a number between 1 and 100 inclusive", self)
        self.instruct_lbl.setStyleSheet("color: #c1121f; font-size: 20px; font-weight: 700")
        self.answer_lbl = QLabel("", self)
        self.answer_lbl.setStyleSheet("color: #669bbc; font-size: 20px; font-weight: 700")

        # Connect signals
        self.submit_btn.clicked.connect(self.submitted)
        self.reset_btn.clicked.connect(self.reset)

        # Inner layout
        h_layout = QHBoxLayout()
        v_layout = QVBoxLayout()
        h_layout.addWidget(self.number_input, stretch=3)
        h_layout.addWidget(self.submit_btn, stretch=1)
        h_layout.addWidget(self.reset_btn, stretch=1)
        v_layout.addWidget(self.instruct_lbl)
        v_layout.addLayout(h_layout)
        v_layout.addWidget(self.answer_lbl)

        # Content widget with fixed size
        main_content = QWidget()
        main_content.setLayout(v_layout)
        main_content.setFixedSize(500, 250)

        # Central container widget to hold and center content
        center_container = QWidget()
        container_layout = QGridLayout(center_container)
        container_layout.addWidget(main_content, 0, 0, Qt.AlignmentFlag.AlignCenter)

        self.setCentralWidget(center_container)

        # Random answer initialization
        self.real_answer = random.randint(1, 100)

    def submitted(self):
        self.reset_btn.hide()
        self.user_answer = self.number_input.text()
        self.number_input.clear()

        if not self.user_answer.isdigit():
            self.answer_lbl.setText("Please enter a valid number!")
            return

        val = int(self.user_answer)
        if val != self.real_answer:
            if val > self.real_answer:
                self.answer_lbl.setText(f"Incorrect! {val} is more than the answer.")
            else:
                self.answer_lbl.setText(f"Incorrect! {val} is less than the answer.")
        else:
            self.answer_lbl.setText(f"Correct! {val} is the answer!")
            self.number_input.setEnabled(False)
            self.submit_btn.hide()
            self.reset_btn.show()

    def reset(self):
        self.reset_btn.hide()
        self.submit_btn.show()
        self.real_answer = random.randint(1, 100)
        self.answer_lbl.setText("")
        self.number_input.setEnabled(True)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec())

Summary

Whenever you need a fixed-size widget to sit squarely in the center of a QMainWindow, remember to embed it within an outer container widget utilizing a layout with Qt.AlignmentFlag.AlignCenter.