258 lines
8.1 KiB
Python
258 lines
8.1 KiB
Python
import math
|
|
|
|
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
|
QPushButton, QFrame, QGridLayout, QSpacerItem)
|
|
from PyQt5.QtCore import Qt, pyqtSignal
|
|
from PyQt5.QtGui import QPixmap, QIcon, QColor, QLinearGradient, QBrush, QPainter
|
|
from PyQt5.QtCore import QRectF
|
|
|
|
|
|
class GradientFrame(QFrame):
|
|
def __init__(self, start_color, end_color, angle=0, parent=None):
|
|
super().__init__(parent)
|
|
self.start_color = QColor(start_color)
|
|
self.end_color = QColor(end_color)
|
|
self.angle = angle # 0-360 degrees
|
|
|
|
def paintEvent(self, event):
|
|
painter = QPainter(self)
|
|
painter.setRenderHint(QPainter.Antialiasing)
|
|
|
|
gradient = QLinearGradient(0, 0, self.width(), self.height())
|
|
if self.angle == 0:
|
|
gradient = QLinearGradient(0, 0, self.width(), 0)
|
|
elif self.angle == 90:
|
|
gradient = QLinearGradient(0, 0, 0, self.height())
|
|
elif self.angle == 180:
|
|
gradient = QLinearGradient(self.width(), 0, 0, 0)
|
|
elif self.angle == 270:
|
|
gradient = QLinearGradient(0, self.height(), 0, 0)
|
|
else:
|
|
# Angle between 0 and 360
|
|
rad = self.angle * 3.14159 / 180.0
|
|
cx = self.width() / 2
|
|
cy = self.height() / 2
|
|
radius = max(self.width(), self.height())
|
|
start_x = cx + radius * 0.5 * math.cos(rad)
|
|
start_y = cy + radius * 0.5 * math.sin(rad)
|
|
end_x = cx - radius * 0.5 * math.cos(rad)
|
|
end_y = cy - radius * 0.5 * math.sin(rad)
|
|
gradient = QLinearGradient(start_x, start_y, end_x, end_y)
|
|
|
|
gradient.setColorAt(0, self.start_color)
|
|
gradient.setColorAt(1, self.end_color)
|
|
|
|
painter.fillRect(self.rect(), QBrush(gradient))
|
|
|
|
super().paintEvent(event)
|
|
|
|
|
|
class AppCenter(QWidget):
|
|
app_selected = pyqtSignal(str)
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.init_ui()
|
|
|
|
def init_ui(self):
|
|
self.setObjectName("appCenter")
|
|
self.setStyleSheet("""
|
|
#appCenter {
|
|
background-color: #1a202c;
|
|
}
|
|
|
|
#pageTitle {
|
|
font-size: 28px;
|
|
font-weight: bold;
|
|
color: white;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
#appCard {
|
|
border-radius: 12px;
|
|
background-color: #2d3748;
|
|
border: 1px solid #4a5568;
|
|
transition: transform 0.2s, box-shadow 0.2s;
|
|
}
|
|
|
|
#appCard:hover {
|
|
transform: translateY(-5px);
|
|
background-color: #3c4657;
|
|
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.25);
|
|
}
|
|
|
|
#appCardTitle {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
color: white;
|
|
text-align: center;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
#appCardDesc {
|
|
font-size: 14px;
|
|
color: #cbd5e0;
|
|
text-align: center;
|
|
padding: 0 10px;
|
|
}
|
|
|
|
#appCardBtn {
|
|
background-color: #4f46e5;
|
|
color: white;
|
|
border-radius: 6px;
|
|
padding: 10px 16px;
|
|
font-weight: 600;
|
|
border: none;
|
|
min-width: 120px;
|
|
}
|
|
|
|
#appCardBtn:hover {
|
|
background-color: #4338ca;
|
|
}
|
|
""")
|
|
|
|
layout = QVBoxLayout()
|
|
layout.setContentsMargins(40, 30, 40, 30)
|
|
layout.setSpacing(20)
|
|
|
|
# 标题区域
|
|
title_layout = QHBoxLayout()
|
|
|
|
title = QLabel("应用中心")
|
|
title.setObjectName("pageTitle")
|
|
|
|
title_spacer = QSpacerItem(40, 20)
|
|
|
|
title_layout.addWidget(title)
|
|
title_layout.addSpacerItem(title_spacer)
|
|
|
|
layout.addLayout(title_layout)
|
|
|
|
# 卡片容器
|
|
grid_layout = QVBoxLayout()
|
|
grid_layout.setSpacing(20)
|
|
|
|
# 应用卡片
|
|
apps = [
|
|
{
|
|
"id": "word_to_pdf",
|
|
"title": "Word转PDF",
|
|
"desc": "批量将Word文档转换为PDF格式",
|
|
"color": ("#6366F1", "#4F46E5") # 渐变开始和结束颜色
|
|
},
|
|
{
|
|
"id": "ocr",
|
|
"title": "OCR文字识别",
|
|
"desc": "从图片中提取文字内容",
|
|
"color": ("#4ADE80", "#22C55E")
|
|
},
|
|
{
|
|
"id": "image_convert",
|
|
"title": "图片格式转换",
|
|
"desc": "转换图像文件格式并优化",
|
|
"color": ("#F97316", "#EA580C")
|
|
},
|
|
{
|
|
"id": "coming_soon",
|
|
"title": "敬请期待",
|
|
"desc": "更多实用功能正在开发中",
|
|
"color": ("#8B5CF6", "#7C3AED")
|
|
}
|
|
]
|
|
|
|
# 每行显示2张卡片
|
|
for i in range(0, len(apps), 2):
|
|
row_layout = QHBoxLayout()
|
|
row_layout.setSpacing(30)
|
|
|
|
for j in range(2):
|
|
index = i + j
|
|
if index < len(apps):
|
|
row_layout.addWidget(self.create_app_card(apps[index]))
|
|
else:
|
|
# 添加空白占位符保持布局
|
|
spacer = QSpacerItem(0, 0)
|
|
row_layout.addItem(spacer)
|
|
|
|
grid_layout.addLayout(row_layout)
|
|
|
|
layout.addLayout(grid_layout)
|
|
layout.addStretch()
|
|
|
|
self.setLayout(layout)
|
|
|
|
def create_app_card(self, app):
|
|
"""创建应用卡片"""
|
|
card = GradientFrame(app["color"][0], app["color"][1], 45)
|
|
card.setObjectName("appCard")
|
|
card.setFixedSize(300, 280)
|
|
|
|
layout = QVBoxLayout(card)
|
|
layout.setContentsMargins(20, 20, 20, 20)
|
|
layout.setSpacing(15)
|
|
|
|
# 图标
|
|
icon_frame = QFrame()
|
|
icon_frame.setFixedSize(80, 80)
|
|
icon_frame.setStyleSheet("background-color: rgba(255, 255, 255, 0.2); border-radius: 40px;")
|
|
icon_frame.setObjectName("appCardIcon")
|
|
|
|
icon_layout = QVBoxLayout(icon_frame)
|
|
icon_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
# 使用QSS设置图标颜色为白色
|
|
icon = QLabel()
|
|
icon_pixmap = QPixmap(f":/icons/{app['id']}.png").scaled(48, 48,
|
|
Qt.KeepAspectRatio,
|
|
Qt.SmoothTransformation)
|
|
# 转换图标为白色
|
|
if app["id"] != "coming_soon":
|
|
painter = QPainter(icon_pixmap)
|
|
painter.setCompositionMode(QPainter.CompositionMode_SourceIn)
|
|
painter.fillRect(icon_pixmap.rect(), Qt.white)
|
|
painter.end()
|
|
|
|
icon.setPixmap(icon_pixmap)
|
|
icon.setAlignment(Qt.AlignCenter)
|
|
icon_layout.addWidget(icon)
|
|
|
|
layout.addWidget(icon_frame, 0, Qt.AlignHCenter)
|
|
|
|
# 标题
|
|
title = QLabel(app["title"])
|
|
title.setObjectName("appCardTitle")
|
|
layout.addWidget(title)
|
|
|
|
# 描述
|
|
desc = QLabel(app["desc"])
|
|
desc.setObjectName("appCardDesc")
|
|
desc.setWordWrap(True)
|
|
layout.addWidget(desc)
|
|
|
|
# 添加伸缩空间保持底部对齐
|
|
spacer = QSpacerItem(20, 20)
|
|
layout.addItem(spacer)
|
|
|
|
# 按钮
|
|
btn_text = "开始使用" if app["id"] != "coming_soon" else "敬请期待"
|
|
btn = QPushButton(btn_text)
|
|
btn.setObjectName("appCardBtn")
|
|
btn.setCursor(Qt.PointingHandCursor)
|
|
|
|
if app["id"] == "coming_soon":
|
|
btn.setEnabled(False)
|
|
btn.setStyleSheet("""
|
|
#appCardBtn:disabled {
|
|
background-color: rgba(255, 255, 255, 0.3);
|
|
color: rgba(255, 255, 255, 0.7);
|
|
}
|
|
""")
|
|
else:
|
|
btn.clicked.connect(lambda: self.app_selected.emit(app["id"]))
|
|
|
|
layout.addWidget(btn, 0, Qt.AlignHCenter)
|
|
|
|
# 为卡片添加点击事件
|
|
card.mousePressEvent = lambda e: self.app_selected.emit(app["id"]) if app["id"] != "coming_soon" else None
|
|
|
|
return card |