PyQt5中移除新窗口标题栏并实现弹窗式登录窗口
PyQt5登录弹窗自定义标题栏与窗口重叠问题解决
问题说明
开发PyQt5应用时,点击主窗口按钮弹出登录窗口,需求如下:
- 移除登录窗口系统标题栏(包含最小化、最大化、关闭按钮)
- 自定义标题栏,仅保留标题文本和返回按钮
- 解决窗口弹出时与主窗口重叠的问题
之前使用Qt.FramelessWindowHint和WA_TranslucentBackground未达到预期效果,还出现窗口重叠现象。
修改方案
- 自定义标题栏:在LoginWindow中添加包含标题和返回按钮的顶部布局,替代系统标题栏
- 调整窗口标志:保留
Qt.FramelessWindowHint移除系统标题栏,但去掉WA_TranslucentBackground避免不必要的透明效果 - 设置模态窗口:将登录窗口设为模态,防止用户操作主窗口,同时让弹窗居中显示在主窗口上方
- 优化窗口大小:调整窗口最小尺寸和布局,避免内容溢出
完整修改代码
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_())
关键修改说明
- 自定义标题栏:通过
setup_title_bar方法创建包含返回按钮和标题的顶部栏,替代系统标题栏,同时设置背景色区分 - 窗口标志调整:使用
Qt.Window | Qt.FramelessWindowHint确保窗口能正常显示且无系统标题栏,移除WA_TranslucentBackground避免透明导致的布局问题 - 模态与居中:设置登录窗口为模态(
setModal(True)),防止用户操作主窗口;计算并设置弹窗在主窗口中央的位置,解决重叠问题 - 布局优化:将内容区布局嵌套在主布局中,确保标题栏和内容区正确排列,同时简化
go_back方法逻辑
内容的提问来源于stack exchange,提问作者Shisui Otsutsuki
相关产品推荐
相关产品推荐

