import time from tkinter import * import threading import pygame import requests from ttkbootstrap import * import tkinter.messagebox import tkinter.filedialog import sys import re import os import json import subprocess from random import randint from random import choice as c import math import webbrowser from pyperclip import copy # 子代码 from nflmusic import language as lang, make_image, theme_language as tmla, logs, ifm_json as ij from nflmusic.label_button import LabelButton as lb from nflmusic import lyrics from nflmusic.player import MusicPlayer from nflmusic.load_gif import * def opening_animation(): global loaded, appdata while True: try: root0 = Frame(root, height=530, width=810) break except: pass time.sleep(0.05) root.attributes("-topmost", True) root.overrideredirect(True) root0.place(x=0, y=0) label_image = Label(root0, image=imagetk8) label_image.place(relx=0.5, rely=0.5, anchor="center") time.sleep(2) root0.destroy() root.attributes("-topmost", False) root.overrideredirect(False) homepage_frame.place(x=0, y=0) root.config(menu=menubar) loaded = True run(update) def make_jsondata(): appdata = os.getenv("APPDATA") with open(appdata + "/.NFLmusic/NFLmusic.json", "w") as f: jsondata = ij.usercache f.write(json.dumps(jsondata)) def make_lang_json(): if not os.path.exists(appdata + "/.NFLmusic/language"): os.mkdir(appdata + "/.NFLmusic/language") with open(appdata + "/.NFLmusic/language/zh_cn.json", "w") as f: f.write(json.dumps(ij.Language.zh_cn)) with open(appdata + "/.NFLmusic/language/en_us.json", "w") as f: f.write(json.dumps(ij.Language.en_us)) def save_jsondata(): jsondata["language"] = var5.get() jsondata["choice"] = repo_dict[var4.get()] jsondata["auto_update"] = var3.get() jsondata["auto_play"] = var6.get() tm = var1.get() style.theme = tmla.get(la)[tm] jsondata["theme"] = tmla.get(la)[tm] if not os.path.exists(var2.get()): var2.set(path) jsondata["path"] = var2.get() with open(appdata + "/.NFLmusic/NFLmusic.json", "w") as f: f.write(json.dumps(jsondata)) def detect_change(): global changed if ( jsondata["language"] != var5.get() or jsondata["choice"] != repo_dict[var4.get()] or jsondata["auto_update"] != var3.get() or jsondata["auto_play"] != var6.get() or jsondata["theme"] != tmla.get(la)[var1.get()] or jsondata["path"] != var2.get() ): changed = True def display(window, msg, ltime=3): a = Label(window, text=msg) a.place(relx=0.5, rely=0.9, anchor="center") time.sleep(ltime) a.destroy() def get_treeview_index(tree, item): parent_id = tree.parent(item) if parent_id: # 如果有父节点,获取父节点下所有子节点,并返回目标节点在其中的索引值 children = tree.get_children(parent_id) return children.index(item) else: # 如果没有父节点,直接返回根节点下的索引值 root_children = tree.get_children() return root_children.index(item) def download_check(*value): global downloading time.sleep(0.2) try: if not downloading: downloading = True run(download_music, var0.get(), get_treeview_index(songlist, songlist.selection()[0]) + 1) except: downloading = False def download_music(song_name, choose): global progressbar, downloading def update_progressbar(): while True: progress = int((downloaded / total_length) * 100) progressbar['value'] = progress if downloaded == total_length: break time.sleep(0.05) try: progressbar = Progressbar(labelframe_download, mode='determinate', length=490, style='success.Striped.Horizontal.TProgressbar') progressbar.place(x=10, y=300) br = br_dict[var.get()] if choice == "KUWO": resp = requests.get(f"{url}/?msg={song_name}&n={choose}&br={br}&limit=60") resp.close() id = resp.json()["data"]["rid"].replace("MUSIC_", "") resp_lrc = requests.get(f"https://api.jkyai.top/API/yyjhss.php?id={id}&type=kw") resp_lrc.close() try: lrc = resp_lrc.json()["data"]["lrc"] except Exception as e: print(f"download_kw_lrc: {e}") lrc = "" music_name = resp.json()["data"]["song"] singer = resp.json()["data"]["singer"] music_url = resp.json()["data"]["url"] elif choice == "WANGYIYUN": resp = requests.get(f"{url}/?name={song_name}&n={choose}&br={br}&limit=60") resp.close() id = resp.json()["data"]["id"] resp_lrc = requests.get(f"https://api.jkyai.top/API/yyjhss.php?id={id}&type=wy") resp_lrc.close() try: lrc = resp_lrc.json()["data"]["lrc"] except Exception as e: print(f"download_wyy_lrc: {e}") lrc = "" music_name = resp.json()["data"]["name"] singer = resp.json()["data"]["singers"][0]["name"] music_url = resp.json()["data"]["url"] else: lrc = "" response = requests.get(music_url, stream=True) formated = music_url.split("?")[0].rsplit(".", 1)[1] filename_without_endswith = f"{singer} - {music_name}" filename = f"{filename_without_endswith}.{formated}" filename = filename.replace("\\", "#").replace("/", "#") filename = filename.replace(":", "#").replace("*", "#") filename = filename.replace("?", "#").replace("\"", "#") filename = filename.replace("<", "#").replace(">", "#").replace("|", "#") temp_filename = f"{filename}.crdownload" if path == "./music": if os.path.exists("./music"): pass else: os.makedirs("./music") try: if lrc: with open(os.path.join(path, f"{filename_without_endswith}.lrc", ), "w", encoding="utf-8") as f: f.write(lrc) except: pass temp_filepath = os.path.join(path, temp_filename) final_filepath = os.path.join(path, filename) # 检查同名文件是否存在 if os.path.exists(final_filepath): progressbar.destroy() response.close() if not lrc: display(labelframe_download, lang.get(la, 'ui.download.text.file_exists', {"_filename_": filename})) else: display(labelframe_download, lang.get(la, 'ui.download.text.download_lyrics_success')) downloading = False return with open(temp_filepath, "wb") as f: total_length = int(response.headers.get('content-length')) downloaded = 0 run(update_progressbar) for data in response.iter_content(chunk_size=1024): downloaded += len(data) f.write(data) os.rename(temp_filepath, final_filepath) refresh() time.sleep(0.1) progressbar.destroy() response.close() display(labelframe_download, lang.get(la, 'ui.download.text.download_success', {"_singer_": f"{singer}", "_music_": f"{music_name}"})) downloading = False except KeyError: downloading = False progressbar.destroy() if song_name == "": songlist.delete(0, "end") display(labelframe_download, lang.get(la, "ui.download.text.download_fail_no_keys")) else: display(labelframe_download, lang.get(la, "ui.download.text.search_fail_not_found")) except PermissionError: downloading = False progressbar.destroy() response.close() display(labelframe_download, lang.get(la, "ui.download.text.download_fail_no_permission")) except requests.exceptions.ConnectionError: downloading = False progressbar.destroy() response.close() display(labelframe_download, lang.get(la, "ui.download.text.download_fail_no_network")) except FileNotFoundError: downloading = False progressbar.destroy() response.close() display(labelframe_download, lang.get(la, "ui.download.text.download_fail_file_not_found")) except FileExistsError: downloading = False progressbar.destroy() response.close() display(labelframe_download, lang.get(la, 'ui.download.text.download_success', {"_singer_": f"{singer}", "_music_": f"{music_name}"})) def run(task, *args): t = threading.Thread(target=task, args=args, daemon=True) t.start() def get_data_without_blocking(song_name): def search_and_update_list(): global last_search_target if song_name != last_search_target: try: button0["state"] = "disabled" songlist.delete(*songlist.get_children()) if choice == "KUWO": url1 = f"{url}/?msg={song_name}&limit=60" else: url1 = f"{url}/?name={song_name}&limit=60" resp = requests.get(url1) jsondata = resp.json()["data"] resp.close() last_search_target = song_name for index in range(len(jsondata)): if choice == "KUWO": full_name = jsondata[index]["song"] artist = jsondata[index]["singer"] album = jsondata[index]["album"] else: full_name = jsondata[index]["name"] artist = jsondata[index]["singers"][0]["name"] album = "" songlist.insert("", "end", values=(full_name, artist, album)) except requests.exceptions.JSONDecodeError: resp_text = resp.text songname_rule = '"songname": "(.*?)",' name_rule = '"name": "(.*?)",' songname_list = re.findall(songname_rule, resp_text) name_list = re.findall(name_rule, resp_text) for index in range(len(songname_list) - 1): full_name = songname_list[index] artist = name_list[index] songlist.insert("", "end", values=(full_name, artist)) except TypeError: pass except: tkinter.messagebox.showinfo(title=lang.get(la, "mbox.title.search_fail"), message=lang.get(la, "mbox.text.search_fail", )) pass finally: button0["state"] = "normal" search_thread = threading.Thread(target=search_and_update_list) search_thread.start() def refresh(): global music_dir, music_dir_without_endswith try: listbox1.delete(0, "end") music_dir_without_endswith = [os.path.splitext(file)[0] for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] music_dir = [file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] for musics in music_dir_without_endswith: listbox1.insert("end", musics) except: pass def delete(): global music_dir global listbox1 try: if tkinter.messagebox.askokcancel(lang.get(la, "mbox.title.delete"), lang.get(la, "mbox.text.delete", )): abs_path = path + "/" + music_dir[listbox1.curselection()[0]] os.remove(abs_path) music_dir.remove(music_dir[listbox1.curselection()[0]]) listbox1.delete(listbox1.curselection()[0]) except IndexError: tkinter.messagebox.showwarning(title=lang.get(la, "mbox.title.delete_fail"), message=lang.get(la, "mbox.text.delete_fail_no_target", )) except PermissionError: tkinter.messagebox.showerror(title=lang.get(la, "mbox.title.delete_fail"), message=lang.get(la, "mbox.text.delete_fail_no_permission", )) except FileNotFoundError: tkinter.messagebox.showerror(title=lang.get(la, "mbox.title.delete_fail"), message=lang.get(la, "mbox.text.delete_fail_not_found", )) def pausesound(): global music_dir, player try: if not music_player.get_finished(): music_player.pause_music() except IndexError: tkinter.messagebox.showwarning(title=lang.get(la, "mbox.title.play_fail"), message=lang.get(la, "mbox.text.play_fail_no_target", )) except: pass tkinter.messagebox.showerror(title=lang.get(la, "mbox.title.play_fail"), message=lang.get(la, "mbox.text.play_fail_not_found", )) def playsound(*event): global music_playing, music_file_name, music_file_without_endswith, lyric, song_list, song_list_limit if not music_player.get_finished(): music_player.stop_music() lyric = "" music_dir_without_endswith = [os.path.splitext(file)[0] for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] music_dir = [file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] abs_path = path + "/" + music_dir[listbox1.curselection()[0]] if abs_path not in song_list: song_list.append(abs_path) if len(song_list) > song_list_limit: del song_list[0] music_playing = abs_path music_file_name = music_dir[listbox1.curselection()[0]] music_file_without_endswith = music_dir_without_endswith[listbox1.curselection()[0]] music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(abs_path) try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: pass def playmusic(music_path): music_name = music_path.split("/")[-1] try: music_player.stop_music() except: pass try: music_player.play_music(music_path) except pygame.error: tkinter.messagebox.showerror(title=lang.get(la, "mbox.title.play_fail"), message=lang.get(la, "mbox.text.play_fail_unrecognized_format", {"_file_": music_name})) except: pass def restart0(): root.destroy() python = sys.executable os.execl(python, python, *sys.argv) def save_sth(): jsondata["br"][choice] = var.get() jsondata["playing_mode"] = playingmode save_jsondata() root.destroy() def display_sentences(): global poem, passage, label0 time.sleep(0.1) poem = "" try: resp = requests.get("http://git.nanfengling.cn/NFL_jiancx/NFLmusic/raw/branch/master/version_info/random_quote") poem = resp.text.replace("\r", "").split("\n") resp.close() resp0 = requests.get("http://git.nanfengling.cn/NFL_jiancx/NFLmusic/raw/branch/master/version_info/announcement") announcement_text = resp0.text.replace("\\n", "") resp0.close() poem = c(poem) poem_lines = [poem[i:i + 15] for i in range(0, len(poem), 15)] passage = lang.get(la, "ui.about.text.information", {"_version_": version}) time.sleep(2) random_quote["text"] = "\n".join(poem_lines) announcement["text"] = lang.get(la, "ui.about.text.announcement", {"_announcement_": announcement_text}) label0["text"] = passage except requests.exceptions.ConnectionError: poem = c(lang.get(la, "ui.about.text.starting_poem", )) poem_lines = [poem[i:i + 15] for i in range(0, len(poem), 15)] passage = lang.get(la, "ui.about.text.information", {"_version_": version}) while True: if loaded: break time.sleep(0.05) tkinter.messagebox.showinfo(title=lang.get(la, "mbox.title.network_connection_fail"), message=lang.get(la, "mbox.text.network_connection_fail", )) random_quote["text"] = "\n".join(poem_lines) label0["text"] = passage def make_resource(): global resource_path resource_path = os.getenv('APPDATA') make_image.get(resource_path) def open_file_dialog(): filepath = tkinter.filedialog.askdirectory() if filepath: var2.set(filepath) def settings(): global page, changed detect_change() if changed: response = tkinter.messagebox.askyesnocancel(lang.get(la, "mbox.title.save_settings"), lang.get(la, "mbox.text.save_settings", )) if response is not None: if response: if not os.path.exists(var2.get()): tkinter.messagebox.showwarning(title=lang.get(la, "mbox.title.position_not_exist"), message=lang.get(la, "mbox.text.position_not_exist", )) else: save_jsondata() tkinter.messagebox.showinfo(message=lang.get(la, "mbox.text.restart"), title=lang.get(la, "mbox.title.restart", )) restart0() else: page = will_page if page == "homepage": ExchangeGUI.home_page() elif page == "about": ExchangeGUI.about() elif page == "versions": ExchangeGUI.versions() var1.set(tmla.catch(la, jsondata["theme"])) var2.set(path) var3.set(auto_update) var4.set(repo_dict_reverse[choice]) var5.set(la) var6.set(auto_play) else: pass else: page = will_page if page == "homepage": ExchangeGUI.home_page() elif page == "about": ExchangeGUI.about() elif page == "versions": ExchangeGUI.versions() changed = False class joke: @staticmethod def parabola_frame(): x = -400 while True: y = pow(x / 10, 2) root.geometry(f'+{x + 400}+{int(y)}') time.sleep(0.01) x += 1 if x == 400: x = -400 @staticmethod def jump_window(): while True: for x in range(0, 20): y = pow(x, 2) root.geometry(f'+0+{int(y)}') time.sleep(0.02) for x in range(0, 20): y = pow(19 - x, 2) root.geometry(f'+0+{int(y)}') time.sleep(0.02) @staticmethod def wave_window(): while True: for x in range(-1080, 1440): y = math.sin(x / 180 * math.pi) root.geometry(f'+{int(x)}+{int(y * 300) + 300}') time.sleep(0.01) @staticmethod def portal_window(): while True: root.geometry(f'+{randint(0, 400)}+{randint(0, 400)}') time.sleep(0.1) @staticmethod def repeat_window(): for i in range(10): run(tkinter.messagebox.showinfo, lang.get(la, "mbox.title.joke0"), lang.get(la, "mbox.text.joke0", )) @staticmethod def circle_window(): while True: for i in range(360): x = math.cos(i / 180 * math.pi) y = math.sin(i / 180 * math.pi) root.geometry(f'{int(x * 300) + 400}x{int(y * 300) + 300}+{int(x * 300) + 400}+{int(y * 300) + 300}') time.sleep(0.01) def do_not_click(): global isJoking if not isJoking: tkinter.messagebox.showwarning(lang.get(la, "mbox.title.joke_warning"), lang.get(la, "mbox.text.joke_warning", )) joke_mode = randint(0, 5) ExchangeGUI.home_page() isJoking = True if joke_mode == 0: run(joke.wave_window) elif joke_mode == 1: run(joke.jump_window) elif joke_mode == 2: run(joke.parabola_frame) elif joke_mode == 3: run(joke.repeat_window) isJoking = False elif joke_mode == 4: run(joke.portal_window) elif joke_mode == 5: run(joke.circle_window) else: tkinter.messagebox.showwarning(lang.get(la, "mbox.title.joke_fail"), lang.get(la, "mbox.text.joke_fail", )) def update(): global datalist, have_checked, screen_height, screen_width def f_update_progressbar(): while True: progress = int((downloaded / total_length) * 100) update_progressbar['value'] = progress if downloaded == total_length: break time.sleep(0.05) def f_app_progressbar(): while True: progress = int((downloaded / total_length) * 100) app_progressbar['value'] = progress if downloaded == total_length: break time.sleep(0.05) def prevent_closing(): pass def run_update(): subprocess.Popen(update_path + "update.exe") appdata = os.getenv('APPDATA') if not os.path.exists(appdata + "/.NFLmusic/update"): os.mkdir(appdata + "/.NFLmusic/update") if not have_checked: data_url = "http://git.nanfengling.cn/NFL_jiancx/NFLmusic/raw/branch/master/version_info/data" data_resp = requests.get(data_url) data_resp.close() datalist = data_resp.text.replace("\r", "").split("\n") update_path = appdata + "/.NFLmusic/update/" data_url = "http://git.nanfengling.cn/NFL_jiancx/NFLmusic/raw/branch/master/version_info/latest_update_log" data_resp = requests.get(data_url).text latest_version = datalist[0] if latest_version != version: if not jsondata["auto_update"]: response = tkinter.messagebox.askquestion( lang.get(la, "mbox.title.update_reminding", {"_version_": latest_version}), lang.get(la, "mbox.text.update_reminding", {"_update_": data_resp})) if response == "yes": check_update_button["state"] = "disabled" # 将root隐藏 root.withdraw() download_page = Toplevel(root) x_dl = (screen_width - 360) // 2 y_dl = (screen_height - 200) // 2 download_page.geometry(f"360x200+{x_dl}+{y_dl}") download_page.title(lang.get(la, "mbox.title.update_start", {"_version_": latest_version})) download_page.protocol("WM_DELETE_WINDOW", prevent_closing) download_page.resizable(False, False) download_page.iconbitmap(resource_path + "/.NFLmusic/resource/icon.ico") update_progressbar = Progressbar(download_page, mode="determinate", length=320, style="success.Striped.Horizontal.TProgressbar") app_progressbar = Progressbar(download_page, mode="determinate", length=320, style="info.Striped.Horizontal.TProgressbar") Label(download_page, text=lang.get(la, "ui.update.text.download_update")).pack() update_progressbar.pack() Label(download_page, text=f"\n\n{lang.get(la, 'ui.update.text.download_app')}").pack() app_progressbar.pack() update_url = datalist[1] app_url = datalist[2] try: update_resp = requests.get(update_url, stream=True) app_resp = requests.get(app_url, stream=True) with open(update_path + "file_path", "w") as f: f.write(latest_version + "\n" + os.path.abspath(sys.executable)) with open(update_path + "update.exe", "wb") as f: total_length = int(update_resp.headers.get('content-length')) downloaded = 0 run(f_update_progressbar) for data in update_resp.iter_content(chunk_size=1024): downloaded += len(data) f.write(data) time.sleep(0.1) with open(update_path + f"NFLmusicv{latest_version}.exe", "wb") as f: total_length = int(app_resp.headers.get('content-length')) downloaded = 0 run(f_app_progressbar) for data in app_resp.iter_content(chunk_size=1024): downloaded += len(data) f.write(data) run_update() download_page.destroy() root.destroy() except: download_page.destroy() tkinter.messagebox.showerror(title=lang.get(la, "mbox.title.update_fail"), message=lang.get(la, "mbox.text.update_fail", )) else: check_update_button["state"] = "normal" else: tkinter.messagebox.showinfo(lang.get(la, "mbox.title.update_start", {"_version_": latest_version}), lang.get(la, "mbox.text.update_start_auto", {"_update_": data_resp})) check_update_button["state"] = "disabled" # 将root隐藏 root.withdraw() download_page = Toplevel(root) x_dl = (screen_width - 360) // 2 y_dl = (screen_height - 200) // 2 download_page.geometry(f"360x200+{x_dl}+{y_dl}") download_page.title(lang.get(la, "mbox.title.update_start", {"_version_": latest_version})) download_page.protocol("WM_DELETE_WINDOW", prevent_closing) download_page.resizable(False, False) download_page.iconbitmap(resource_path + "/.NFLmusic/resource/icon.ico") update_progressbar = Progressbar(download_page, mode="determinate", length=320, style="success.Striped.Horizontal.TProgressbar") app_progressbar = Progressbar(download_page, mode="determinate", length=320, style="info.Striped.Horizontal.TProgressbar") Label(download_page, text=lang.get(la, "ui.update.text.download_update")).pack() update_progressbar.pack() Label(download_page, text=f"\n\n{lang.get(la, 'ui.update.text.download_app')}").pack() app_progressbar.pack() update_url = datalist[1] app_url = datalist[2] try: update_resp = requests.get(update_url, stream=True) app_resp = requests.get(app_url, stream=True) with open(update_path + "file_path", "w") as f: f.write(latest_version + "\n" + os.path.abspath(sys.executable)) with open(update_path + "update.exe", "wb") as f: total_length = int(update_resp.headers.get('content-length')) downloaded = 0 run(f_update_progressbar) for data in update_resp.iter_content(chunk_size=1024): downloaded += len(data) f.write(data) time.sleep(0.1) with open(update_path + f"NFLmusicv{latest_version}.exe", "wb") as f: total_length = int(app_resp.headers.get('content-length')) downloaded = 0 run(f_app_progressbar) for data in app_resp.iter_content(chunk_size=1024): downloaded += len(data) f.write(data) run_update() download_page.destroy() root.destroy() except Exception as e: # 重新显示窗口 root.deiconify() print(e) download_page.destroy() tkinter.messagebox.showerror(title=lang.get(la, "mbox.title.update_fail"), message=lang.get(la, "mbox.text.update_fail", )) def check_update(): global datalist, have_checked check_update_button["state"] = "disabled" try: data_url = "http://git.nanfengling.cn/NFL_jiancx/NFLmusic/raw/branch/master/version_info/data" data_resp = requests.get(data_url) datalist = data_resp.text.replace("\r", "").split("\n") latest_version = datalist[0] data_resp.close() if version == latest_version: tkinter.messagebox.showinfo(lang.get(la, "mbox.title.update_reminding", {"- v_version_": ""}), lang.get(la, "mbox.text.update_latest")) check_update_button["state"] = "normal" else: run(update) except: check_update_button["state"] = "normal" have_checked = True class ExchangeGUI: exchanged = False page_list = ["homepage", "settings", "about", "versions"] @staticmethod def close_other_page(): homepage_frame.place_forget() setting_frame.place_forget() about_frame.place_forget() version_frame.place_forget() @classmethod def display_animation(cls, frame, current_page): if not cls.exchanged: global page cls.exchanged = True frame.place(x=0, y=1000) def animation(): global page, former_page if cls.page_list.index(page) > cls.page_list.index(former_page): for i in range(40, 0, -1): frame.place(x=pow(i, 2), y=0) time.sleep(0.01) elif cls.page_list.index(page) < cls.page_list.index(former_page): for i in range(40, 0, -1): frame.place(x=-pow(i, 2), y=0) time.sleep(0.01) elif cls.page_list.index(page) == cls.page_list.index(former_page): for i in range(40, 0, -1): frame.place(x=0, y=pow(i, 2)) time.sleep(0.01) cls.exchanged = False page = current_page run(animation) @staticmethod def home_page(): global page, will_page, former_page if page == "settings": will_page = "homepage" settings() else: ExchangeGUI.close_other_page() page = "homepage" ExchangeGUI.display_animation(homepage_frame, page) former_page = "homepage" @staticmethod def window_settings(): global page, former_page ExchangeGUI.close_other_page() var2.set(path) page = "settings" ExchangeGUI.display_animation(setting_frame, page) former_page = "settings" @staticmethod def about(): global page, will_page, former_page will_page = "about" if page == "settings": will_page = "about" settings() else: ExchangeGUI.close_other_page() page = "about" ExchangeGUI.display_animation(about_frame, page) former_page = "about" @staticmethod def versions(): global page, will_page, former_page will_page = "versions" if page == "settings": will_page = "versions" settings() else: ExchangeGUI.close_other_page() page = "versions" ExchangeGUI.display_animation(version_frame, page) former_page = "versions" def tick(): def lrc_rolling(timestamp): global next_showed try: lrc = lyrics.get_lyrics(lyric, music_player.get_progress()) try: timestamp_list = list(lyric.keys()) next_timestamp = timestamp_list[timestamp_list.index(timestamp) + 1] this_time = music_player.decode_format(timestamp) next_time = music_player.decode_format(next_timestamp) rolling_frequency = (next_time - this_time) / (len(lrc) - 30) / 1.5 except: end_time = music_player.decode_format(music_player.get_length()) this_time = music_player.decode_format(timestamp) rolling_frequency = (end_time - this_time) / (len(lrc) - 30) / 1.5 for i in range(0, len(lrc) - 30): music_lrc["text"] = lrc[i:i + 31] time.sleep(rolling_frequency) if next_showed: next_showed = False break except: pass global music_playing, playingmode, music_file_name, music_file_without_endswith, lyric, song_list last_timestamp = "0" while True: try: music_dir_with_path = [path + "/" + file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] song_list = [song for song in song_list if song in music_dir_with_path] if music_player.finish: if auto_play: playing_progress.state(["disabled"]) playsoundButton["image"] = imagetk1 try: if playingmode == 0: if music_playing: refresh() music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(music_playing) if playingmode == 1: if music_playing: refresh() music_dir_with_path = [path + "/" + file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] if music_playing == song_list[-1]: if len(song_list) >= len(music_dir_with_path): del song_list[0] elif len(song_list) > song_list_limit: del song_list[0] song_list_full = [song for song in music_dir_with_path if song not in song_list] random_index = randint(0, len(song_list_full) - 1) abs_path = song_list_full[random_index] music_file_without_endswith = abs_path.split("/")[-1].rsplit(".", 1)[0] song_list.append(abs_path) music_playing = abs_path else: try: current_index = song_list.index(music_playing) except ValueError: current_index = -1 abs_path = song_list[current_index + 1] music_file_without_endswith = abs_path.split("/")[-1].rsplit(".", 1)[0] music_playing = abs_path try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except Exception as e: print(e) lyric = {} music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(abs_path) if playingmode == 2: if music_playing: refresh() music_dir = [file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] music_dir_without_endswith = [os.path.splitext(file)[0] for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] try: music_file_name = music_dir[music_dir.index(music_file_name) + 1] music_file_without_endswith = music_dir_without_endswith[ music_dir_without_endswith.index(music_file_without_endswith) + 1] abs_path = path + "/" + music_file_name music_playing = abs_path try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except Exception as e: print(e) lyric = {} except IndexError: music_file_name = music_dir[0] music_file_without_endswith = music_dir_without_endswith[0] music_playing = path + "/" + music_file_name try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: lyric = {} music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(music_playing) except Exception as e: print(e) pass else: playing_progress.state(["!disabled"]) try: if lyric: if len(lyrics.get_lyrics(lyric, music_player.get_progress())) >= 30: if last_timestamp != music_player.get_progress(): run(lrc_rolling, music_player.get_progress()) last_timestamp = music_player.get_progress() else: next_showed = True music_lrc["text"] = lyrics.get_lyrics(lyric, music_player.get_progress()) else: music_lrc["text"] = "" except: pass if music_player.get_busy(): playsoundButton["image"] = imagetk6 else: playsoundButton["image"] = imagetk1 except: pass time.sleep(0.1) def former_song(): global music_playing, lyric, music_file_name, song_list, song_list_limit, music_file_without_endswith if playingmode == 1: refresh() music_dir_with_path = [path + "/" + file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] if music_playing == song_list[0]: if len(song_list) >= len(music_dir_with_path): del song_list[-1] elif len(song_list) > song_list_limit: del song_list[-1] song_list_full = [song for song in music_dir_with_path if song not in song_list] random_index = randint(0, len(song_list_full) - 1) abs_path = song_list_full[random_index] music_file_without_endswith = abs_path.split("/")[-1].rsplit(".", 1)[0] song_list.insert(0, abs_path) music_playing = abs_path else: try: current_index = song_list.index(music_playing) except ValueError: song_list.append(music_playing) current_index = -1 abs_path = song_list[current_index - 1] music_file_without_endswith = abs_path.rsplit("/")[-1].rsplit(".", 1)[0] music_playing = abs_path try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: lyric = {} music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(abs_path) if playingmode in [0, 2]: refresh() music_dir = [file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] try: music_file_name = music_dir[music_dir.index(music_playing.split("/")[-1]) - 1] music_file_without_endswith = music_file_name.split("/")[-1].rsplit(".", 1)[0] abs_path = path + "/" + music_file_name music_playing = abs_path try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: lyric = {} except IndexError: music_file_name = music_dir[0] music_file_without_endswith = music_file_name.split("/")[-1].rsplit(".", 1)[0] music_playing = path + "/" + music_file_name try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: lyric = {} music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(music_playing) def latter_song(): global music_playing, lyric, music_file_name, song_list, song_list_limit, music_file_without_endswith if playingmode == 1: refresh() music_dir_with_path = [path + "/" + file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] try: last_song = song_list[-1] except IndexError: last_song = song_list[0] if music_playing == last_song: if len(song_list) >= len(music_dir_with_path): del song_list[0] elif len(song_list) > song_list_limit: del song_list[0] song_list_full = [song for song in music_dir_with_path if song not in song_list] random_index = randint(0, len(song_list_full) - 1) abs_path = song_list_full[random_index] music_file_without_endswith = abs_path.split("/")[-1].rsplit(".", 1)[0] song_list.append(abs_path) music_playing = abs_path else: try: current_index = song_list.index(music_playing) except ValueError: current_index = 0 song_list.insert(0, music_playing) abs_path = song_list[current_index + 1] music_file_without_endswith = abs_path.split("/")[-1].rsplit(".", 1)[0] music_playing = abs_path try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: lyric = {} music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(abs_path) if playingmode in [0, 2]: refresh() music_dir = [file for file in os.listdir(path) if file.endswith(('.mp3', '.flac', '.ogg', '.m4a'))] try: music_file_name = music_dir[music_dir.index(music_playing.split("/")[-1]) + 1] music_file_without_endswith = music_file_name.split("/")[-1].rsplit(".", 1)[0] abs_path = path + "/" + music_file_name music_playing = abs_path try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: lyric = {} except IndexError: music_file_name = music_dir[0] music_file_without_endswith = music_file_name.split("/")[-1].rsplit(".", 1)[0] music_playing = path + "/" + music_file_name try: lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") except: lyric = {} music_player.set_format_of_time( lang.get(la, "ui.playing.text.time_format", {"_music_": music_file_without_endswith})) playmusic(music_playing) def entry_focus(boolean): global last_search_target if boolean: if entry.get() == lang.get(la, "ui.download.entry.song_name"): var0.set("") else: if entry.get() == "": var0.set(lang.get(la, "ui.download.entry.song_name")) def change_playing_mode(): global playingmode if playingmode == 0: playingmodeButton["image"] = imagetk7["rand"] playingmode += 1 elif playingmode == 1: playingmodeButton["image"] = imagetk7["sequ"] playingmode += 1 else: playingmodeButton["image"] = imagetk7["loop"] playingmode = 0 def load_versions(): global version_json time.sleep(0.5) try: resp = requests.get("http://git.nanfengling.cn/NFL_jiancx/NFLmusic/raw/branch/master/version_info/version_list.json") version_json = resp.json() resp.close() for version_item in version_json: list_version = version_item["version"] list_upload_time = version_item["upload_time"] list_brief = version_item["brief"] version_list.insert("", "end", values=(list_version, list_upload_time, list_brief)) except: labelframe_update_log["text"] = lang.get(la, "frame.update_log", {"_version_": "NFLmusic"}) def version_choice(*event): global version_download_choice try: version_download_choice = version_list.selection()[0] choice_index = get_treeview_index(version_list, version_download_choice) labelframe_update_log["text"] = lang.get(la, "frame.update_log", {"_version_": version_json[choice_index]["version"]}) data["state"] = "normal" data.delete(1.0, END) data.insert("end", version_json[choice_index]["log"]) data["state"] = "disabled" download_button.place(relx=0.5, rely=0.9, anchor="center") except: pass def return_all_log(*event): data["state"] = "normal" text = logs.get(la) data.delete("1.0", END) data.insert('end', text) data["state"] = "disabled" download_button.place_forget() labelframe_update_log["text"] = lang.get(la, "frame.update_log", {"_version_": "NFLmusic"}) def download_version(): version_web = version_json[get_treeview_index(version_list, version_download_choice)]["url"] if tkinter.messagebox.askyesno(lang.get(la, "mbox.title.download_web"), lang.get(la, "mbox.text.download_web", {"_url_": version_web})): tkinter.messagebox.showinfo(lang.get(la, "mbox.title.copy_pwd"), lang.get(la, "mbox.text.copy_pwd", {"_pwd_": version_json[ get_treeview_index(version_list, version_download_choice)][ "password"]})) webbrowser.open(version_web) copy(version_json[get_treeview_index(version_list, version_download_choice)]["password"]) version = "4.0.10" poem = "" appdata = os.getenv("APPDATA") make_resource() make_lang_json() if not os.path.exists(appdata + "/.NFLmusic/NFLmusic.json"): make_jsondata() try: with open(appdata + '/.NFLmusic/NFLmusic.json', 'r') as file: jsondata = json.loads(file.read()) la = jsondata["language"] theme = tmla.catch(la, jsondata["theme"]) choice = jsondata["choice"] url = ij.api_data[choice][0] br_dict = ij.api_data[choice][1] br_list = [br for br in br_dict] path = jsondata["path"] br = jsondata["br"][choice] auto_update = jsondata["auto_update"] playingmode = jsondata["playing_mode"] auto_play = jsondata["auto_play"] except: make_jsondata() with open(appdata + '/.NFLmusic/NFLmusic.json', 'r') as file: jsondata = json.loads(file.read()) la = jsondata["language"] theme = tmla.catch(la, jsondata["theme"]) choice = jsondata["choice"] url = ij.api_data[choice][0] br_dict = ij.api_data[choice][1] br_list = [br for br in br_dict] path = jsondata["path"] br = jsondata["br"][choice] auto_update = jsondata["auto_update"] playingmode = jsondata["playing_mode"] auto_play = jsondata["auto_play"] theme0 = tmla.get(la)[theme] style = Style(theme=theme0) style.configure("Treeview", rowheight=40) root = style.master version_json = {} version_download_choice = 0 song_list_limit = 20 music_player = MusicPlayer(root) music_playing = "" music_file_name = "" music_dir_without_endswith = [] song_list = [] music_file_without_endswith = "" lyric = "" last_search_target = "" root.resizable(0, 0) screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() # 计算窗口左上角的位置使窗口居中 x = (screen_width - 810) // 2 y = (screen_height - 530) // 2 root.geometry(f'810x530+{x}+{y}') root.title(f"NFLmusic v{version}") root.protocol('WM_DELETE_WINDOW', save_sth) downloading = False var = StringVar() var0 = StringVar() var0.set(lang.get(la, "ui.download.entry.song_name")) var1 = StringVar() var2 = StringVar() var3 = BooleanVar() var3.set(auto_update) var4 = StringVar() var5 = StringVar() var5.set(la) var6 = BooleanVar() var6.set(auto_play) isJoking = False changed = False player = None OptionMenu = ttk.OptionMenu Button = ttk.Button Scrollbar = ttk.Scrollbar Progressbar = ttk.Progressbar Checkbutton = ttk.Checkbutton Entry = ttk.Entry showed = False page = "homepage" will_page = "homepage" former_page = "homepage" next_showed = False loaded = False have_checked = False playingmode_dict = { 0: "loop", 1: "rand", 2: "sequ" } if path == "./music": if os.path.exists("./music"): pass else: os.makedirs("./music") image1 = Image.open(resource_path + "/.NFLmusic/resource/buttons/playsound.png") imagetk1 = ImageTk.PhotoImage(image1.resize((20, 20))) image2 = Image.open(resource_path + "/.NFLmusic/resource/buttons/download.png") imagetk2 = ImageTk.PhotoImage(image2.resize((16, 16))) image3 = Image.open(resource_path + "/.NFLmusic/resource/buttons/refresh.png") imagetk3 = ImageTk.PhotoImage(image3.resize((16, 16))) image4 = Image.open(resource_path + "/.NFLmusic/resource/buttons/delete.png") imagetk4 = ImageTk.PhotoImage(image4.resize((16, 16))) image5 = Image.open(resource_path + "/.NFLmusic/resource/buttons/browse.png") imagetk5 = ImageTk.PhotoImage(image5.resize((16, 16))) image6 = Image.open(resource_path + "/.NFLmusic/resource/buttons/pausesound.png") imagetk6 = ImageTk.PhotoImage(image6.resize((20, 20))) image7 = {"sequ": Image.open(resource_path + "/.NFLmusic/resource/buttons/playingmode_sequential.png"), "rand": Image.open(resource_path + "/.NFLmusic/resource/buttons/playingmode_random.png"), "loop": Image.open(resource_path + "/.NFLmusic/resource/buttons/playingmode_loop.png")} imagetk7 = {"sequ": ImageTk.PhotoImage(image7["sequ"].resize((16, 16))), "rand": ImageTk.PhotoImage(image7["rand"].resize((16, 16))), "loop": ImageTk.PhotoImage(image7["loop"].resize((16, 16)))} image8 = Image.open(resource_path + "/.NFLmusic/resource/images/logo.png") imagetk8 = ImageTk.PhotoImage(image8.resize((256, 256))) image9 = Image.open(resource_path + "/.NFLmusic/resource/buttons/former.png") imagetk9 = ImageTk.PhotoImage(image9.resize((20, 20))) image0 = Image.open(resource_path + "/.NFLmusic/resource/buttons/latter.png") imagetk0 = ImageTk.PhotoImage(image0.resize((20, 20))) run(opening_animation) label_image = Label(root, image=imagetk8) label_image.place(relx=0.5, rely=0.5, anchor="center") # 主页 homepage_frame = ttk.Frame(root, width=1000, height=1000) labelframe_playing_settings = ttk.Labelframe(homepage_frame, text=lang.get(la, "frame.playing_settings"), width=770, height=120) labelframe_playing_settings.place(x=20, y=380) # 操控按钮 button_x = 15 button_y = 9 play_button_y = 7 formerButton = Button(labelframe_playing_settings, image=imagetk9, style="Link.TButton", command=former_song) formerButton.place(x=button_x + 45, y=play_button_y) latterButton = Button(labelframe_playing_settings, image=imagetk0, style="Link.TButton", command=latter_song) latterButton.place(x=button_x + 135, y=play_button_y) playsoundButton = Button(labelframe_playing_settings, command=pausesound, image=imagetk1, style="Link.TButton") playsoundButton.place(x=button_x + 90, y=play_button_y) playingmodeButton = Button(labelframe_playing_settings, command=change_playing_mode, image=imagetk7[playingmode_dict[playingmode]], style="Link.TButton") playingmodeButton.place(x=button_x + 180, y=button_y) refreshButton = Button(labelframe_playing_settings, command=refresh, style="Link.TButton", image=imagetk3) refreshButton.place(x=button_x, y=button_y) deleteButton = Button(labelframe_playing_settings, command=delete, style="Link.TButton", image=imagetk4) deleteButton.place(x=button_x + 225, y=button_y) playing_time = ttk.Label(labelframe_playing_settings, text="") playing_time.place(relx=0.03, rely=0.5) music_lrc = ttk.Label(labelframe_playing_settings, text=lyric, style="Link.TLabel", font=("黑体", 15), foreground="orange") music_lrc.place(relx=0.65, rely=0.3, anchor="center") playing_progress = ttk.Scale(labelframe_playing_settings, length=730, from_=0, to=1) playing_progress.place(x=20, y=70) labelframe_song_list = ttk.Labelframe(homepage_frame, text=lang.get(la, "frame.song_list"), width=250, height=354) labelframe_song_list.place(x=20, y=20) scrollbar1 = Scrollbar(labelframe_song_list, orient=VERTICAL) listbox1 = Listbox(labelframe_song_list, width=30, height=17, yscrollcommand=scrollbar1.set) listbox1.place(x=10, y=8) listbox1.bind("", playsound) scrollbar1.config(command=listbox1.yview) scrollbar1.place(x=227, y=8, height=315) refresh() labelframe_download = ttk.Labelframe(homepage_frame, text=lang.get(la, "frame.download"), height=354, width=510) labelframe_download.place(x=280, y=20) scrollbar2 = Scrollbar(labelframe_download, orient=VERTICAL) songlist = ttk.Treeview(labelframe_download, columns=("Song", "Artist", "Album"), height=5, show="headings", yscrollcommand=scrollbar2.set) songlist.heading("Song", text=lang.get(la, "ui.download.treeview.song")) songlist.heading("Artist", text=lang.get(la, "ui.download.treeview.artist")) songlist.heading("Album", text=lang.get(la, "ui.download.treeview.album")) songlist.column("Song", width=160, minwidth=160) songlist.column("Artist", width=160, minwidth=160) songlist.column("Album", width=160, minwidth=160) songlist.place(x=5, y=50) songlist.bind("", download_check) scrollbar2.config(command=songlist.yview) scrollbar2.place(x=490, y=50, height=235) button0 = Button(labelframe_download, text=lang.get(la, "ui.download.button.search"), command=lambda: get_data_without_blocking(var0.get()), style="Outline.TButton") button0.place(x=230, y=10) Label(labelframe_download, text=lang.get(la, "ui.download.text.song_name")).place(x=10, y=14) Label(labelframe_download, text=lang.get(la, "ui.download.text.sound_quality")).place(x=310, y=14) entry = Entry(labelframe_download, textvariable=var0) entry.place(x=70, y=10) entry.bind("", lambda event: get_data_without_blocking(var0.get())) entry.bind("", lambda event: entry_focus(True)) entry.bind("", lambda event: entry_focus(False)) menu0 = OptionMenu(labelframe_download, var, br, *br_list) menu0.place(x=370, y=10) # 设置页面 setting_frame = Frame(root, width=1000, height=1000) labelframe_settings = ttk.Labelframe(setting_frame, text=lang.get(la, "frame.base_settings"), height=480, width=500) labelframe_settings.place(x=20, y=20) # 关于页面 about_frame = Frame(root, width=1000, height=1000) labelframe_treasure_chest = ttk.LabelFrame(about_frame, text=lang.get(la, "frame.treasure_chest"), height=210, width=500) labelframe_treasure_chest.place(x=20, y=20) random_quote = Label(labelframe_treasure_chest, text="", font=("楷体", 18)) random_quote.place(relx=0.5, rely=0.2, anchor="center") do_not_click_button = Button(labelframe_treasure_chest, text=lang.get(la, "ui.about.button.do_not_click"), style="danger.Outline.TButton", width=30, command=do_not_click) do_not_click_button.place(relx=0.5, rely=0.7, anchor="center") labelframe_about = ttk.LabelFrame(about_frame, text=lang.get(la, "frame.about"), height=261, width=500) labelframe_about.place(x=20, y=240) label0 = Label(labelframe_about, text="") label0.place(x=30, y=10) announcement = Label(labelframe_about, text="") announcement.place(x=300, y=10) run(display_sentences) labelframe_thanks = LabelFrame(about_frame, text=lang.get(la, "frame.thanks"), height=480, width=250, ) labelframe_thanks.place(x=540, y=20) # 鸣谢 oiapi = "https://oiapi.net/" githook = "http://git.nanfengling.cn/" nanfect = "http://pan.nanfengling.cn/" skylark = "https://space.bilibili.com/1868716664" sponsorship = "https://afdian.com/a/NFLstudio" lb0 = lb(pack_box=labelframe_thanks, label=lang.get(la, 'ui.thanks.text.music_url'), button=lang.get(la, 'ui.thanks.button.music_url'), command=lambda: webbrowser.open(oiapi)) lb0.place(button=(80, 15), label=(10, 20)) lb1 = lb(pack_box=labelframe_thanks, label=lang.get(la, 'ui.thanks.text.random_poem'), button=lang.get(la, 'ui.thanks.button.random_poem'), command=lambda: webbrowser.open(githook)) lb1.place(button=(80, 55), label=(10, 60)) lb2 = lb(pack_box=labelframe_thanks, label=lang.get(la, 'ui.thanks.text.file_store'), button=lang.get(la, 'ui.thanks.button.file_store'), command=lambda: webbrowser.open(nanfect)) lb2.place(button=(80, 95), label=(10, 100)) lb3 = lb(pack_box=labelframe_thanks, label=lang.get(la, 'ui.thanks.text.bug_fix'), button=lang.get(la, 'ui.thanks.button.bug_fix'), command=lambda: webbrowser.open(skylark)) lb3.place(button=(80, 135), label=(10, 140)) lb4 = lb(pack_box=labelframe_thanks, label=lang.get(la, 'ui.thanks.text.sponsorship'), button=lang.get(la, 'ui.thanks.button.sponsorship'), command=lambda: webbrowser.open(sponsorship)) lb4.place(button=(80, 175), label=(10, 180)) scrollbar3 = Scrollbar(labelframe_thanks, orient=VERTICAL) sponsors_list = Listbox(labelframe_thanks, height=13, width=30, yscrollcommand=scrollbar3.set) sponsors_list.place(x=10, y=210) scrollbar3.config(command=sponsors_list.yview) scrollbar3.place(x=227, y=210, height=240) try: data_url = "http://git.nanfengling.cn/NFL_jiancx/NFLmusic/raw/branch/master/version_info/sponsors" data_resp = requests.get(data_url) data_list = data_resp.text.replace("\r", "").split("\n") for sponsor in data_list: sponsors_list.insert("end", sponsor) data_resp.close() except: pass # 开发版本页面 version_frame = Frame(root, width=1000, height=1000) current_version = Label(version_frame, font=("微软雅黑", 10), text=lang.get(la, "ui.versions.text.current_version", {"_version_": version})) current_version.place(relx=0.4, rely=0.08, anchor="center") labelframe_version_list = LabelFrame(version_frame, text=lang.get(la, "frame.version_list"), height=350, width=500) labelframe_version_list.place(x=20, y=140) scrollbar4 = Scrollbar(labelframe_version_list, orient=VERTICAL) version_list = ttk.Treeview(labelframe_version_list, style="success.Treeview", columns=("Version", "UploadTime", "UpdateBrief"), height=6, show="headings", yscrollcommand=scrollbar4.set) version_list.heading("Version", text=lang.get(la, "ui.versions.treeview.version")) version_list.heading("UploadTime", text=lang.get(la, "ui.versions.treeview.upload_time")) version_list.heading("UpdateBrief", text=lang.get(la, "ui.versions.treeview.update_brief")) version_list.column("Version", width=100, minwidth=100) version_list.column("UploadTime", width=100, minwidth=100) version_list.column("UpdateBrief", width=250, minwidth=250) version_list.place(x=20, y=20) version_list.bind("", version_choice) version_list.bind("", return_all_log) scrollbar4.config(command=version_list.yview) scrollbar4.place(x=475, y=40, height=255) labelframe_update_log = ttk.LabelFrame(version_frame, text=lang.get(la, "frame.update_log", {"_version_": "NFLmusic"}), height=350, width=250) labelframe_update_log.place(x=540, y=140) # 更新日志 scrollbar = Scrollbar(labelframe_update_log, orient=VERTICAL) data = Text(labelframe_update_log, width=29, height=14, yscrollcommand=scrollbar.set) data.place(x=10, y=16) scrollbar.config(command=data.yview) scrollbar.place(x=230, y=10, height=265) download_button = Button(labelframe_update_log, image=imagetk2, style="warning.TButton", command=lambda: download_version()) return_all_log() run(load_versions) # 菜单栏 menubar = Menu(root) menubar.add_command(label=lang.get(la, "menu.homepage"), command=ExchangeGUI.home_page) menubar.add_command(label=lang.get(la, "menu.settings"), command=ExchangeGUI.window_settings) menubar.add_command(label=lang.get(la, "menu.about"), command=ExchangeGUI.about) menubar.add_command(label=lang.get(la, "menu.versions"), command=ExchangeGUI.versions) themeLabel = Label(labelframe_settings, text=lang.get(la, "ui.settings.text.theme", )) themeLabel.place(x=10, y=25) # 基本设置 repo_dict = { "酷我音乐": "KUWO", "网易云音乐": "WANGYIYUN" } repo_dict_reverse = {} for repo in repo_dict: repo_dict_reverse[repo_dict[repo]] = repo repo_list = [repo for repo in repo_dict] language_list = lang.list_languages() label3 = Label(labelframe_settings, text=lang.get(la, 'ui.settings.text.download_source', )) label3.place(x=10, y=65) if repo_dict_reverse.get(jsondata["choice"]) is None: jsondata["choice"] = "KUWO" menu0 = OptionMenu(labelframe_settings, var4, repo_dict_reverse[jsondata["choice"]], *repo_list) menu0.place(x=80, y=60) label1 = Label(labelframe_settings, text=lang.get(la, 'ui.settings.text.download_position', )) label1.place(x=10, y=105) entry0 = Entry(labelframe_settings, textvariable=var2, width=20) entry0.place(x=80, y=100) button1 = Button(labelframe_settings, image=imagetk5, command=open_file_dialog) button1.place(x=240, y=100) label2 = Label(labelframe_settings, text=lang.get(la, 'ui.settings.text.auto_update', )) label2.place(x=10, y=142) check_button1 = Checkbutton(labelframe_settings, variable=var3, style="Squaretoggle.Toolbutton", text=lang.get(la, "ui.settings.check_button.auto_update", )) check_button1.place(x=80, y=140) label3 = Label(labelframe_settings, text=lang.get(la, 'ui.settings.text.language', )) label3.place(x=10, y=175) lang_optionmenu = OptionMenu(labelframe_settings, var5, jsondata["language"], *language_list) lang_optionmenu.place(x=50, y=170) label4 = Label(labelframe_settings, text=lang.get(la, 'ui.settings.button.auto_play', )) label4.place(x=10, y=212) check_button2 = Checkbutton(labelframe_settings, variable=var6, style="Squaretoggle.Toolbutton", text=lang.get(la, "ui.settings.check_button.auto_play", )) check_button2.place(x=80, y=210) check_update_button = Button(labelframe_settings, text=lang.get(la, 'ui.settings.button.check_update', ), command=check_update, style="info.Outline.TButton") check_update_button.place(x=10, y=240) menu1 = OptionMenu(labelframe_settings, var1, theme, *list(tmla.get(la).keys())) menu1.place(x=50, y=20) root.iconbitmap(resource_path + "/.NFLmusic/resource/icon.ico") run(tick) music_player.bind(cls_time=playing_time, cls_progress_bar=playing_progress) playing_progress["command"] = lambda event: music_player.set_progress(playing_progress.get()) music_player.set_format_of_time(lang.get(la, "ui.playing.text.time_format", {"_music_": ""})) root.mainloop()