feat(core): 优化窗口动画和布局

- 新增按钮点击动画效果
- 动态调整窗口大小和布局
- 实现圆角窗口和拖动功能
- 优化安装按钮状态管理
- 更新菜单动画逻辑
- 为2.0新窗口做预实现
This commit is contained in:
hyb-oyqq
2025-07-25 15:18:05 +08:00
parent 0f9c91b59a
commit 286270a819
6 changed files with 661 additions and 88 deletions

BIN
source/IMG/BG/title_bg1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
source/IMG/BG/title_bg2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -1,15 +1,24 @@
import sys
from PySide6.QtCore import (QObject, QPropertyAnimation, QParallelAnimationGroup, from PySide6.QtCore import (QObject, QPropertyAnimation, QParallelAnimationGroup,
QPoint, QEasingCurve, QTimer, Signal) QPoint, QEasingCurve, QTimer, Signal, QRect)
from PySide6.QtWidgets import QGraphicsOpacityEffect from PySide6.QtWidgets import QGraphicsOpacityEffect, QPushButton
from PySide6.QtGui import QColor
class MultiStageAnimations(QObject): class MultiStageAnimations(QObject):
animation_finished = Signal() animation_finished = Signal()
def __init__(self, ui, parent=None): def __init__(self, ui, parent=None):
super().__init__(parent) super().__init__(parent)
self.ui = ui self.ui = ui
# 获取画布尺寸 self.parent = parent # 保存父窗口引用以获取当前尺寸
self.canvas_width = ui.centralwidget.width()
self.canvas_height = ui.centralwidget.height() # 获取画布尺寸 - 动态从父窗口获取
if parent:
self.canvas_width = parent.width()
self.canvas_height = parent.height()
else:
# 默认尺寸
self.canvas_width = 1280
self.canvas_height = 720
# 动画时序配置 # 动画时序配置
self.animation_config = { self.animation_config = {
@@ -18,29 +27,132 @@ class MultiStageAnimations(QObject):
}, },
"mainbg": { "mainbg": {
"delay_after": 500 "delay_after": 500
},
"button_click": {
"scale_duration": 100,
"scale_min": 0.95,
"scale_max": 1.0
} }
} }
# 第一阶段Logo动画配置 # 第一阶段Logo动画配置根据新布局调整Y坐标
self.logo_widgets = [ self.logo_widgets = [
{"widget": ui.vol1bg, "delay": 0, "duration": 500, "end_pos": QPoint(0, 120)}, {"widget": ui.vol1bg, "delay": 0, "duration": 500, "end_pos": QPoint(0, 150)},
{"widget": ui.vol2bg, "delay": 80, "duration": 500, "end_pos": QPoint(0, 180)}, {"widget": ui.vol2bg, "delay": 80, "duration": 500, "end_pos": QPoint(0, 210)},
{"widget": ui.vol3bg, "delay": 160, "duration": 500, "end_pos": QPoint(0, 240)}, {"widget": ui.vol3bg, "delay": 160, "duration": 500, "end_pos": QPoint(0, 270)},
{"widget": ui.vol4bg, "delay": 240, "duration": 500, "end_pos": QPoint(0, 300)}, {"widget": ui.vol4bg, "delay": 240, "duration": 500, "end_pos": QPoint(0, 330)},
{"widget": ui.afterbg, "delay": 320, "duration": 500, "end_pos": QPoint(0, 360)} {"widget": ui.afterbg, "delay": 320, "duration": 500, "end_pos": QPoint(0, 390)}
] ]
# 第二阶段:菜单元素 # 第二阶段:菜单元素,位置会在开始动画时动态计算
self.menu_widgets = [ self.menu_widgets = [
{"widget": ui.menubg, "end_pos": QPoint(710, 0), "duration": 600}, # 移除菜单背景动画
{"widget": ui.button_container, "end_pos": QPoint(780, 250), "duration": 600}, # {"widget": ui.menubg, "end_pos": QPoint(720, 55), "duration": 600},
{"widget": ui.exit_container, "end_pos": QPoint(780, 340), "duration": 600} {"widget": ui.button_container, "end_pos": None, "duration": 600},
{"widget": ui.exit_container, "end_pos": None, "duration": 600}
] ]
self.animations = [] self.animations = []
self.timers = [] self.timers = []
# 设置按钮点击动画
self.setup_button_click_animations()
def setup_button_click_animations(self):
"""设置按钮点击动画"""
# 为开始安装按钮添加点击动画
self.ui.start_install_btn.pressed.connect(
lambda: self.start_button_click_animation(self.ui.button_container)
)
self.ui.start_install_btn.released.connect(
lambda: self.end_button_click_animation(self.ui.button_container)
)
# 为退出按钮添加点击动画
self.ui.exit_btn.pressed.connect(
lambda: self.start_button_click_animation(self.ui.exit_container)
)
self.ui.exit_btn.released.connect(
lambda: self.end_button_click_animation(self.ui.exit_container)
)
def start_button_click_animation(self, button_container):
"""开始按钮点击动画"""
# 创建缩放动画
scale_anim = QPropertyAnimation(button_container.children()[0], b"geometry") # 只对按钮背景应用动画
scale_anim.setDuration(self.animation_config["button_click"]["scale_duration"])
# 获取当前几何形状
current_geometry = button_container.children()[0].geometry()
# 计算缩放后的几何形状(保持中心点不变)
scale_factor = self.animation_config["button_click"]["scale_min"]
width_diff = current_geometry.width() * (1 - scale_factor) / 2
height_diff = current_geometry.height() * (1 - scale_factor) / 2
new_geometry = QRect(
current_geometry.x() + width_diff,
current_geometry.y() + height_diff,
current_geometry.width() * scale_factor,
current_geometry.height() * scale_factor
)
scale_anim.setEndValue(new_geometry)
scale_anim.setEasingCurve(QEasingCurve.Type.OutQuad)
# 启动动画
scale_anim.start()
self.animations.append(scale_anim)
# 对文本标签也应用同样的动画
text_anim = QPropertyAnimation(button_container.children()[1], b"geometry")
text_anim.setDuration(self.animation_config["button_click"]["scale_duration"])
text_geometry = button_container.children()[1].geometry()
new_text_geometry = QRect(
text_geometry.x() + width_diff,
text_geometry.y() + height_diff,
text_geometry.width() * scale_factor,
text_geometry.height() * scale_factor
)
text_anim.setEndValue(new_text_geometry)
text_anim.setEasingCurve(QEasingCurve.Type.OutQuad)
text_anim.start()
self.animations.append(text_anim)
def end_button_click_animation(self, button_container):
"""结束按钮点击动画,恢复正常外观"""
# 创建恢复动画 - 对背景
scale_anim = QPropertyAnimation(button_container.children()[0], b"geometry")
scale_anim.setDuration(self.animation_config["button_click"]["scale_duration"])
# 恢复到原始大小 (10,10,191,91)
original_geometry = QRect(10, 10, 191, 91)
scale_anim.setEndValue(original_geometry)
scale_anim.setEasingCurve(QEasingCurve.Type.OutElastic)
# 启动动画
scale_anim.start()
self.animations.append(scale_anim)
# 恢复文本标签
text_anim = QPropertyAnimation(button_container.children()[1], b"geometry")
text_anim.setDuration(self.animation_config["button_click"]["scale_duration"])
# 恢复文本到原始大小 (10,7,191,91)
text_anim.setEndValue(QRect(10, 7, 191, 91))
text_anim.setEasingCurve(QEasingCurve.Type.OutElastic)
text_anim.start()
self.animations.append(text_anim)
def initialize(self): def initialize(self):
"""初始化所有组件状态""" """初始化所有组件状态"""
# 更新画布尺寸
if self.parent:
self.canvas_width = self.parent.width()
self.canvas_height = self.parent.height()
# 设置Mainbg初始状态 # 设置Mainbg初始状态
effect = QGraphicsOpacityEffect(self.ui.Mainbg) effect = QGraphicsOpacityEffect(self.ui.Mainbg)
effect.setOpacity(0) effect.setOpacity(0)
@@ -125,6 +237,9 @@ class MultiStageAnimations(QObject):
self.animations.append(main_anim) self.animations.append(main_anim)
def start_menu_animations(self): def start_menu_animations(self):
"""启动菜单动画(从下往上)""" """启动菜单动画(从下往上)"""
# 更新按钮最终位置
self._update_button_positions()
for item in self.menu_widgets: for item in self.menu_widgets:
anim_group = QParallelAnimationGroup() anim_group = QParallelAnimationGroup()
@@ -149,6 +264,46 @@ class MultiStageAnimations(QObject):
anim_group.start() anim_group.start()
self.animations.append(anim_group) self.animations.append(anim_group)
def _update_button_positions(self):
"""更新按钮最终位置"""
# 根据当前窗口大小动态计算按钮位置
if self.parent:
width = self.parent.width()
height = self.parent.height()
# 计算按钮位置
right_margin = 20 # 减小右边距,使按钮更靠右
# 开始安装按钮
if hasattr(self.ui, 'button_container'):
btn_width = self.ui.button_container.width()
x_pos = width - btn_width - right_margin
y_pos = int((height - 55) * 0.42) - 10 # 调整Y位置以适应扩大的容器
# 更新动画目标位置
for item in self.menu_widgets:
if item["widget"] == self.ui.button_container:
item["end_pos"] = QPoint(x_pos, y_pos)
# 退出按钮
if hasattr(self.ui, 'exit_container'):
btn_width = self.ui.exit_container.width()
x_pos = width - btn_width - right_margin
y_pos = int((height - 55) * 0.62) - 10 # 调整Y位置以适应扩大的容器
# 更新动画目标位置
for item in self.menu_widgets:
if item["widget"] == self.ui.exit_container:
item["end_pos"] = QPoint(x_pos, y_pos)
else:
# 默认位置
for item in self.menu_widgets:
if item["widget"] == self.ui.button_container:
item["end_pos"] = QPoint(1050, 285)
elif item["widget"] == self.ui.exit_container:
item["end_pos"] = QPoint(1050, 415)
def start_animations(self): def start_animations(self):
"""启动完整动画序列""" """启动完整动画序列"""
self.clear_animations() self.clear_animations()

