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

PyQt5中移除新窗口标题栏并实现弹窗式登录窗口

PyQt5登录弹窗自定义标题栏与窗口重叠问题解决

问题说明

开发PyQt5应用时,点击主窗口按钮弹出登录窗口,需求如下:

  • 移除登录窗口系统标题栏(包含最小化、最大化、关闭按钮)
  • 自定义标题栏,仅保留标题文本和返回按钮
  • 解决窗口弹出时与主窗口重叠的问题

之前使用Qt.FramelessWindowHint和WA_TranslucentBackground未达到预期效果,还出现窗口重叠现象。

修改方案

  1. 自定义标题栏:在LoginWindow中添加包含标题和返回按钮的顶部布局,替代系统标题栏
  2. 调整窗口标志:保留Qt.FramelessWindowHint移除系统标题栏,但去掉WA_TranslucentBackground避免不必要的透明效果
  3. 设置模态窗口:将登录窗口设为模态,防止用户操作主窗口,同时让弹窗居中显示在主窗口上方
  4. 优化窗口大小:调整窗口最小尺寸和布局,避免内容溢出

完整修改代码

from PyQt5.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QLabel, QLineEdit, QPushButton, QSizePolicy)
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt

class LoginWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 设置窗口标志:无边框 + 窗口类型
        self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
        # 移除透明背景属性,避免不必要的透明效果
        self.setStyleSheet("background-color: #F8F8F8;")
        self.setMinimumSize(500, 500)

        self.setup_title_bar()
        self.setup_ui()

    def setup_title_bar(self):
        # 自定义标题栏布局
        title_bar = QWidget(self)
        title_bar.setStyleSheet("background-color: #E8E8E8; padding: 8px;")
        title_bar_layout = QHBoxLayout(title_bar)
        title_bar_layout.setContentsMargins(0, 0, 0, 0)

        # 返回按钮
        back_arrow = QPushButton("←", self)
        back_arrow.setStyleSheet(
            "QPushButton {background-color: transparent; color: black; font-size: 20px; font-weight: bold;}"
            "QPushButton:hover {color: #555555;}"
        )
        back_arrow.setFixedSize(40, 40)
        back_arrow.clicked.connect(self.go_back)

        # 标题文本
        title_label = QLabel("Login", self)
        title_label.setFont(QFont("Arial", 14, QFont.Bold))
        title_label.setAlignment(Qt.AlignCenter)

        title_bar_layout.addWidget(back_arrow)
        title_bar_layout.addWidget(title_label)
        title_bar_layout.addStretch()

        # 主布局包含标题栏和内容区
        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)

        main_layout.addWidget(title_bar)
        self.content_layout = QVBoxLayout()
        self.content_layout.setAlignment(Qt.AlignCenter)
        self.content_layout.setSpacing(20)
        main_layout.addLayout(self.content_layout)

    def setup_ui(self):
        username_label = QLabel("Username", self)
        username_label.setFont(QFont("Arial", 12))

        username_input = QLineEdit(self)
        username_input.setPlaceholderText("Enter your username")
        username_input.setFixedWidth(250)

        organization_label = QLabel("Organization", self)
        organization_label.setFont(QFont("Arial", 12))

        organization_input = QLineEdit(self)
        organization_input.setPlaceholderText("Enter your organization name")
        organization_input.setFixedWidth(250)

        next_button = QPushButton("Next", self)
        next_button.setStyleSheet(
            "QPushButton {background-color: #000000; color: white; border-radius: 10px; padding: 10px;}"
            "QPushButton:hover {background-color: #333333;}"
            "QPushButton:pressed {background-color: #555555;}"
        )

        self.content_layout.addSpacing(20)
        self.content_layout.addWidget(username_label)
        self.content_layout.addWidget(username_input)
        self.content_layout.addWidget(organization_label)
        self.content_layout.addWidget(organization_input)
        self.content_layout.addSpacing(20)
        self.content_layout.addWidget(next_button, alignment=Qt.AlignHCenter)

    def go_back(self):
        self.close()
        if self.parent():
            self.parent().setEnabled(True)

class StartupWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Startup Window")
        self.setFixedSize(500, 300)
        self.setStyleSheet("background-color: #F8F8F8;")

        self.setup_ui()

    def setup_ui(self):
        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)

        main_layout = QVBoxLayout(central_widget)
        main_layout.setAlignment(Qt.AlignCenter)
        main_layout.setSpacing(20)
        main_layout.addStretch(1)

        button_layout = QHBoxLayout()
        button_layout.setAlignment(Qt.AlignCenter)

        login_button = QPushButton("Login", self)
        login_button.setStyleSheet(
            "QPushButton {background-color: #44A147; color: white; border-radius: 10px; "
            "padding-left: 20px; padding-right: 20px; padding-top: 10px; padding-bottom: 10px;}"
            "QPushButton:hover {background-color: #3B8548;}"
        )

        signup_button = QPushButton("Sign Up", self)
        signup_button.setStyleSheet(
            "QPushButton {background-color: #007BFF; color: white; border-radius: 10px; padding-left: 20px; "
            "padding-right: 20px; padding-top: 10px; padding-bottom: 10px;} "
            "QPushButton:hover {background-color: #0069D9;}"
        )

        exit_button = QPushButton("Close/Exit", self)
        exit_button.setStyleSheet(
            "QPushButton {background-color: #DC3545; color: white; border-radius: 10px; padding: 10px;}"
            "QPushButton:hover {background-color: #C82333;}"
        )

        login_button.clicked.connect(self.open_login_window)

        button_layout.addWidget(login_button)
        button_layout.addSpacing(20)
        button_layout.addWidget(signup_button)

        main_layout.addLayout(button_layout)
        main_layout.addStretch(1)
        main_layout.addWidget(exit_button, alignment=Qt.AlignCenter)

    def open_login_window(self):
        self.setEnabled(False)
        self.login_window = LoginWindow(self)
        # 设置模态窗口,居中显示在主窗口上方
        self.login_window.setModal(True)
        # 计算居中位置
        parent_geo = self.geometry()
        window_geo = self.login_window.geometry()
        x = parent_geo.x() + (parent_geo.width() - window_geo.width()) // 2
        y = parent_geo.y() + (parent_geo.height() - window_geo.height()) // 2
        self.login_window.move(x, y)
        self.login_window.show()

# 运行示例
if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication
    app = QApplication(sys.argv)
    window = StartupWindow()
    window.show()
    sys.exit(app.exec_())

关键修改说明

  1. 自定义标题栏:通过setup_title_bar方法创建包含返回按钮和标题的顶部栏,替代系统标题栏,同时设置背景色区分
  2. 窗口标志调整:使用Qt.Window | Qt.FramelessWindowHint确保窗口能正常显示且无系统标题栏,移除WA_TranslucentBackground避免透明导致的布局问题
  3. 模态与居中:设置登录窗口为模态(setModal(True)),防止用户操作主窗口;计算并设置弹窗在主窗口中央的位置,解决重叠问题
  4. 布局优化:将内容区布局嵌套在主布局中,确保标题栏和内容区正确排列,同时简化go_back方法逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:15:02