Files

174 lines
5.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""图形界面入口:``python -m recorder.gui``(或双击 启动录音机.bat)。
负责三件事:High-DPI 适配、深色主题样式表、以及缺依赖时的友好提示。
"""
from __future__ import annotations
import sys
QSS = """
* { font-family: "Microsoft YaHei UI", "Microsoft YaHei", "Segoe UI", sans-serif; }
QWidget { background: #0F1218; color: #E8ECF4; font-size: 12px; }
QMainWindow, QDialog { background: #0F1218; }
QMenuBar { background: #12161D; border-bottom: 1px solid #2A313D; }
QMenuBar::item { padding: 5px 12px; background: transparent; }
QMenuBar::item:selected { background: #1D222C; border-radius: 4px; }
QMenu { background: #161A22; border: 1px solid #2A313D; padding: 4px; }
QMenu::item { padding: 6px 22px; border-radius: 4px; }
QMenu::item:selected { background: #23303F; }
QGroupBox {
background: #161A22;
border: 1px solid #2A313D;
border-radius: 8px;
margin-top: 12px;
padding-top: 8px;
font-weight: 600;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 12px;
padding: 0 6px;
color: #9FB0CB;
}
QFrame#card {
background: #161A22;
border: 1px solid #2A313D;
border-radius: 10px;
}
QLabel { background: transparent; }
QPushButton {
background: #232A36;
border: 1px solid #323A48;
border-radius: 6px;
padding: 6px 12px;
color: #E8ECF4;
}
QPushButton:hover { background: #2A3341; border-color: #3E4A5C; }
QPushButton:pressed { background: #1B2129; }
QPushButton:disabled { color: #5C6577; background: #1A1F27; border-color: #262D38; }
QComboBox, QLineEdit, QSpinBox, QDoubleSpinBox, QPlainTextEdit {
background: #1B2029;
border: 1px solid #2E3644;
border-radius: 6px;
padding: 5px 8px;
selection-background-color: #2C5F9E;
}
QComboBox:hover, QLineEdit:hover, QSpinBox:hover, QDoubleSpinBox:hover {
border-color: #3E4A5C;
}
QComboBox::drop-down { border: none; width: 18px; }
QComboBox QAbstractItemView {
background: #1B2029;
border: 1px solid #2E3644;
selection-background-color: #23303F;
outline: none;
}
QComboBox::down-arrow {
image: none;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 5px solid #8B94A7;
margin-right: 6px;
}
QCheckBox { spacing: 7px; }
QCheckBox::indicator {
width: 15px; height: 15px;
border: 1px solid #3A4352; border-radius: 4px;
background: #1B2029;
}
QCheckBox::indicator:checked {
background: #4EA1FF; border-color: #4EA1FF;
}
QSlider::groove:horizontal {
height: 4px; background: #2A313D; border-radius: 2px;
}
QSlider::sub-page:horizontal { background: #4EA1FF; border-radius: 2px; }
QSlider::handle:horizontal {
background: #E8ECF4; width: 14px; margin: -6px 0; border-radius: 7px;
}
QScrollArea { background: transparent; border: none; }
QScrollBar:vertical { background: #12161D; width: 10px; border-radius: 5px; }
QScrollBar::handle:vertical { background: #333B49; border-radius: 5px; min-height: 30px; }
QScrollBar::handle:vertical:hover { background: #414B5C; }
QScrollBar::add-line, QScrollBar::sub-line { height: 0; }
QStatusBar { background: #12161D; border-top: 1px solid #2A313D; color: #8B94A7; }
QStatusBar QLabel { color: #8B94A7; }
QSplitter::handle { background: transparent; width: 6px; }
QProgressBar {
background: #1B2029; border: 1px solid #2E3644; border-radius: 6px;
text-align: center; color: #E8ECF4; height: 16px;
}
QProgressBar::chunk { background: #4EA1FF; border-radius: 5px; }
QToolTip {
background: #1B2029; color: #E8ECF4; border: 1px solid #3E4A5C;
padding: 4px 6px; border-radius: 4px;
}
QTabBar::tab {
background: #1B2029; padding: 6px 14px; border: 1px solid #2E3644;
border-bottom: none; border-top-left-radius: 6px; border-top-right-radius: 6px;
}
QTabBar::tab:selected { background: #232A36; }
"""
def _check_dependencies() -> str | None:
"""返回缺失依赖的说明,全部就绪时返回 None。"""
missing = []
try:
import numpy # noqa: F401 (仅用于探测依赖是否就绪)
except Exception:
missing.append("numpy(数值运算)")
try:
import PyQt5 # noqa: F401 (仅用于探测依赖是否就绪)
except Exception:
missing.append("PyQt5(图形界面)")
from . import engine
if engine.sd is None:
missing.append("sounddevice(PortAudio 音频后端)")
if not missing:
return None
return ("缺少以下依赖,无法启动图形界面:\n\n · " + "\n · ".join(missing)
+ "\n\n请运行:python install_deps.py\n"
"(在项目目录下执行,会把依赖装到项目内的 _vendor 目录)")
def run(argv: list[str] | None = None) -> int:
argv = list(sys.argv if argv is None else argv)
problem = _check_dependencies()
if problem:
print(problem, file=sys.stderr)
try:
from PyQt5.QtWidgets import QApplication as _QA, QMessageBox
except Exception:
return 2
_app = _QA(argv)
QMessageBox.critical(None, "缺少依赖", problem)
return 2
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication
# High-DPI 相关属性必须在 QApplication 实例化之前设置
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
from .window import MainWindow
app = QApplication(argv)
app.setApplicationName("RecorderStudio")
app.setOrganizationName("RecorderStudio")
app.setStyleSheet(QSS)
app.setFont(QFont("Microsoft YaHei UI", 9))
win = MainWindow()
win.show()
return app.exec_()
if __name__ == "__main__":
sys.exit(run())