View File

@@ -140,7 +140,7 @@ class DownloadManager:
def download_action(self): def download_action(self):
"""开始下载流程""" """开始下载流程"""
# 禁用开始安装按钮 # 禁用开始安装按钮
self.main_window.ui.start_install_btn.setEnabled(False) self.main_window.set_start_button_enabled(False)
# 清空下载历史记录 # 清空下载历史记录
self.main_window.download_queue_history = [] self.main_window.download_queue_history = []
@@ -173,7 +173,7 @@ class DownloadManager:
self.main_window, f"错误 - {APP_NAME}", "\n网络状态异常或服务器故障,请重试\n" self.main_window, f"错误 - {APP_NAME}", "\n网络状态异常或服务器故障,请重试\n"
) )
# 重新启用开始安装按钮 # 重新启用开始安装按钮
self.main_window.ui.start_install_btn.setEnabled(True) self.main_window.set_start_button_enabled(True)
return return
# 填充下载队列 # 填充下载队列
@@ -565,6 +565,6 @@ class DownloadManager:
# 重新启用退出按钮和开始安装按钮 # 重新启用退出按钮和开始安装按钮
self.main_window.ui.exit_btn.setEnabled(True) self.main_window.ui.exit_btn.setEnabled(True)
self.main_window.ui.start_install_btn.setEnabled(True) self.main_window.set_start_button_enabled(True)
self.main_window.show_result() self.main_window.show_result()

View File

