tkinter_ui.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import os
  2. import sys
  3. sys.path.append(os.path.dirname(sys.path[0]))
  4. import tkinter as tk
  5. from tkinter import messagebox
  6. from PIL import Image, ImageTk
  7. from utils.config import config
  8. from utils.tools import resource_path
  9. from main import UpdateSource
  10. import asyncio
  11. import threading
  12. import webbrowser
  13. from about import AboutUI
  14. from default import DefaultUI
  15. from speed import SpeedUI
  16. from prefer import PreferUI
  17. from multicast import MulticastUI
  18. from hotel import HotelUI
  19. from subscribe import SubscribeUI
  20. from online_search import OnlineSearchUI
  21. import json
  22. class TkinterUI:
  23. def __init__(self, root):
  24. with open(resource_path("version.json"), "r", encoding="utf-8") as f:
  25. info = json.load(f)
  26. self.root = root
  27. self.root.title(info.get("name", ""))
  28. self.version = info.get("version", "")
  29. self.about_ui = AboutUI()
  30. self.default_ui = DefaultUI()
  31. self.speed_ui = SpeedUI()
  32. self.prefer_ui = PreferUI()
  33. self.multicast_ui = MulticastUI()
  34. self.hotel_ui = HotelUI()
  35. self.subscribe_ui = SubscribeUI()
  36. self.online_search_ui = OnlineSearchUI()
  37. self.update_source = UpdateSource()
  38. self.update_running = False
  39. self.result_url = None
  40. def view_result_link_callback(self, event):
  41. webbrowser.open_new_tab(self.result_url)
  42. def save_config(self):
  43. config_values = {
  44. "open_driver": self.default_ui.open_driver_var.get(),
  45. "open_filter_resolution": self.speed_ui.open_filter_resolution_var.get(),
  46. "open_hotel": self.hotel_ui.open_hotel_var.get(),
  47. "open_hotel_foodie": self.hotel_ui.open_hotel_foodie_var.get(),
  48. "open_hotel_fofa": self.hotel_ui.open_hotel_fofa_var.get(),
  49. "open_keep_all": self.default_ui.open_keep_all_var.get(),
  50. "open_multicast": self.multicast_ui.open_multicast_var.get(),
  51. "open_multicast_foodie": self.multicast_ui.open_multicast_foodie_var.get(),
  52. "open_multicast_fofa": self.multicast_ui.open_multicast_fofa_var.get(),
  53. "open_online_search": self.online_search_ui.open_online_search_var.get(),
  54. "open_proxy": self.default_ui.open_proxy_var.get(),
  55. "open_request": self.default_ui.open_request_var.get(),
  56. "open_service": self.default_ui.open_service_var.get(),
  57. "open_sort": self.speed_ui.open_sort_var.get(),
  58. "open_subscribe": self.subscribe_ui.open_subscribe_var.get(),
  59. "open_supply": self.prefer_ui.open_supply_var.get(),
  60. "open_update": self.default_ui.open_update_var.get(),
  61. "open_update_time": self.default_ui.open_update_time_var.get(),
  62. "open_url_info": self.default_ui.open_url_info_var.get(),
  63. "open_use_cache": self.default_ui.open_use_cache_var.get(),
  64. "open_use_old_result": self.default_ui.open_use_old_result_var.get(),
  65. "final_file": self.default_ui.final_file_entry.get(),
  66. "hotel_region_list": self.hotel_ui.region_list_combo.get(),
  67. "hotel_page_num": self.hotel_ui.page_num_entry.get(),
  68. "ipv_type": self.default_ui.ipv_type_combo.get(),
  69. "ipv6_support": self.default_ui.ipv6_support_var.get(),
  70. "min_resolution": self.speed_ui.min_resolution_entry.get(),
  71. "multicast_region_list": self.multicast_ui.region_list_combo.get(),
  72. "multicast_page_num": self.multicast_ui.page_num_entry.get(),
  73. "online_search_page_num": self.online_search_ui.page_num_entry.get(),
  74. "recent_days": self.online_search_ui.recent_days_entry.get(),
  75. "request_timeout": self.default_ui.request_timeout_entry.get(),
  76. "sort_timeout": self.speed_ui.sort_timeout_entry.get(),
  77. "source_file": self.default_ui.source_file_entry.get(),
  78. "urls_limit": self.default_ui.urls_limit_entry.get(),
  79. }
  80. for key, value in config_values.items():
  81. config.set("Settings", key, str(value))
  82. config.save()
  83. messagebox.showinfo("提示", "保存成功")
  84. def change_state(self, state):
  85. self.default_ui.change_entry_state(state=state)
  86. self.speed_ui.change_entry_state(state=state)
  87. self.prefer_ui.change_entry_state(state=state)
  88. self.multicast_ui.change_entry_state(state=state)
  89. self.hotel_ui.change_entry_state(state=state)
  90. self.subscribe_ui.change_entry_state(state=state)
  91. self.online_search_ui.change_entry_state(state=state)
  92. async def run_update(self):
  93. self.update_running = not self.update_running
  94. if self.update_running:
  95. self.run_button.config(text="取消更新", state="normal")
  96. self.change_state("disabled")
  97. self.progress_bar["value"] = 0
  98. self.progress_label.pack()
  99. self.view_result_link.pack()
  100. self.progress_bar.pack()
  101. await self.update_source.start(self.update_progress)
  102. else:
  103. self.stop()
  104. self.update_source.stop()
  105. self.run_button.config(text="开始更新", state="normal")
  106. self.change_state("normal")
  107. self.progress_bar.pack_forget()
  108. self.view_result_link.pack_forget()
  109. self.progress_label.pack_forget()
  110. def on_run_update(self):
  111. loop = asyncio.new_event_loop()
  112. def run_loop():
  113. asyncio.set_event_loop(loop)
  114. loop.run_until_complete(self.run_update())
  115. self.thread = threading.Thread(target=run_loop, daemon=True)
  116. self.thread.start()
  117. def stop(self):
  118. asyncio.get_event_loop().stop()
  119. def update_progress(self, title, progress, finished=False, url=None):
  120. self.progress_bar["value"] = progress
  121. progress_text = f"{title}, 进度: {progress}%" if not finished else f"{title}"
  122. self.progress_label["text"] = progress_text
  123. self.root.update()
  124. if finished:
  125. self.run_button.config(text="开始更新", state="normal")
  126. self.update_running = False
  127. self.change_state("normal")
  128. if url:
  129. self.view_result_link.config(text=url)
  130. self.result_url = url
  131. def init_UI(self):
  132. menu_bar = tk.Menu(self.root)
  133. help_menu = tk.Menu(menu_bar, tearoff=0)
  134. help_menu.add_command(
  135. label="关于",
  136. command=lambda: self.about_ui.init_ui(root=self.root, version=self.version),
  137. )
  138. menu_bar.add_cascade(label="帮助", menu=help_menu)
  139. self.root.config(menu=menu_bar)
  140. notebook = tk.ttk.Notebook(self.root)
  141. notebook.pack(fill="both", padx=10, pady=5)
  142. frame_default = tk.ttk.Frame(notebook)
  143. frame_speed = tk.ttk.Frame(notebook)
  144. frame_prefer = tk.ttk.Frame(notebook)
  145. frame_hotel = tk.ttk.Frame(notebook)
  146. frame_multicast = tk.ttk.Frame(notebook)
  147. frame_subscribe = tk.ttk.Frame(notebook)
  148. frame_online_search = tk.ttk.Frame(notebook)
  149. settings_icon_source = Image.open(
  150. resource_path("static/images/settings_icon.png")
  151. ).resize((16, 16))
  152. settings_icon = ImageTk.PhotoImage(settings_icon_source)
  153. speed_icon_source = Image.open(
  154. resource_path("static/images/speed_icon.png")
  155. ).resize((16, 16))
  156. speed_icon = ImageTk.PhotoImage(speed_icon_source)
  157. prefer_icon_source = Image.open(
  158. resource_path("static/images/prefer_icon.png")
  159. ).resize((16, 16))
  160. prefer_icon = ImageTk.PhotoImage(prefer_icon_source)
  161. hotel_icon_source = Image.open(
  162. resource_path("static/images/hotel_icon.png")
  163. ).resize((16, 16))
  164. hotel_icon = ImageTk.PhotoImage(hotel_icon_source)
  165. multicast_icon_source = Image.open(
  166. resource_path("static/images/multicast_icon.png")
  167. ).resize((16, 16))
  168. multicast_icon = ImageTk.PhotoImage(multicast_icon_source)
  169. subscribe_icon_source = Image.open(
  170. resource_path("static/images/subscribe_icon.png")
  171. ).resize((16, 16))
  172. subscribe_icon = ImageTk.PhotoImage(subscribe_icon_source)
  173. online_search_icon_source = Image.open(
  174. resource_path("static/images/online_search_icon.png")
  175. ).resize((16, 16))
  176. online_search_icon = ImageTk.PhotoImage(online_search_icon_source)
  177. notebook.add(
  178. frame_default, text="通用设置", image=settings_icon, compound=tk.LEFT
  179. )
  180. notebook.add(frame_speed, text="测速设置", image=speed_icon, compound=tk.LEFT)
  181. notebook.add(frame_prefer, text="偏好设置", image=prefer_icon, compound=tk.LEFT)
  182. notebook.add(frame_hotel, text="酒店源", image=hotel_icon, compound=tk.LEFT)
  183. notebook.add(
  184. frame_multicast, text="组播源", image=multicast_icon, compound=tk.LEFT
  185. )
  186. notebook.add(
  187. frame_subscribe, text="订阅源", image=subscribe_icon, compound=tk.LEFT
  188. )
  189. notebook.add(
  190. frame_online_search,
  191. text="关键字搜索",
  192. image=online_search_icon,
  193. compound=tk.LEFT,
  194. )
  195. notebook.settings_icon = settings_icon
  196. notebook.speed_icon = speed_icon
  197. notebook.prefer_icon = prefer_icon
  198. notebook.hotel_icon = hotel_icon
  199. notebook.multicast_icon = multicast_icon
  200. notebook.subscribe_icon = subscribe_icon
  201. notebook.online_search_icon = online_search_icon
  202. self.default_ui.init_ui(frame_default)
  203. self.speed_ui.init_ui(frame_speed)
  204. self.prefer_ui.init_ui(frame_prefer)
  205. self.multicast_ui.init_ui(frame_multicast)
  206. self.hotel_ui.init_ui(frame_hotel)
  207. self.subscribe_ui.init_ui(frame_subscribe)
  208. self.online_search_ui.init_ui(frame_online_search)
  209. root_operate = tk.Frame(self.root)
  210. root_operate.pack(fill=tk.X, pady=8, padx=120)
  211. root_operate_column1 = tk.Frame(root_operate)
  212. root_operate_column1.pack(side=tk.LEFT, fill=tk.Y)
  213. root_operate_column2 = tk.Frame(root_operate)
  214. root_operate_column2.pack(side=tk.RIGHT, fill=tk.Y)
  215. self.save_button = tk.ttk.Button(
  216. root_operate_column1, text="保存设置", command=self.save_config
  217. )
  218. self.save_button.pack(side=tk.LEFT, padx=4, pady=8)
  219. self.run_button = tk.ttk.Button(
  220. root_operate_column2, text="开始更新", command=self.on_run_update
  221. )
  222. self.run_button.pack(side=tk.LEFT, padx=4, pady=8)
  223. root_progress = tk.Frame(self.root)
  224. root_progress.pack(fill=tk.X)
  225. self.progress_bar = tk.ttk.Progressbar(
  226. root_progress, length=300, mode="determinate"
  227. )
  228. self.progress_bar.pack_forget()
  229. self.progress_label = tk.Label(root_progress, text="进度: 0%")
  230. self.progress_label.pack_forget()
  231. self.view_result_link = tk.Label(
  232. root_progress, text="", fg="blue", cursor="hand2"
  233. )
  234. self.view_result_link.bind(
  235. "<Button-1>",
  236. self.view_result_link_callback,
  237. )
  238. self.view_result_link.pack_forget()
  239. def get_root_location(root):
  240. screen_width = root.winfo_screenwidth()
  241. screen_height = root.winfo_screenheight()
  242. width = 500
  243. height = 600
  244. x = (screen_width / 2) - (width / 2)
  245. y = (screen_height / 2) - (height / 2)
  246. return (width, height, x, y)
  247. if __name__ == "__main__":
  248. root = tk.Tk()
  249. tkinter_ui = TkinterUI(root)
  250. tkinter_ui.init_UI()
  251. screen_width = root.winfo_screenwidth()
  252. screen_height = root.winfo_screenheight()
  253. root.geometry("%dx%d+%d+%d" % get_root_location(root))
  254. root.iconbitmap(resource_path("static/images/favicon.ico"))
  255. root.after(0, config.copy)
  256. root.mainloop()