641 lines
22 KiB
Python
641 lines
22 KiB
Python
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
|
QLineEdit, QPushButton, QFrame, QCheckBox,
|
|
QSpacerItem, QSizePolicy)
|
|
from PyQt5.QtCore import Qt, pyqtSignal, QPropertyAnimation, QEasingCurve, QPoint, QSize, QTimer, QPointF
|
|
from PyQt5.QtGui import QPixmap, QPainter, QLinearGradient, QColor, QIcon, QFont, QBrush
|
|
|
|
|
|
class LoginPage(QWidget):
|
|
login_success = pyqtSignal(str)
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.init_ui()
|
|
self.setup_animations()
|
|
self.gradient_angle = 0
|
|
self.particle_timer = QTimer(self)
|
|
self.particle_timer.timeout.connect(self.update_particles)
|
|
self.particle_timer.start(100) # 更新粒子位置的定时器
|
|
self.particles = self.create_particles()
|
|
|
|
# 添加回车键提交支持
|
|
self.username_input.returnPressed.connect(self.handle_login)
|
|
self.password_input.returnPressed.connect(self.handle_login)
|
|
|
|
def init_ui(self):
|
|
self.setObjectName("loginPage")
|
|
self.setMinimumSize(800, 600)
|
|
|
|
# 主要布局
|
|
main_layout = QHBoxLayout()
|
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
|
main_layout.setSpacing(0)
|
|
self.setLayout(main_layout)
|
|
|
|
# 左侧装饰区 - 添加玻璃态效果
|
|
self.left_frame = QWidget() # 改为QWidget以便自定义绘制
|
|
self.left_frame.setObjectName("leftDecor")
|
|
self.left_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
|
|
# 在左侧装饰区添加艺术字体和版本信息
|
|
left_layout = QVBoxLayout(self.left_frame)
|
|
left_layout.setContentsMargins(40, 40, 40, 40)
|
|
left_layout.addStretch()
|
|
|
|
# 艺术字体标题
|
|
title_container = QFrame()
|
|
title_container.setObjectName("titleContainer")
|
|
title_container.setStyleSheet("background-color: rgba(0, 0, 0, 0.2); border-radius: 15px;")
|
|
title_layout = QVBoxLayout(title_container)
|
|
title_layout.setContentsMargins(30, 30, 30, 30)
|
|
|
|
app_title = QLabel("奶酪云工具箱")
|
|
app_title.setObjectName("appTitle")
|
|
app_title.setAlignment(Qt.AlignCenter)
|
|
app_title.setStyleSheet("""
|
|
#appTitle {
|
|
font-size: 56px;
|
|
font-weight: bold;
|
|
color: white;
|
|
font-family: 'SimHei', 'Microsoft YaHei', sans-serif;
|
|
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5),
|
|
0 0 20px rgba(99, 102, 241, 0.8),
|
|
0 0 30px rgba(99, 102, 241, 0.6),
|
|
0 0 40px rgba(99, 102, 241, 0.4);
|
|
letter-spacing: 5px;
|
|
}
|
|
""")
|
|
|
|
subtitle = QLabel("高效 · 安全 · 云端协作")
|
|
subtitle.setObjectName("subtitle")
|
|
subtitle.setAlignment(Qt.AlignCenter)
|
|
subtitle.setStyleSheet("""
|
|
#subtitle {
|
|
font-size: 18px;
|
|
color: rgba(255, 255, 255, 0.85);
|
|
letter-spacing: 3px;
|
|
margin-top: 10px;
|
|
}
|
|
""")
|
|
|
|
title_layout.addWidget(app_title)
|
|
title_layout.addWidget(subtitle)
|
|
|
|
# 版本信息
|
|
version_info = QWidget()
|
|
version_layout = QVBoxLayout(version_info)
|
|
version_layout.setAlignment(Qt.AlignBottom | Qt.AlignCenter)
|
|
|
|
version_label = QLabel("版本 0.0.1")
|
|
version_label.setObjectName("versionLabel")
|
|
version_label.setAlignment(Qt.AlignCenter)
|
|
version_label.setStyleSheet("""
|
|
#versionLabel {
|
|
color: rgba(255, 255, 255, 0.7);
|
|
font-size: 14px;
|
|
}
|
|
""")
|
|
|
|
author_label = QLabel("作者:年糕崽崽")
|
|
author_label.setObjectName("authorLabel")
|
|
author_label.setAlignment(Qt.AlignCenter)
|
|
author_label.setStyleSheet("""
|
|
#authorLabel {
|
|
color: rgba(255, 255, 255, 0.7);
|
|
font-size: 14px;
|
|
margin-top: 5px;
|
|
}
|
|
""")
|
|
|
|
version_layout.addWidget(version_label)
|
|
version_layout.addWidget(author_label)
|
|
|
|
# 添加到左侧布局
|
|
left_layout.addWidget(title_container)
|
|
left_layout.addStretch()
|
|
left_layout.addWidget(version_info)
|
|
|
|
# 右侧登录区 - 深色背景
|
|
right_frame = QFrame()
|
|
right_frame.setFixedWidth(400)
|
|
right_frame.setObjectName("rightFrame")
|
|
right_frame.setStyleSheet("""
|
|
#rightFrame {
|
|
background-color: rgba(45, 55, 72, 0.85);
|
|
border-left: 1px solid rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
""")
|
|
|
|
main_layout.addWidget(self.left_frame, 3)
|
|
main_layout.addWidget(right_frame, 1)
|
|
|
|
# 右侧登录区布局
|
|
login_layout = QVBoxLayout(right_frame)
|
|
login_layout.setContentsMargins(40, 80, 40, 40)
|
|
login_layout.setSpacing(0)
|
|
|
|
# 标题 - 浅色文字
|
|
title_layout = QVBoxLayout()
|
|
title_layout.setSpacing(10)
|
|
|
|
welcome_label = QLabel("欢迎回来")
|
|
welcome_label.setObjectName("welcomeLabel")
|
|
welcome_label.setAlignment(Qt.AlignCenter)
|
|
|
|
logo_label = QLabel()
|
|
logo_pixmap = QPixmap(":/icons/app_icon.png").scaled(80, 80, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
|
|
# 使图标变为白色以适应深色背景
|
|
painter = QPainter(logo_pixmap)
|
|
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
|
painter.fillRect(logo_pixmap.rect(), Qt.white)
|
|
painter.end()
|
|
|
|
logo_label.setPixmap(logo_pixmap)
|
|
logo_label.setAlignment(Qt.AlignCenter)
|
|
|
|
title_label = QLabel("文档处理中心")
|
|
title_label.setObjectName("titleLabel")
|
|
title_label.setAlignment(Qt.AlignCenter)
|
|
|
|
title_layout.addWidget(welcome_label)
|
|
title_layout.addWidget(logo_label)
|
|
title_layout.addWidget(title_label)
|
|
|
|
# 表单区
|
|
form_frame = QFrame()
|
|
form_frame.setObjectName("formFrame")
|
|
|
|
form_layout = QVBoxLayout(form_frame)
|
|
form_layout.setContentsMargins(0, 40, 0, 0)
|
|
form_layout.setSpacing(25)
|
|
|
|
# 用户名输入框
|
|
username_frame = QFrame()
|
|
username_frame.setObjectName("inputFrame")
|
|
username_layout = QHBoxLayout(username_frame)
|
|
username_layout.setContentsMargins(15, 0, 15, 0)
|
|
username_layout.setSpacing(10)
|
|
|
|
username_icon = QLabel()
|
|
username_pixmap = QPixmap(":/icons/user.png").scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
|
|
# 使图标变为白色
|
|
painter = QPainter(username_pixmap)
|
|
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
|
painter.fillRect(username_pixmap.rect(), Qt.white)
|
|
painter.end()
|
|
username_icon.setPixmap(username_pixmap)
|
|
|
|
self.username_input = QLineEdit()
|
|
self.username_input.setObjectName("usernameInput")
|
|
self.username_input.setPlaceholderText("请输入用户名")
|
|
self.username_input.setStyleSheet("""
|
|
#usernameInput {
|
|
border: none;
|
|
background: transparent;
|
|
font-size: 15px;
|
|
color: #e2e8f0;
|
|
padding: 12px 0;
|
|
}
|
|
#usernameInput:focus {
|
|
outline: none;
|
|
}
|
|
""")
|
|
self.username_input.setAttribute(Qt.WA_MacShowFocusRect, 0)
|
|
|
|
username_layout.addWidget(username_icon)
|
|
username_layout.addWidget(self.username_input)
|
|
|
|
# 密码输入框
|
|
password_frame = QFrame()
|
|
password_frame.setObjectName("inputFrame")
|
|
password_layout = QHBoxLayout(password_frame)
|
|
password_layout.setContentsMargins(15, 0, 15, 0)
|
|
password_layout.setSpacing(10)
|
|
|
|
password_icon = QLabel()
|
|
password_pixmap = QPixmap(":/icons/lock.png").scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
|
|
# 使图标变为白色
|
|
painter = QPainter(password_pixmap)
|
|
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
|
painter.fillRect(password_pixmap.rect(), Qt.white)
|
|
painter.end()
|
|
password_icon.setPixmap(password_pixmap)
|
|
|
|
self.password_input = QLineEdit()
|
|
self.password_input.setObjectName("passwordInput")
|
|
self.password_input.setPlaceholderText("请输入密码")
|
|
self.password_input.setEchoMode(QLineEdit.Password)
|
|
self.password_input.setStyleSheet("""
|
|
#passwordInput {
|
|
border: none;
|
|
background: transparent;
|
|
font-size: 15px;
|
|
color: #e2e8f0;
|
|
padding: 12px 0;
|
|
}
|
|
#passwordInput:focus {
|
|
outline: none;
|
|
}
|
|
""")
|
|
self.password_input.setAttribute(Qt.WA_MacShowFocusRect, 0)
|
|
|
|
# 显示/隐藏密码按钮
|
|
self.toggle_password_btn = QPushButton()
|
|
self.toggle_password_btn.setObjectName("togglePasswordBtn")
|
|
|
|
# 加载图标并设置为白色
|
|
eye_off_pixmap = QPixmap(":/icons/eye_off.png").scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
painter = QPainter(eye_off_pixmap)
|
|
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
|
painter.fillRect(eye_off_pixmap.rect(), Qt.white)
|
|
painter.end()
|
|
|
|
self.toggle_password_btn.setIcon(QIcon(eye_off_pixmap))
|
|
self.toggle_password_btn.setIconSize(QSize(18, 18))
|
|
self.toggle_password_btn.setStyleSheet("background: transparent; border: none;")
|
|
self.toggle_password_btn.clicked.connect(self.toggle_password_visibility)
|
|
|
|
password_layout.addWidget(password_icon)
|
|
password_layout.addWidget(self.password_input)
|
|
password_layout.addWidget(self.toggle_password_btn)
|
|
|
|
# 记住我选项
|
|
remember_layout = QHBoxLayout()
|
|
remember_layout.setContentsMargins(15, 0, 0, 0)
|
|
|
|
self.remember_check = QCheckBox("记住我")
|
|
self.remember_check.setObjectName("rememberCheck")
|
|
self.remember_check.setStyleSheet("""
|
|
#rememberCheck {
|
|
color: #cbd5e0;
|
|
font-size: 13px;
|
|
}
|
|
""")
|
|
|
|
forget_btn = QPushButton("忘记密码?")
|
|
forget_btn.setObjectName("forgetPassword")
|
|
forget_btn.setStyleSheet("""
|
|
#forgetPassword {
|
|
color: #a0aec0;
|
|
font-size: 13px;
|
|
background: transparent;
|
|
border: none;
|
|
text-decoration: none;
|
|
}
|
|
#forgetPassword:hover {
|
|
color: #818cf8;
|
|
text-decoration: underline;
|
|
}
|
|
""")
|
|
|
|
remember_layout.addWidget(self.remember_check)
|
|
remember_layout.addStretch()
|
|
remember_layout.addWidget(forget_btn)
|
|
|
|
# 错误提示
|
|
self.error_label = QLabel()
|
|
self.error_label.setObjectName("errorLabel")
|
|
self.error_label.setStyleSheet("""
|
|
#errorLabel {
|
|
color: #fc8181;
|
|
font-size: 13px;
|
|
padding-left: 15px;
|
|
min-height: 20px;
|
|
}
|
|
""")
|
|
self.error_label.hide()
|
|
|
|
# 登录按钮
|
|
login_btn = QPushButton("登录")
|
|
login_btn.setObjectName("loginBtn")
|
|
login_btn.clicked.connect(self.handle_login)
|
|
|
|
# 添加表单元素
|
|
form_layout.addWidget(username_frame)
|
|
form_layout.addWidget(password_frame)
|
|
form_layout.addLayout(remember_layout)
|
|
form_layout.addWidget(self.error_label)
|
|
form_layout.addWidget(login_btn, 0, Qt.AlignCenter)
|
|
|
|
# 底部区域
|
|
footer_layout = QVBoxLayout()
|
|
footer_layout.setContentsMargins(0, 30, 0, 0)
|
|
footer_layout.setSpacing(10)
|
|
|
|
signup_layout = QHBoxLayout()
|
|
signup_layout.setAlignment(Qt.AlignCenter)
|
|
|
|
signup_label = QLabel("没有账户?")
|
|
signup_label.setStyleSheet("color: #a0aec0; font-size: 13px;")
|
|
|
|
signup_btn = QPushButton("立即注册")
|
|
signup_btn.setObjectName("signupBtn")
|
|
signup_btn.setStyleSheet("""
|
|
#signupBtn {
|
|
background: transparent;
|
|
border: none;
|
|
color: #818cf8;
|
|
font-weight: 600;
|
|
font-size: 13px;
|
|
padding: 0 5px;
|
|
}
|
|
#signupBtn:hover {
|
|
text-decoration: underline;
|
|
}
|
|
""")
|
|
|
|
signup_layout.addWidget(signup_label)
|
|
signup_layout.addWidget(signup_btn)
|
|
|
|
footer_layout.addLayout(signup_layout, Qt.AlignCenter)
|
|
|
|
# 添加所有组件到主布局
|
|
login_layout.addLayout(title_layout)
|
|
login_layout.addWidget(form_frame)
|
|
login_layout.addLayout(footer_layout)
|
|
|
|
# 应用样式
|
|
self.apply_styles()
|
|
|
|
def apply_styles(self):
|
|
# 设置全局样式 - 暗色主题
|
|
self.setStyleSheet("""
|
|
/* 登录页面背景渐变 - 深色 */
|
|
#loginPage {
|
|
background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
|
|
stop:0 #1a202c, stop:1 #2d3748);
|
|
}
|
|
|
|
/* 左侧装饰区玻璃效果 - 深色 */
|
|
#leftDecor {
|
|
background: rgba(45, 55, 72, 0.15);
|
|
border-radius: 0px;
|
|
backdrop-filter: blur(15px);
|
|
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
border-left: none;
|
|
}
|
|
|
|
/* 欢迎文本 - 浅色 */
|
|
#welcomeLabel {
|
|
font-size: 22px;
|
|
font-weight: 300;
|
|
color: #e2e8f0;
|
|
letter-spacing: 2px;
|
|
}
|
|
|
|
/* 主标题 - 浅色 */
|
|
#titleLabel {
|
|
font-size: 28px;
|
|
font-weight: bold;
|
|
color: #ffffff;
|
|
margin-bottom: 15px;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
/* 输入框容器 - 深色 */
|
|
#inputFrame {
|
|
background: rgba(30, 41, 59, 0.5);
|
|
border: 1px solid #4a5568;
|
|
border-radius: 8px;
|
|
padding: 5px 0;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
#inputFrame:hover {
|
|
border-color: #5b6e91;
|
|
box-shadow: 0 2px 8px rgba(99, 102, 241, 0.2);
|
|
}
|
|
|
|
#inputFrame:focus-within {
|
|
border-color: #818cf8;
|
|
box-shadow: 0 2px 12px rgba(99, 102, 241, 0.3);
|
|
}
|
|
|
|
/* 登录按钮 - 紫色主题 */
|
|
#loginBtn {
|
|
background-color: #6366f1;
|
|
color: white;
|
|
border-radius: 8px;
|
|
padding: 14px 30px;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
border: none;
|
|
min-width: 240px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
#loginBtn:hover {
|
|
background-color: #4f46e5;
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
|
|
}
|
|
|
|
#loginBtn:pressed {
|
|
transform: translateY(0);
|
|
box-shadow: 0 2px 6px rgba(99, 102, 241, 0.3);
|
|
}
|
|
""")
|
|
|
|
def setup_animations(self):
|
|
# 创建输入框动画
|
|
self.username_anim = QPropertyAnimation(self.username_input, b"pos")
|
|
self.username_anim.setDuration(300)
|
|
self.username_anim.setEasingCurve(QEasingCurve.OutQuad)
|
|
|
|
self.password_anim = QPropertyAnimation(self.password_input, b"pos")
|
|
self.password_anim.setDuration(300)
|
|
self.password_anim.setEasingCurve(QEasingCurve.OutQuad)
|
|
|
|
def create_particles(self):
|
|
particles = []
|
|
for _ in range(30): # 创建30个粒子
|
|
size = 2 + 5 * (0.5) # 随机大小
|
|
x = 50 + 700 * (0.5) # 随机X位置
|
|
y = 50 + 500 * (0.5) # 随机Y位置
|
|
speed_x = -1 + 2 * (0.5) # X方向速度
|
|
speed_y = -1 + 2 * (0.5) # Y方向速度
|
|
color = QColor( # 随机蓝色调
|
|
int(100 + 155 * (0.5)),
|
|
int(180 + 75 * (0.5)),
|
|
int(255 - 50 * (0.5)),
|
|
int(50 + 100 * (0.5))
|
|
)
|
|
particles.append({
|
|
'x': x, 'y': y,
|
|
'size': size,
|
|
'speed_x': speed_x, 'speed_y': speed_y,
|
|
'color': color
|
|
})
|
|
return particles
|
|
|
|
def update_particles(self):
|
|
for p in self.particles:
|
|
# 更新粒子位置
|
|
p['x'] += p['speed_x']
|
|
p['y'] += p['speed_y']
|
|
|
|
# 边界反弹
|
|
if p['x'] <= 0 or p['x'] >= self.width():
|
|
p['speed_x'] *= -1
|
|
if p['y'] <= 0 or p['y'] >= self.height():
|
|
p['speed_y'] *= -1
|
|
|
|
self.left_frame.update() # 触发重绘
|
|
|
|
def toggle_password_visibility(self):
|
|
if self.password_input.echoMode() == QLineEdit.Password:
|
|
self.password_input.setEchoMode(QLineEdit.Normal)
|
|
|
|
# 更新眼睛图标
|
|
eye_on_pixmap = QPixmap(":/icons/eye_on.png").scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
painter = QPainter(eye_on_pixmap)
|
|
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
|
painter.fillRect(eye_on_pixmap.rect(), Qt.white)
|
|
painter.end()
|
|
|
|
self.toggle_password_btn.setIcon(QIcon(eye_on_pixmap))
|
|
else:
|
|
self.password_input.setEchoMode(QLineEdit.Password)
|
|
|
|
# 更新眼睛图标
|
|
eye_off_pixmap = QPixmap(":/icons/eye_off.png").scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
painter = QPainter(eye_off_pixmap)
|
|
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
|
painter.fillRect(eye_off_pixmap.rect(), Qt.white)
|
|
painter.end()
|
|
|
|
self.toggle_password_btn.setIcon(QIcon(eye_off_pixmap))
|
|
|
|
def handle_login(self):
|
|
username = self.username_input.text().strip()
|
|
password = self.password_input.text().strip()
|
|
|
|
# 验证登录
|
|
if not username:
|
|
self.show_error("请输入用户名")
|
|
self.animate_error(self.username_input)
|
|
return
|
|
|
|
if not password:
|
|
self.show_error("请输入密码")
|
|
self.animate_error(self.password_input)
|
|
return
|
|
|
|
# 实际登录验证
|
|
if username in ["liqi", "qiqi991012"] and password == "qiqi991012":
|
|
self.error_label.hide()
|
|
self.login_success.emit(username)
|
|
else:
|
|
self.show_error("用户名或密码错误")
|
|
self.animate_error(self.password_input)
|
|
|
|
def animate_error(self, input_field):
|
|
# 保存原始位置
|
|
original_pos = input_field.pos()
|
|
|
|
# 创建抖动动画
|
|
animation = QPropertyAnimation(input_field, b"pos")
|
|
animation.setDuration(70)
|
|
animation.setLoopCount(3)
|
|
animation.setEasingCurve(QEasingCurve.InOutSine)
|
|
|
|
# 左右各抖动3次
|
|
positions = [
|
|
QPoint(original_pos.x() + 5, original_pos.y()),
|
|
QPoint(original_pos.x() - 5, original_pos.y()),
|
|
original_pos
|
|
]
|
|
|
|
for i, pos in enumerate(positions):
|
|
animation.setKeyValueAt(i / len(positions), pos)
|
|
|
|
animation.start()
|
|
|
|
def show_error(self, message):
|
|
self.error_label.setText(message)
|
|
self.error_label.show()
|
|
|
|
# 添加红色边框效果(暗色主题版本)
|
|
self.username_input.parent().setStyleSheet("#inputFrame { border: 1px solid #fc8181; }")
|
|
self.password_input.parent().setStyleSheet("#inputFrame { border: 1px solid #fc8181; }")
|
|
|
|
# 2秒后恢复
|
|
QTimer.singleShot(2000, self.reset_styles)
|
|
|
|
def reset_styles(self):
|
|
self.username_input.parent().setStyleSheet("#inputFrame { border: 1px solid #4a5568; }")
|
|
self.password_input.parent().setStyleSheet("#inputFrame { border: 1px solid #4a5568; }")
|
|
|
|
def paintEvent(self, event):
|
|
# 绘制背景渐变 - 深色主题
|
|
painter = QPainter(self)
|
|
painter.setRenderHint(QPainter.Antialiasing)
|
|
|
|
# 创建渐变背景
|
|
gradient = QLinearGradient(0, 0, self.width(), self.height())
|
|
gradient.setColorAt(0, QColor("#1a202c"))
|
|
gradient.setColorAt(1, QColor("#2d3748"))
|
|
|
|
painter.fillRect(self.rect(), gradient)
|
|
|
|
# 绘制装饰性气泡 - 深色主题
|
|
painter.setPen(Qt.NoPen)
|
|
|
|
# 左上角大泡 - 使用深紫色
|
|
painter.setBrush(QColor(79, 70, 229, 30))
|
|
painter.drawEllipse(QPoint(50, 70), 150, 150)
|
|
|
|
# 左下角中泡 - 使用深蓝色
|
|
painter.setBrush(QColor(49, 46, 129, 40))
|
|
painter.drawEllipse(QPoint(100, 450), 80, 80)
|
|
|
|
# 右边中泡 - 使用深青色
|
|
painter.setBrush(QColor(15, 23, 42, 50))
|
|
painter.drawEllipse(QPoint(600, 150), 100, 100)
|
|
|
|
# 中央小泡 - 使用深绿色
|
|
painter.setBrush(QColor(6, 78, 59, 60))
|
|
painter.drawEllipse(QPoint(250, 300), 50, 50)
|
|
|
|
super().paintEvent(event)
|
|
|
|
# 专门绘制左侧装饰区域的粒子效果
|
|
if self.left_frame.isVisible():
|
|
# 保存当前绘画状态
|
|
painter.save()
|
|
|
|
# 将绘画区域限制在左侧框架内
|
|
painter.translate(self.left_frame.pos())
|
|
painter.setClipRect(self.left_frame.rect())
|
|
|
|
# 绘制动态粒子
|
|
for p in self.particles:
|
|
painter.setBrush(QBrush(p['color']))
|
|
painter.setPen(Qt.NoPen)
|
|
painter.drawEllipse(QPointF(p['x'], p['y']), p['size'], p['size'])
|
|
|
|
# 绘制发光的光斑背景
|
|
gradient = QLinearGradient(0, 0, self.width(), self.height())
|
|
gradient.setColorAt(0, QColor(99, 102, 241, 20)) # 紫色
|
|
gradient.setColorAt(0.5, QColor(79, 70, 229, 40)) # 更亮的紫色
|
|
gradient.setColorAt(1, QColor(49, 46, 129, 20)) # 深紫色
|
|
painter.setBrush(QBrush(gradient))
|
|
painter.drawRect(0, 0, self.left_frame.width(), self.left_frame.height())
|
|
|
|
painter.restore()
|
|
|
|
|
|
# 使用示例
|
|
if __name__ == "__main__":
|
|
from PyQt5.QtWidgets import QApplication
|
|
import sys
|
|
|
|
app = QApplication(sys.argv)
|
|
login_page = LoginPage()
|
|
login_page.login_success.connect(lambda username: print(f"登录成功: {username}"))
|
|
login_page.show()
|
|
sys.exit(app.exec_()) |