@@ -5,8 +5,9 @@ import json
import webbrowser import webbrowser
from PySide6 import QtWidgets from PySide6 import QtWidgets
from PySide6.QtCore import QTimer from PySide6.QtCore import QTimer, Qt, QPoint, QRect, QSize
from PySide6.QtWidgets import QMainWindow, QMessageBox from PySide6.QtWidgets import QMainWindow, QMessageBox, QGraphicsOpacityEffect, QGraphicsColorizeEffect
from PySide6.QtGui import QPalette, QColor, QPainterPath, QRegion
from ui.Ui_install import Ui_MainWindows from ui.Ui_install import Ui_MainWindows
from data.config import ( from data.config import (
@@ -28,10 +29,31 @@ class MainWindow(QMainWindow):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
# 设置窗口为无边框
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
# 设置窗口背景透明
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
# 调整窗口大小以适应背景图片比例 (1280x720)
self.resize(1280, 720)
# 移除大小限制,允许自由缩放
# self.setMinimumSize(QSize(1024, 576))
# self.setMaximumSize(QSize(1024, 576))
# 窗口比例 (16:9)
self.aspect_ratio = 16 / 9
# 拖动窗口相关变量
self._drag_position = QPoint()
self._is_dragging = False
# 初始化UI (从Ui_install.py导入) # 初始化UI (从Ui_install.py导入)
self.ui = Ui_MainWindows() self.ui = Ui_MainWindows()
self.ui.setupUi(self) self.ui.setupUi(self)
# 设置圆角窗口
self.setRoundedCorners()
# 初始化配置 # 初始化配置
self.config = load_config() self.config = load_config()
@@ -57,6 +79,12 @@ class MainWindow(QMainWindow):
self.debug_manager = DebugManager(self) self.debug_manager = DebugManager(self)
self.download_manager = DownloadManager(self) self.download_manager = DownloadManager(self)
# 设置关闭按钮事件连接
if hasattr(self.ui, 'close_btn'):
self.ui.close_btn.clicked.connect(self.close)
if hasattr(self.ui, 'minimize_btn'):
self.ui.minimize_btn.clicked.connect(self.showMinimized)
# 检查管理员权限和进程 # 检查管理员权限和进程
self.admin_privileges.request_admin_privileges() self.admin_privileges.request_admin_privileges()
@@ -78,9 +106,13 @@ class MainWindow(QMainWindow):
sys.exit(1) sys.exit(1)
# 连接信号 - 绑定到新按钮 # 连接信号 - 绑定到新按钮
self.ui.start_install_btn.clicked.connect(self.download_manager.file_dialog) self.ui.start_install_btn.clicked.connect(self.handle_install_button_click)
self.ui.exit_btn.clicked.connect(self.shutdown_app) self.ui.exit_btn.clicked.connect(self.shutdown_app)
# 初始化按钮状态标记
self.install_button_enabled = False
self.last_error_message = ""
# 根据初始配置决定是否开启Debug模式 # 根据初始配置决定是否开启Debug模式
if hasattr(self.ui_manager, 'debug_action') and self.ui_manager.debug_action: if hasattr(self.ui_manager, 'debug_action') and self.ui_manager.debug_action:
if self.ui_manager.debug_action.isChecked(): if self.ui_manager.debug_action.isChecked():
@@ -92,6 +124,94 @@ class MainWindow(QMainWindow):
# 窗口显示后延迟100ms启动动画 # 窗口显示后延迟100ms启动动画
QTimer.singleShot(100, self.start_animations) QTimer.singleShot(100, self.start_animations)
def setRoundedCorners(self):
"""设置窗口圆角"""
# 实现圆角窗口
path = QPainterPath()
path.addRoundedRect(self.rect(), 20, 20)
mask = QRegion(path.toFillPolygon().toPolygon())
self.setMask(mask)
# 更新resize事件时更新圆角
self.updateRoundedCorners = True
# 添加鼠标事件处理,实现窗口拖动
def mousePressEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
# 只有当鼠标在标题栏区域时才可以拖动
if hasattr(self.ui, 'title_bar') and self.ui.title_bar.geometry().contains(event.position().toPoint()):
self._is_dragging = True
self._drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
event.accept()
def mouseMoveEvent(self, event):
if event.buttons() & Qt.MouseButton.LeftButton and self._is_dragging:
self.move(event.globalPosition().toPoint() - self._drag_position)
event.accept()
def mouseReleaseEvent(self, event):
if event.button() == Qt.MouseButton.LeftButton:
self._is_dragging = False
event.accept()
def resizeEvent(self, event):
"""当窗口大小改变时更新圆角和维持纵横比"""
# 计算基于当前宽度的合适高度以维持16:9比例
new_width = event.size().width()
new_height = int(new_width / self.aspect_ratio)
if new_height != event.size().height():
# 阻止变形,保持比例
self.resize(new_width, new_height)
# 更新主容器大小
if hasattr(self.ui, 'main_container'):
self.ui.main_container.setGeometry(0, 0, new_width, new_height)
# 更新内容容器大小
if hasattr(self.ui, 'content_container'):
self.ui.content_container.setGeometry(0, 0, new_width, new_height)
# 更新标题栏宽度
if hasattr(self.ui, 'title_bar'):
self.ui.title_bar.setGeometry(0, 0, new_width, 30)
# 更新内容区域大小
if hasattr(self.ui, 'inner_content'):
self.ui.inner_content.setGeometry(0, 55, new_width, new_height - 55)
# 更新背景图大小
if hasattr(self.ui, 'Mainbg'):
self.ui.Mainbg.setGeometry(0, 0, new_width, new_height - 55)
if hasattr(self.ui, 'loadbg'):
self.ui.loadbg.setGeometry(0, 0, new_width, new_height - 55)
# 调整按钮位置 - 固定在右侧
right_margin = 20 # 减小右边距,使按钮更靠右
if hasattr(self.ui, 'button_container'):
btn_width = 211 # 扩大后的容器宽度
btn_height = 111 # 扩大后的容器高度
x_pos = new_width - btn_width - right_margin
y_pos = int((new_height - 55) * 0.42) - 10 # 调整Y位置以适应扩大的容器
self.ui.button_container.setGeometry(x_pos, y_pos, btn_width, btn_height)
if hasattr(self.ui, 'exit_container'):
btn_width = 211 # 扩大后的容器宽度
btn_height = 111 # 扩大后的容器高度
x_pos = new_width - btn_width - right_margin
y_pos = int((new_height - 55) * 0.62) - 10 # 调整Y位置以适应扩大的容器
self.ui.exit_container.setGeometry(x_pos, y_pos, btn_width, btn_height)
# 更新圆角
if hasattr(self, 'updateRoundedCorners') and self.updateRoundedCorners:
path = QPainterPath()
path.addRoundedRect(self.rect(), 20, 20)
mask = QRegion(path.toFillPolygon().toPolygon())
self.setMask(mask)
super().resizeEvent(event)
def start_animations(self): def start_animations(self):
"""开始启动动画""" """开始启动动画"""
# 不再禁用退出按钮的交互性,只通过样式表控制外观 # 不再禁用退出按钮的交互性,只通过样式表控制外观
@@ -100,7 +220,7 @@ class MainWindow(QMainWindow):
# 按钮容器初始是隐藏的,无需在这里禁用 # 按钮容器初始是隐藏的,无需在这里禁用
# 但确保开始安装按钮仍然处于禁用状态 # 但确保开始安装按钮仍然处于禁用状态
self.ui.start_install_btn.setEnabled(False) self.set_start_button_enabled(False)
self.animator.animation_finished.connect(self.on_animations_finished) self.animator.animation_finished.connect(self.on_animations_finished)
self.animator.start_animations() self.animator.start_animations()
@@ -112,9 +232,26 @@ class MainWindow(QMainWindow):
# 只有在配置有效时才启用开始安装按钮 # 只有在配置有效时才启用开始安装按钮
if self.config_valid: if self.config_valid:
self.ui.start_install_btn.setEnabled(True) self.set_start_button_enabled(True)
else: else:
self.ui.start_install_btn.setEnabled(False) self.set_start_button_enabled(False)
def set_start_button_enabled(self, enabled):
"""设置开始安装按钮的启用状态和视觉效果
Args:
enabled: 是否启用按钮
"""
self.ui.start_install_btn.setEnabled(True) # 始终启用按钮,以便捕获点击事件
# 根据状态修改文本内容,但不再修改颜色样式
if enabled:
self.ui.start_install_text.setText("开始安装")
else:
self.ui.start_install_text.setText("!无法安装!")
# 记录当前按钮状态,用于点击事件处理
self.install_button_enabled = enabled
def fetch_cloud_config(self): def fetch_cloud_config(self):
"""获取云端配置""" """获取云端配置"""
@@ -134,6 +271,8 @@ class MainWindow(QMainWindow):
if error_message: if error_message:
# 标记配置无效 # 标记配置无效
self.config_valid = False self.config_valid = False
# 记录错误信息,用于按钮点击时显示
self.last_error_message = error_message
if error_message == "update_required": if error_message == "update_required":
msg_box = msgbox_frame( msg_box = msgbox_frame(
@@ -175,18 +314,20 @@ class MainWindow(QMainWindow):
) )
msg_box.exec() msg_box.exec()
# 在无法连接到云端时禁用开始安装按钮 # 在无法连接到云端时禁用开始安装按钮
self.ui.start_install_btn.setEnabled(False) self.set_start_button_enabled(False)
else: else:
self.cloud_config = data self.cloud_config = data
# 标记配置有效 # 标记配置有效
self.config_valid = True self.config_valid = True
# 清除错误信息
self.last_error_message = ""
debug_mode = self.ui_manager.debug_action.isChecked() if self.ui_manager.debug_action else False debug_mode = self.ui_manager.debug_action.isChecked() if self.ui_manager.debug_action else False
if debug_mode: if debug_mode:
print("--- Cloud config fetched successfully ---") print("--- Cloud config fetched successfully ---")
print(json.dumps(data, indent=2)) print(json.dumps(data, indent=2))
# 确保按钮在成功获取配置时启用 # 确保按钮在成功获取配置时启用
self.ui.start_install_btn.setEnabled(True) self.set_start_button_enabled(True)
def toggle_debug_mode(self, checked): def toggle_debug_mode(self, checked):
"""切换调试模式 """切换调试模式
@@ -290,7 +431,7 @@ class MainWindow(QMainWindow):
# 重新启用退出按钮和开始安装按钮 # 重新启用退出按钮和开始安装按钮
self.ui.exit_btn.setEnabled(True) self.ui.exit_btn.setEnabled(True)
self.ui.start_install_btn.setEnabled(True) self.set_start_button_enabled(True)
# 添加短暂延迟确保UI更新 # 添加短暂延迟确保UI更新
QTimer.singleShot(100, self.show_result) QTimer.singleShot(100, self.show_result)
@@ -424,4 +565,29 @@ class MainWindow(QMainWindow):
else: else:
sys.exit(0) sys.exit(0)
def handle_install_button_click(self):
"""处理安装按钮点击事件
根据按钮当前状态决定是显示错误还是执行安装
"""
if not self.install_button_enabled:
# 按钮处于"无法安装"状态,显示上次错误消息
if self.last_error_message == "update_required":
msg_box = msgbox_frame(
f"更新提示 - {APP_NAME}",
"\n当前版本过低,请及时更新。\n",
QMessageBox.StandardButton.Ok,
)
msg_box.exec()
else:
# 默认显示网络错误
msg_box = msgbox_frame(
f"错误 - {APP_NAME}",
"\n访问云端配置失败,请检查网络状况或稍后再试。\n",
QMessageBox.StandardButton.Ok,
)
msg_box.exec()
else:
# 按钮处于"开始安装"状态,正常执行安装流程
self.download_manager.file_dialog()

View File

@@ -8,9 +8,9 @@ from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QCursor, QFont, QFontDatabase, QGradient, QCursor, QFont, QFontDatabase, QGradient,
QIcon, QImage, QKeySequence, QLinearGradient, QIcon, QImage, QKeySequence, QLinearGradient,
QPainter, QPalette, QPixmap, QRadialGradient, QPainter, QPalette, QPixmap, QRadialGradient,
QTransform) QTransform, QPainterPath, QRegion)
from PySide6.QtWidgets import (QApplication, QLabel, QMainWindow, QMenu, from PySide6.QtWidgets import (QApplication, QLabel, QMainWindow, QMenu,
QMenuBar, QPushButton, QSizePolicy, QWidget) QMenuBar, QPushButton, QSizePolicy, QWidget, QHBoxLayout)
import os import os
def load_base64_image(base64_str): def load_base64_image(base64_str):
@@ -28,13 +28,15 @@ class Ui_MainWindows(object):
if not MainWindows.objectName(): if not MainWindows.objectName():
MainWindows.setObjectName(u"MainWindows") MainWindows.setObjectName(u"MainWindows")
MainWindows.setEnabled(True) MainWindows.setEnabled(True)
MainWindows.resize(1024, 576) # 调整窗口默认大小为1280x720以匹配背景图片
MainWindows.setMinimumSize(QSize(1024, 576)) MainWindows.resize(1280, 720)
MainWindows.setMaximumSize(QSize(1024, 576)) # 移除最大和最小尺寸限制,允许自由缩放
# MainWindows.setMinimumSize(QSize(1024, 576))
# MainWindows.setMaximumSize(QSize(1024, 576))
MainWindows.setMouseTracking(False) MainWindows.setMouseTracking(False)
MainWindows.setTabletTracking(False) MainWindows.setTabletTracking(False)
MainWindows.setAcceptDrops(True) MainWindows.setAcceptDrops(True)
MainWindows.setAutoFillBackground(True) MainWindows.setAutoFillBackground(False)
MainWindows.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly) MainWindows.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
MainWindows.setAnimated(True) MainWindows.setAnimated(True)
MainWindows.setDocumentMode(False) MainWindows.setDocumentMode(False)
@@ -48,41 +50,274 @@ class Ui_MainWindows(object):
self.centralwidget = QWidget(MainWindows) self.centralwidget = QWidget(MainWindows)
self.centralwidget.setObjectName(u"centralwidget") self.centralwidget.setObjectName(u"centralwidget")
self.centralwidget.setAutoFillBackground(True) self.centralwidget.setAutoFillBackground(False) # 修改为False以支持透明背景
self.loadbg = QLabel(self.centralwidget) self.centralwidget.setStyleSheet("""
QWidget#centralwidget {
background-color: transparent;
}
""")
# 圆角背景容器
self.main_container = QWidget(self.centralwidget)
self.main_container.setObjectName(u"main_container")
self.main_container.setGeometry(QRect(0, 0, 1280, 720))
self.main_container.setStyleSheet("""
QWidget#main_container {
background-color: #C5DDFC;
border-radius: 20px;
border: 1px solid #A4C2F4;
}
""")
# 内容容器 - 用于限制内容在圆角范围内
self.content_container = QWidget(self.main_container)
self.content_container.setObjectName(u"content_container")
self.content_container.setGeometry(QRect(0, 0, 1280, 720))
self.content_container.setStyleSheet("""
QWidget#content_container {
background-color: transparent;
border-radius: 20px;
}
""")
# 添加圆角裁剪,确保内容在圆角范围内
rect = QRect(0, 0, 1280, 720)
path = QPainterPath()
path.addRoundedRect(rect, 20, 20)
region = QRegion(path.toFillPolygon().toPolygon())
self.content_container.setMask(region)
# 禁用裁剪,这可能导致窗口变形
# rect = self.content_container.rect()
# path = QPainterPath()
# path.addRoundedRect(rect, 20, 20)
# self.content_container.setMask(QRegion(path.toFillPolygon().toPolygon()))
# 标题栏
self.title_bar = QWidget(self.content_container)
self.title_bar.setObjectName(u"title_bar")
self.title_bar.setGeometry(QRect(0, 0, 1280, 30))
self.title_bar.setStyleSheet("""
QWidget#title_bar {
background-color: #A4C2F4;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
border-bottom: 1px solid #8AB4F8;
}
""")
# 标题栏布局
self.title_layout = QHBoxLayout(self.title_bar)
self.title_layout.setSpacing(10)
self.title_layout.setContentsMargins(10, 0, 10, 0)
# 添加最小化和关闭按钮到标题栏
self.minimize_btn = QPushButton(self.title_bar)
self.minimize_btn.setObjectName(u"minimize_btn")
self.minimize_btn.setMinimumSize(QSize(24, 24))
self.minimize_btn.setMaximumSize(QSize(24, 24))
self.minimize_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.minimize_btn.setStyleSheet("""
QPushButton {
background-color: #FFC107;
border-radius: 12px;
border: none;
}
QPushButton:hover {
background-color: #FFD54F;
}
QPushButton:pressed {
background-color: #FFA000;
}
""")
self.minimize_btn.setText("")
self.minimize_btn.setFont(QFont(font_family, 10))
self.close_btn = QPushButton(self.title_bar)
self.close_btn.setObjectName(u"close_btn")
self.close_btn.setMinimumSize(QSize(24, 24))
self.close_btn.setMaximumSize(QSize(24, 24))
self.close_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.close_btn.setStyleSheet("""
QPushButton {
background-color: #F44336;
border-radius: 12px;
border: none;
color: white;
font-weight: bold;
}
QPushButton:hover {
background-color: #EF5350;
}
QPushButton:pressed {
background-color: #D32F2F;
}
""")
self.close_btn.setText("×")
self.close_btn.setFont(QFont(font_family, 14))
# 标题文本
self.title_label = QLabel(self.title_bar)
self.title_label.setObjectName(u"title_label")
self.title_label.setText("FraiseMoe Addons Manager")
title_font = QFont(font_family, 12)
title_font.setBold(True)
self.title_label.setFont(title_font)
self.title_label.setStyleSheet("color: #333333; padding-left: 10px;")
self.title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
# 添加按钮到标题栏布局
self.title_layout.addWidget(self.title_label)
self.title_layout.addStretch(1)
self.title_layout.addWidget(self.minimize_btn)
self.title_layout.addSpacing(5)
self.title_layout.addWidget(self.close_btn)
# 菜单区域
self.menu_area = QWidget(self.content_container)
self.menu_area.setObjectName(u"menu_area")
self.menu_area.setGeometry(QRect(0, 30, 1024, 25))
self.menu_area.setStyleSheet("""
QWidget#menu_area {
background-color: #D4E4FC;
border-bottom: 1px solid #A4C2F4;
}
""")
# 创建菜单栏在菜单区域中
self.menubar = QMenuBar(self.menu_area)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(10, 2, 200, 20))
self.menubar.setStyleSheet("""
QMenuBar {
background-color: transparent;
color: #333333;
font-weight: bold;
spacing: 5px;
}
QMenuBar::item {
background-color: transparent;
padding: 1px 8px;
border-radius: 4px;
}
QMenuBar::item:selected {
background-color: rgba(0, 0, 0, 0.1);
}
QMenuBar::item:pressed {
background-color: rgba(0, 0, 0, 0.15);
}
QMenu {
background-color: #D4E4FC;
border: 1px solid #A4C2F4;
border-radius: 6px;
padding: 5px;
margin: 2px;
}
QMenu::item {
padding: 6px 25px 6px 20px;
color: #333333;
border-radius: 4px;
}
QMenu::item:selected {
background-color: rgba(0, 0, 0, 0.1);
}
""")
# 内容子容器
self.inner_content = QWidget(self.content_container)
self.inner_content.setObjectName(u"inner_content")
# 确保宽度足够大,保证右侧元素完全显示
self.inner_content.setGeometry(QRect(0, 55, 1280, 665))
self.inner_content.setStyleSheet("""
QWidget#inner_content {
background-color: transparent;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
}
""")
# 添加底部圆角裁剪
inner_rect = QRect(0, 0, 1280, 665)
inner_path = QPainterPath()
inner_path.addRoundedRect(inner_rect, 20, 20)
inner_region = QRegion(inner_path.toFillPolygon().toPolygon())
self.inner_content.setMask(inner_region)
# 确保底部的圆角正确显示
# 在菜单背景区域下方添加一个底部圆角装饰器
# self.bottom_corner_left = QWidget(self.main_container)
# self.bottom_corner_left.setObjectName(u"bottom_corner_left")
# self.bottom_corner_left.setGeometry(QRect(0, 556, 20, 20))
# self.bottom_corner_left.setStyleSheet("""
# QWidget#bottom_corner_left {
# background-color: #C5DDFC;
# border-bottom-left-radius: 20px;
# }
# """)
# self.bottom_corner_right = QWidget(self.main_container)
# self.bottom_corner_right.setObjectName(u"bottom_corner_right")
# self.bottom_corner_right.setGeometry(QRect(1004, 556, 20, 20))
# self.bottom_corner_right.setStyleSheet("""
# QWidget#bottom_corner_right {
# background-color: #C5DDFC;
# border-bottom-right-radius: 20px;
# }
# """)
self.menu = QMenu(self.menubar)
self.menu.setObjectName(u"menu")
self.menu_2 = QMenu(self.menubar)
self.menu_2.setObjectName(u"menu_2")
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.menu.addSeparator()
# 在主容器中添加背景和内容元素
# 修改loadbg使用title_bg1.png作为整个背景
# 原来的loadbg保持不变
self.loadbg = QLabel(self.inner_content)
self.loadbg.setObjectName(u"loadbg") self.loadbg.setObjectName(u"loadbg")
self.loadbg.setGeometry(QRect(0, 0, 1031, 561)) self.loadbg.setGeometry(QRect(0, 0, 1280, 665)) # 调整尺寸
self.loadbg.setPixmap(load_base64_image(img_data["loadbg"])) self.loadbg.setPixmap(load_base64_image(img_data["loadbg"]))
self.loadbg.setScaledContents(True) self.loadbg.setScaledContents(True)
self.vol1bg = QLabel(self.centralwidget)
self.vol1bg = QLabel(self.inner_content)
self.vol1bg.setObjectName(u"vol1bg") self.vol1bg.setObjectName(u"vol1bg")
self.vol1bg.setGeometry(QRect(0, 120, 93, 64)) self.vol1bg.setGeometry(QRect(0, 150, 93, 64))
self.vol1bg.setPixmap(load_base64_image(img_data["vol1"])) self.vol1bg.setPixmap(load_base64_image(img_data["vol1"]))
self.vol1bg.setScaledContents(True) self.vol1bg.setScaledContents(True)
self.vol2bg = QLabel(self.centralwidget)
self.vol2bg = QLabel(self.inner_content)
self.vol2bg.setObjectName(u"vol2bg") self.vol2bg.setObjectName(u"vol2bg")
self.vol2bg.setGeometry(QRect(0, 180, 93, 64)) self.vol2bg.setGeometry(QRect(0, 210, 93, 64))
self.vol2bg.setPixmap(load_base64_image(img_data["vol2"])) self.vol2bg.setPixmap(load_base64_image(img_data["vol2"]))
self.vol2bg.setScaledContents(True) self.vol2bg.setScaledContents(True)
self.vol3bg = QLabel(self.centralwidget)
self.vol3bg = QLabel(self.inner_content)
self.vol3bg.setObjectName(u"vol3bg") self.vol3bg.setObjectName(u"vol3bg")
self.vol3bg.setGeometry(QRect(0, 240, 93, 64)) self.vol3bg.setGeometry(QRect(0, 270, 93, 64))
self.vol3bg.setPixmap(load_base64_image(img_data["vol3"])) self.vol3bg.setPixmap(load_base64_image(img_data["vol3"]))
self.vol3bg.setScaledContents(True) self.vol3bg.setScaledContents(True)
self.vol4bg = QLabel(self.centralwidget)
self.vol4bg = QLabel(self.inner_content)
self.vol4bg.setObjectName(u"vol4bg") self.vol4bg.setObjectName(u"vol4bg")
self.vol4bg.setGeometry(QRect(0, 300, 93, 64)) self.vol4bg.setGeometry(QRect(0, 330, 93, 64))
self.vol4bg.setPixmap(load_base64_image(img_data["vol4"])) self.vol4bg.setPixmap(load_base64_image(img_data["vol4"]))
self.vol4bg.setScaledContents(True) self.vol4bg.setScaledContents(True)
self.afterbg = QLabel(self.centralwidget)
self.afterbg = QLabel(self.inner_content)
self.afterbg.setObjectName(u"afterbg") self.afterbg.setObjectName(u"afterbg")
self.afterbg.setGeometry(QRect(0, 360, 93, 64)) self.afterbg.setGeometry(QRect(0, 390, 93, 64))
self.afterbg.setPixmap(load_base64_image(img_data["after"])) self.afterbg.setPixmap(load_base64_image(img_data["after"]))
self.afterbg.setScaledContents(True) self.afterbg.setScaledContents(True)
self.Mainbg = QLabel(self.centralwidget)
# 修复Mainbg位置并使用title_bg1.png作为背景图片
self.Mainbg = QLabel(self.inner_content)
self.Mainbg.setObjectName(u"Mainbg") self.Mainbg.setObjectName(u"Mainbg")
self.Mainbg.setGeometry(QRect(0, 0, 1031, 561)) self.Mainbg.setGeometry(QRect(0, 0, 1280, 665)) # 调整尺寸
self.Mainbg.setPixmap(load_base64_image(img_data["Mainbg"])) self.Mainbg.setPixmap(load_image_from_file(os.path.join(os.path.dirname(os.path.dirname(__file__)), "IMG", "BG", "title_bg1.png")))
self.Mainbg.setScaledContents(True) self.Mainbg.setScaledContents(True)
# 使用新的按钮图片 # 使用新的按钮图片
@@ -90,29 +325,30 @@ class Ui_MainWindows(object):
# 创建文本标签布局的按钮 # 创建文本标签布局的按钮
# 开始安装按钮 - 基于背景图片和标签组合 # 开始安装按钮 - 基于背景图片和标签组合
self.button_container = QWidget(self.centralwidget) self.button_container = QWidget(self.inner_content)
self.button_container.setObjectName(u"start_install_container") self.button_container.setObjectName(u"start_install_container")
self.button_container.setGeometry(QRect(780, 250, 191, 91)) self.button_container.setGeometry(QRect(1050, 285, 211, 111)) # 扩大容器尺寸,预留动画空间
# 不要隐藏容器,让动画系统来控制它的可见性和位置 # 不要隐藏容器,让动画系统来控制它的可见性和位置
# 使用原来的按钮背景图片
self.start_install_bg = QLabel(self.button_container) self.start_install_bg = QLabel(self.button_container)
self.start_install_bg.setObjectName(u"start_install_bg") self.start_install_bg.setObjectName(u"start_install_bg")
self.start_install_bg.setGeometry(QRect(0, 0, 191, 91)) self.start_install_bg.setGeometry(QRect(10, 10, 191, 91)) # 居中放置在扩大的容器中
self.start_install_bg.setPixmap(button_pixmap) self.start_install_bg.setPixmap(button_pixmap)
self.start_install_bg.setScaledContents(True) self.start_install_bg.setScaledContents(True)
self.start_install_text = QLabel(self.button_container) self.start_install_text = QLabel(self.button_container)
self.start_install_text.setObjectName(u"start_install_text") self.start_install_text.setObjectName(u"start_install_text")
self.start_install_text.setGeometry(QRect(0, -3, 191, 91)) self.start_install_text.setGeometry(QRect(10, 7, 191, 91)) # 居中放置在扩大的容器中
self.start_install_text.setText("开始安装") self.start_install_text.setText("开始安装")
self.start_install_text.setFont(self.custom_font) self.start_install_text.setFont(self.custom_font)
self.start_install_text.setAlignment(Qt.AlignmentFlag.AlignCenter) self.start_install_text.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.start_install_text.setStyleSheet("color: black; letter-spacing: 1px;") self.start_install_text.setStyleSheet("letter-spacing: 1px;")
# 点击区域透明按钮 # 点击区域透明按钮
self.start_install_btn = QPushButton(self.button_container) self.start_install_btn = QPushButton(self.button_container)
self.start_install_btn.setObjectName(u"start_install_btn") self.start_install_btn.setObjectName(u"start_install_btn")
self.start_install_btn.setGeometry(QRect(0, 0, 191, 91)) self.start_install_btn.setGeometry(QRect(10, 10, 191, 91)) # 居中放置在扩大的容器中
self.start_install_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) # 设置鼠标悬停时为手形光标 self.start_install_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) # 设置鼠标悬停时为手形光标
self.start_install_btn.setFlat(True) self.start_install_btn.setFlat(True)
self.start_install_btn.raise_() # 确保按钮在最上层 self.start_install_btn.raise_() # 确保按钮在最上层
@@ -124,29 +360,30 @@ class Ui_MainWindows(object):
""") """)
# 退出按钮 - 基于背景图片和标签组合 # 退出按钮 - 基于背景图片和标签组合
self.exit_container = QWidget(self.centralwidget) self.exit_container = QWidget(self.inner_content)
self.exit_container.setObjectName(u"exit_container") self.exit_container.setObjectName(u"exit_container")
self.exit_container.setGeometry(QRect(780, 340, 191, 91)) self.exit_container.setGeometry(QRect(1050, 415, 211, 111)) # 扩大容器尺寸,预留动画空间
# 不要隐藏容器,让动画系统来控制它的可见性和位置 # 不要隐藏容器,让动画系统来控制它的可见性和位置
# 使用原来的按钮背景图片
self.exit_bg = QLabel(self.exit_container) self.exit_bg = QLabel(self.exit_container)
self.exit_bg.setObjectName(u"exit_bg") self.exit_bg.setObjectName(u"exit_bg")
self.exit_bg.setGeometry(QRect(0, 0, 191, 91)) self.exit_bg.setGeometry(QRect(10, 10, 191, 91)) # 居中放置在扩大的容器中
self.exit_bg.setPixmap(button_pixmap) self.exit_bg.setPixmap(button_pixmap)
self.exit_bg.setScaledContents(True) self.exit_bg.setScaledContents(True)
self.exit_text = QLabel(self.exit_container) self.exit_text = QLabel(self.exit_container)
self.exit_text.setObjectName(u"exit_text") self.exit_text.setObjectName(u"exit_text")
self.exit_text.setGeometry(QRect(0, -3, 191, 91)) self.exit_text.setGeometry(QRect(10, 7, 191, 91)) # 居中放置在扩大的容器中
self.exit_text.setText("退出") self.exit_text.setText("退出程序")
self.exit_text.setFont(self.custom_font) self.exit_text.setFont(self.custom_font)
self.exit_text.setAlignment(Qt.AlignmentFlag.AlignCenter) self.exit_text.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.exit_text.setStyleSheet("color: black; letter-spacing: 1px;") self.exit_text.setStyleSheet("letter-spacing: 1px;")
# 点击区域透明按钮 # 点击区域透明按钮
self.exit_btn = QPushButton(self.exit_container) self.exit_btn = QPushButton(self.exit_container)
self.exit_btn.setObjectName(u"exit_btn") self.exit_btn.setObjectName(u"exit_btn")
self.exit_btn.setGeometry(QRect(0, 0, 191, 91)) self.exit_btn.setGeometry(QRect(10, 10, 191, 91)) # 居中放置在扩大的容器中
self.exit_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) # 设置鼠标悬停时为手形光标 self.exit_btn.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) # 设置鼠标悬停时为手形光标
self.exit_btn.setFlat(True) self.exit_btn.setFlat(True)
self.exit_btn.raise_() # 确保按钮在最上层 self.exit_btn.raise_() # 确保按钮在最上层
@@ -157,12 +394,22 @@ class Ui_MainWindows(object):
} }
""") """)
self.menubg = QLabel(self.centralwidget) # 注释掉menubg移除右侧背景区域
self.menubg.setObjectName(u"menubg") # self.menubg = QLabel(self.inner_content)
self.menubg.setGeometry(QRect(710, 0, 321, 561)) # self.menubg.setObjectName(u"menubg")
self.menubg.setPixmap(load_base64_image(img_data["menubg"])) # # 将X坐标调整为720以使背景图片更靠右
self.menubg.setScaledContents(True) # self.menubg.setGeometry(QRect(720, 0, 321, 521))
# self.menubg.setPixmap(load_base64_image(img_data["menubg"]))
# self.menubg.setScaledContents(True)
# 恢复按钮位置
# self.exit_container = QWidget(self.inner_content)
# self.exit_container.setObjectName(u"exit_container")
# self.exit_container.setGeometry(QRect(780, 340, 191, 91)) # 恢复到原来的位置 780
MainWindows.setCentralWidget(self.centralwidget) MainWindows.setCentralWidget(self.centralwidget)
# 调整层级顺序
self.loadbg.raise_() self.loadbg.raise_()
self.vol1bg.raise_() self.vol1bg.raise_()
self.vol2bg.raise_() self.vol2bg.raise_()
@@ -170,21 +417,29 @@ class Ui_MainWindows(object):
self.vol4bg.raise_() self.vol4bg.raise_()
self.afterbg.raise_() self.afterbg.raise_()
self.Mainbg.raise_() self.Mainbg.raise_()
self.menubg.raise_() # self.menubg.raise_() # 注释掉menubg
# 不再需要底部圆角装饰器
# self.bottom_corner_left.raise_()
# self.bottom_corner_right.raise_()
self.button_container.raise_() self.button_container.raise_()
self.exit_container.raise_() self.exit_container.raise_()
self.menubar = QMenuBar(MainWindows) self.menu_area.raise_() # 确保菜单区域在背景之上
self.menubar.setObjectName(u"menubar") self.title_bar.raise_() # 确保标题栏在最上层
self.menubar.setGeometry(QRect(0, 0, 1024, 21))
self.menu = QMenu(self.menubar) # 保留原有菜单栏,调整到主容器内部
self.menu.setObjectName(u"menu") # self.menubar = QMenuBar(self.main_container)
self.menu_2 = QMenu(self.menubar) # self.menubar.setObjectName(u"menubar")
self.menu_2.setObjectName(u"menu_2") # self.menubar.setGeometry(QRect(0, 0, 1024, 21))
MainWindows.setMenuBar(self.menubar) # self.menu = QMenu(self.menubar)
# self.menu.setObjectName(u"menu")
# self.menu_2 = QMenu(self.menubar)
# self.menu_2.setObjectName(u"menu_2")
# 不再调用MainWindows.setMenuBar而是手动将菜单栏添加到主容器
# MainWindows.setMenuBar(self.menubar)
self.menubar.addAction(self.menu.menuAction()) # self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction()) # self.menubar.addAction(self.menu_2.menuAction())
self.menu.addSeparator() # self.menu.addSeparator()
self.retranslateUi(MainWindows) self.retranslateUi(MainWindows)
QMetaObject.connectSlotsByName(MainWindows) QMetaObject.connectSlotsByName(MainWindows)
@@ -202,10 +457,7 @@ class Ui_MainWindows(object):
#if QT_CONFIG(accessibility) #if QT_CONFIG(accessibility)
self.start_install_btn.setAccessibleDescription("") self.start_install_btn.setAccessibleDescription("")
#endif // QT_CONFIG(accessibility) #endif // QT_CONFIG(accessibility)
# 不再在这里设置文本因为我们已经在setupUi中设置了 # self.menubg.setText("") # 注释掉menubg
# self.start_install_btn.setText("")
# self.exit_btn.setText("")
self.menubg.setText("")
self.menu.setTitle(QCoreApplication.translate("MainWindows", u"\u8bbe\u7f6e", None)) self.menu.setTitle(QCoreApplication.translate("MainWindows", u"\u8bbe\u7f6e", None))
self.menu_2.setTitle(QCoreApplication.translate("MainWindows", u"\u5e2e\u52a9", None)) self.menu_2.setTitle(QCoreApplication.translate("MainWindows", u"\u5e2e\u52a9", None))
# retranslateUi # retranslateUi