添加加载文件夹
This commit is contained in:
parent
82358e7c4f
commit
244792ccb5
BIN
file/next.png
Normal file
BIN
file/next.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
BIN
file/pause.png
BIN
file/pause.png
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 2.3 KiB |
BIN
file/play.png
BIN
file/play.png
Binary file not shown.
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 3.8 KiB |
BIN
file/prev.png
Normal file
BIN
file/prev.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
73
file/林俊杰-裂缝中的阳光.lrc
Normal file
73
file/林俊杰-裂缝中的阳光.lrc
Normal file
@ -0,0 +1,73 @@
|
||||
[ti:裂缝中的阳光]
|
||||
[ar:林俊杰]
|
||||
[al:因你而在]
|
||||
[by:]
|
||||
[offset:0]
|
||||
[00:00.00]裂缝中的阳光 - 林俊杰 (JJ Lin)
|
||||
[00:04.25]词:吴青峰
|
||||
[00:08.51]曲:林俊杰
|
||||
[00:12.76]编曲:林俊杰
|
||||
[00:17.02]制作人:林俊杰
|
||||
[00:21.28]有多少创伤卡在咽喉
|
||||
[00:24.27]
|
||||
[00:26.76]有多少眼泪滴湿枕头
|
||||
[00:29.84]
|
||||
[00:32.38]有多少你觉得不能够
|
||||
[00:35.38]
|
||||
[00:36.66]被懂的痛 只能沉默
|
||||
[00:41.13]
|
||||
[00:43.68]有多少夜晚没有尽头
|
||||
[00:49.15]有多少的寂寞 无人诉说
|
||||
[00:54.85]有多少次的梦 还没做 已成空
|
||||
[01:06.11]等到黑夜翻面之后
|
||||
[01:08.98]会是新的白昼
|
||||
[01:11.74]等到海啸退去之后
|
||||
[01:14.62]只是潮起潮落
|
||||
[01:18.11]别到最后你才发觉
|
||||
[01:21.59]心里头的野兽
|
||||
[01:24.53]还没到最终就已经罢休
|
||||
[01:28.83]心脏没有那么脆弱
|
||||
[01:31.62]总还会有执着
|
||||
[01:33.64]
|
||||
[01:34.43]人生不会只有收获
|
||||
[01:37.21]总难免有伤口
|
||||
[01:39.91]
|
||||
[01:40.66]不要害怕生命中
|
||||
[01:43.45]
|
||||
[01:44.30]不完美的角落
|
||||
[01:46.35]
|
||||
[01:47.09]阳光在每个裂缝中散落
|
||||
[02:00.78]呜呜
|
||||
[02:09.34]Yeah
|
||||
[02:16.70]就算一切重来又怎样
|
||||
[02:21.41]
|
||||
[02:22.47]让你的心在我 心上跳动
|
||||
[02:28.02]每个逐渐暗下来的夜 一起走过
|
||||
[02:37.25]
|
||||
[02:39.36]等到黑夜翻面之后
|
||||
[02:42.24]会是新的白昼
|
||||
[02:44.17]
|
||||
[02:45.07]等到海啸退去之后
|
||||
[02:47.80]只是潮起潮落
|
||||
[02:50.21]
|
||||
[02:51.41]别到最后你才发觉
|
||||
[02:53.93]
|
||||
[02:54.87]心里头的野兽
|
||||
[02:57.00]
|
||||
[02:57.72]还没到最终就已经罢休
|
||||
[03:01.93]心脏没有那么脆弱
|
||||
[03:04.69]总还会有执着
|
||||
[03:06.81]
|
||||
[03:07.60]人生不会只有收获
|
||||
[03:10.36]总难免有伤口
|
||||
[03:12.93]
|
||||
[03:13.83]不要害怕生命中
|
||||
[03:16.57]
|
||||
[03:17.47]不完美的角落
|
||||
[03:19.55]
|
||||
[03:20.27]阳光在每个裂缝中散落
|
||||
[03:25.48]
|
||||
[03:28.17]不如就勇敢打破
|
||||
[03:30.95]
|
||||
[03:31.62]生命中的裂缝
|
||||
[03:34.46]阳光就逐渐洒满了其中
|
BIN
file/林俊杰-裂缝中的阳光.wav
Normal file
BIN
file/林俊杰-裂缝中的阳光.wav
Normal file
Binary file not shown.
119
musicplayer.py
119
musicplayer.py
@ -5,7 +5,7 @@ import time
|
||||
import re
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel,
|
||||
QPushButton, QSlider, QHBoxLayout
|
||||
QPushButton, QSlider, QHBoxLayout, QFileDialog
|
||||
)
|
||||
from PyQt6.QtCore import QTimer, Qt, QSize, QPropertyAnimation, QPoint
|
||||
from PyQt6.QtGui import QPixmap, QIcon, QPalette, QColor
|
||||
@ -18,6 +18,8 @@ class MusicPlayer(QMainWindow):
|
||||
self.initUI()
|
||||
pygame.mixer.init()
|
||||
|
||||
self.playlist = [] # 歌曲列表(文件路径)
|
||||
self.current_song_index = -1 # 当前播放歌曲索引
|
||||
self.lyrics = [] # 解析后的歌词列表 [(时间戳, 歌词)]
|
||||
self.current_lyric_index = 0 # 当前歌词索引
|
||||
self.is_playing = False # 播放状态
|
||||
@ -26,7 +28,9 @@ class MusicPlayer(QMainWindow):
|
||||
self.pause_time = 0 # 暂停时记录的播放进度(秒)
|
||||
self.animation = None # 存储滚动动画对象
|
||||
self.last_lyric = None # 上一次显示的歌词,用于避免重复启动动画
|
||||
self.load_lyrics()
|
||||
self.music_file = None # 当前音乐文件路径
|
||||
self.lyrics_file = None # 当前歌词文件路径
|
||||
self.cover_file = None # 当前封面文件路径
|
||||
|
||||
def initUI(self):
|
||||
self.central_widget = QWidget()
|
||||
@ -41,7 +45,11 @@ class MusicPlayer(QMainWindow):
|
||||
# 封面
|
||||
self.cover_label = QLabel()
|
||||
self.layout.addWidget(self.cover_label, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
self.load_cover()
|
||||
|
||||
# 添加一个按钮用于加载外部音乐文件夹
|
||||
self.load_folder_button = QPushButton("选择音乐文件夹")
|
||||
self.load_folder_button.clicked.connect(self.open_folder_dialog)
|
||||
self.layout.addWidget(self.load_folder_button, alignment=Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
# 歌词显示区域(固定大小容器,便于动画处理,不随内容改变大小)
|
||||
self.lyrics_container = QWidget()
|
||||
@ -62,15 +70,29 @@ class MusicPlayer(QMainWindow):
|
||||
self.slider.sliderReleased.connect(self.seek_music)
|
||||
self.layout.addWidget(self.slider)
|
||||
|
||||
# 播放控制区域
|
||||
# 播放控制区域(增加上一首、播放/暂停、下一首)
|
||||
self.control_layout = QHBoxLayout()
|
||||
self.control_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.prev_button = QPushButton()
|
||||
self.prev_button.setIcon(QIcon(self.resource_path("file/prev.png")))
|
||||
self.prev_button.setIconSize(QSize(40, 40))
|
||||
self.prev_button.setStyleSheet("border: none;")
|
||||
self.prev_button.clicked.connect(self.play_previous_song)
|
||||
self.control_layout.addWidget(self.prev_button)
|
||||
|
||||
self.play_button = QPushButton()
|
||||
self.play_button.setIcon(QIcon(self.resource_path("file/play.png")))
|
||||
self.play_button.setIconSize(QSize(52, 52)) # 明确设置图标尺寸
|
||||
self.play_button.setIconSize(QSize(52, 52))
|
||||
self.play_button.setStyleSheet("border: none;")
|
||||
self.play_button.clicked.connect(self.toggle_play_pause)
|
||||
self.control_layout.addWidget(self.play_button)
|
||||
|
||||
self.next_button = QPushButton()
|
||||
self.next_button.setIcon(QIcon(self.resource_path("file/next.png")))
|
||||
self.next_button.setIconSize(QSize(40, 40))
|
||||
self.next_button.setStyleSheet("border: none;")
|
||||
self.next_button.clicked.connect(self.play_next_song)
|
||||
self.control_layout.addWidget(self.next_button)
|
||||
self.layout.addLayout(self.control_layout)
|
||||
|
||||
# 定时器,每500毫秒更新一次进度和歌词
|
||||
@ -92,18 +114,28 @@ class MusicPlayer(QMainWindow):
|
||||
self.central_widget.setStyleSheet(f"background-color: {color};")
|
||||
|
||||
def load_cover(self):
|
||||
cover_path = self.resource_path("file/cover.jpg")
|
||||
if os.path.exists(cover_path):
|
||||
pixmap = QPixmap(cover_path)
|
||||
self.cover_label.setPixmap(pixmap.scaled(256, 256, Qt.AspectRatioMode.KeepAspectRatio))
|
||||
# 如果用户选择了封面文件,优先加载,否则加载默认封面
|
||||
if self.cover_file and os.path.exists(self.cover_file):
|
||||
pixmap = QPixmap(self.cover_file)
|
||||
else:
|
||||
self.cover_label.setText("封面未找到")
|
||||
cover_path = self.resource_path("file/cover.jpg")
|
||||
if os.path.exists(cover_path):
|
||||
pixmap = QPixmap(cover_path)
|
||||
else:
|
||||
self.cover_label.setText("封面未找到")
|
||||
return
|
||||
self.cover_label.setPixmap(pixmap.scaled(256, 256, Qt.AspectRatioMode.KeepAspectRatio))
|
||||
|
||||
def load_lyrics(self):
|
||||
lyrics_path = self.resource_path("file/林俊杰-光阴副本.lrc")
|
||||
if os.path.exists(lyrics_path):
|
||||
# 根据用户选择的歌词文件加载歌词,如果没有选择则使用默认歌词文件
|
||||
if self.lyrics_file and os.path.exists(self.lyrics_file):
|
||||
path = self.lyrics_file
|
||||
else:
|
||||
# 默认歌词文件(可以根据需要调整)
|
||||
path = self.resource_path("file/默认歌词.lrc")
|
||||
if os.path.exists(path):
|
||||
try:
|
||||
with open(lyrics_path, 'r', encoding='utf-8') as file:
|
||||
with open(path, 'r', encoding='utf-8') as file:
|
||||
lines = file.readlines()
|
||||
self.lyrics = []
|
||||
for line in lines:
|
||||
@ -120,6 +152,34 @@ class MusicPlayer(QMainWindow):
|
||||
else:
|
||||
self.lyrics_browser.setText("歌词文件未找到")
|
||||
|
||||
def open_folder_dialog(self):
|
||||
folder_path = QFileDialog.getExistingDirectory(self, "选择音乐文件夹", "")
|
||||
if folder_path:
|
||||
# 读取该文件夹下所有音乐文件(支持wav和mp3)
|
||||
self.playlist = []
|
||||
for file in os.listdir(folder_path):
|
||||
if file.lower().endswith(('.wav', '.mp3')):
|
||||
self.playlist.append(os.path.join(folder_path, file))
|
||||
self.playlist.sort() # 可按文件名排序
|
||||
if self.playlist:
|
||||
# 将当前索引设置为第一首
|
||||
self.current_song_index = 0
|
||||
self.load_current_song_resources()
|
||||
self.play_music()
|
||||
else:
|
||||
self.lyrics_browser.setText("文件夹中没有找到音乐文件")
|
||||
|
||||
def load_current_song_resources(self):
|
||||
# 设置当前音乐文件路径及相关资源(歌词和封面)
|
||||
self.music_file = self.playlist[self.current_song_index]
|
||||
base, _ = os.path.splitext(self.music_file)
|
||||
lyrics_candidate = base + ".lrc"
|
||||
cover_candidate = base + ".jpg"
|
||||
self.lyrics_file = lyrics_candidate if os.path.exists(lyrics_candidate) else None
|
||||
self.cover_file = cover_candidate if os.path.exists(cover_candidate) else None
|
||||
self.load_cover()
|
||||
self.load_lyrics()
|
||||
|
||||
def toggle_play_pause(self):
|
||||
if not self.is_playing:
|
||||
if self.pause_time > 0:
|
||||
@ -130,29 +190,30 @@ class MusicPlayer(QMainWindow):
|
||||
self.pause_music()
|
||||
|
||||
def play_music(self):
|
||||
music_path = self.resource_path("file/林俊杰-光阴副本.wav")
|
||||
if os.path.exists(music_path):
|
||||
if self.music_file and os.path.exists(self.music_file):
|
||||
try:
|
||||
pygame.mixer.music.load(music_path)
|
||||
pygame.mixer.music.load(self.music_file)
|
||||
pygame.mixer.music.play(start=0)
|
||||
self.music_length = pygame.mixer.Sound(music_path).get_length()
|
||||
self.music_length = pygame.mixer.Sound(self.music_file).get_length()
|
||||
self.start_time = time.time()
|
||||
self.pause_time = 0
|
||||
self.timer.start(500)
|
||||
self.play_button.setIcon(QIcon(self.resource_path("file/pause.png")))
|
||||
self.is_playing = True
|
||||
except Exception as e:
|
||||
pass
|
||||
self.lyrics_browser.setText("播放错误: " + str(e))
|
||||
else:
|
||||
self.lyrics_browser.setText("")
|
||||
|
||||
def resume_music(self):
|
||||
try:
|
||||
pygame.mixer.music.unpause() # 直接恢复播放
|
||||
pygame.mixer.music.unpause()
|
||||
self.start_time = time.time() - self.pause_time
|
||||
self.timer.start(500)
|
||||
self.play_button.setIcon(QIcon(self.resource_path("file/pause.png")))
|
||||
self.is_playing = True
|
||||
except Exception as e:
|
||||
pass
|
||||
self.lyrics_browser.setText("恢复播放错误: " + str(e))
|
||||
|
||||
def pause_music(self):
|
||||
if self.is_playing:
|
||||
@ -174,6 +235,18 @@ class MusicPlayer(QMainWindow):
|
||||
self.play_button.setIcon(QIcon(self.resource_path("file/pause.png")))
|
||||
self.is_playing = True
|
||||
|
||||
def play_next_song(self):
|
||||
if self.playlist:
|
||||
self.current_song_index = (self.current_song_index + 1) % len(self.playlist)
|
||||
self.load_current_song_resources()
|
||||
self.play_music()
|
||||
|
||||
def play_previous_song(self):
|
||||
if self.playlist:
|
||||
self.current_song_index = (self.current_song_index - 1) % len(self.playlist)
|
||||
self.load_current_song_resources()
|
||||
self.play_music()
|
||||
|
||||
def find_lyric_index(self, current_time):
|
||||
for i, (timestamp, _) in enumerate(self.lyrics):
|
||||
if current_time < timestamp:
|
||||
@ -181,12 +254,13 @@ class MusicPlayer(QMainWindow):
|
||||
return len(self.lyrics) - 1
|
||||
|
||||
def update_lyrics_display(self):
|
||||
if not self.lyrics:
|
||||
self.lyrics_browser.setText("歌词为空")
|
||||
return
|
||||
if self.current_lyric_index < len(self.lyrics):
|
||||
_, lyric = self.lyrics[self.current_lyric_index]
|
||||
# 仅当歌词发生变化时再更新(避免重复重启动画)
|
||||
if self.last_lyric != lyric:
|
||||
self.last_lyric = lyric
|
||||
# 如果歌词宽度超过容器,则滚动显示
|
||||
if self.lyrics_browser.fontMetrics().horizontalAdvance(lyric) > self.lyrics_container.width():
|
||||
self.scroll_lyrics(lyric)
|
||||
else:
|
||||
@ -207,7 +281,6 @@ class MusicPlayer(QMainWindow):
|
||||
if self.animation is not None:
|
||||
self.animation.stop()
|
||||
self.animation = QPropertyAnimation(self.lyrics_browser, b"pos")
|
||||
# 根据歌词长度调整滚动时间
|
||||
duration = 8000 + (label_width - container_width) * 20
|
||||
self.animation.setDuration(duration)
|
||||
self.animation.setStartValue(start_pos)
|
||||
|
Loading…
x
Reference in New Issue
Block a user