ソースを参照

feat: 调整垃圾站代码的依赖结构

SongZihuan 3 年 前
コミット
edc1b80976
2 ファイル変更201 行追加148 行削除
  1. 16 15
      control/ranking.py
  2. 185 133
      control/station.py

+ 16 - 15
control/ranking.py

@@ -21,10 +21,6 @@ class RankingPageError(RankingStationException):
 
 
 class RankingStationBase(metaclass=abc.ABCMeta):
-    status_normal = 1
-    status_get_garbage_type = 2
-    status_get_garbage_check = 3
-
     def __init__(self, db: DB):
         self._db = db
         self.rank = [[]]
@@ -87,6 +83,9 @@ class RankingStationBase(metaclass=abc.ABCMeta):
         self.show_rank(self.rank[self.rank_index])
         self.set_prev_btn(False)
 
+        if self.auto:
+            self.set_run_after_now(self.auto_time, self.update_rank_auto)
+
     def rank_page_to_prev(self):
         if self.rank_index == 0:  # 当 rank_index为最后一项时, 该函数不应该被调用(除非数据库被外部改动)
             self.set_prev_btn(True)
@@ -103,6 +102,9 @@ class RankingStationBase(metaclass=abc.ABCMeta):
         self.show_rank(self.rank[self.rank_index])
         self.set_next_btn(False)
 
+        if self.auto:
+            self.set_run_after_now(self.auto_time, self.update_rank_auto)
+
     def show_rank_first(self):
         self.rank_index = 0
         self.offset = 0
@@ -121,7 +123,7 @@ class RankingStationBase(metaclass=abc.ABCMeta):
         if auto:
             self.auto = True
             self.disable_btn()
-            self.set_after_run(self.auto_time, self.update_rank_auto)  # 注册自动函数
+            self.set_run_after_now(self.auto_time, self.update_rank_auto)  # 注册自动函数
         else:
             self.auto = False
             self.able_btn()
@@ -141,8 +143,6 @@ class RankingStationBase(metaclass=abc.ABCMeta):
         else:
             return  # 无法动弹
 
-        self.set_after_run(self.auto_time, self.update_rank_auto)
-
     @abc.abstractmethod
     def show_rank(self, rank_info: List[Tuple[int, uname_t, uid_t, score_t, score_t, Optional[str]]]):
         ...
@@ -172,7 +172,7 @@ class RankingStationBase(metaclass=abc.ABCMeta):
         ...
 
     @abc.abstractmethod
-    def set_after_run(self, ms, func, *args):
+    def set_run_after_now(self, ms, func, *args):
         ...
 
     @abc.abstractmethod
@@ -182,6 +182,7 @@ class RankingStationBase(metaclass=abc.ABCMeta):
 
 class RankingStation(RankingStationBase):
     def __init__(self, db: DB):
+        self.init_after_run_list: List[Tuple[int, Callable, Tuple]] = []
         super(RankingStation, self).__init__(db)
 
         self.window = tk.Tk()
@@ -319,6 +320,9 @@ class RankingStation(RankingStationBase):
         self.rank_btn[1]['command'] = lambda: self.rank_auto(True)
         self.rank_btn[2]['command'] = lambda: self.rank_page_to_next()
 
+    def set_run_after_now(self, ms, func, *args):
+        self.window.after(ms, func, *args)
+
     def __set_rank_info(self, rank_info: List[Tuple[int, uname_t, uid_t, score_t, score_t, Optional[str]]]):
         if len(rank_info) > self.rank_count:
             rank_info = rank_info[:self.rank_count]
@@ -339,6 +343,10 @@ class RankingStation(RankingStationBase):
             relheight = self.rank_y_height[i][1]
             self.rank_label[i].place(relx=0.04, rely=rely, relwidth=0.92, relheight=relheight)
 
+    @staticmethod
+    def __make_font(family: str = 'noto', **kwargs):
+        return font.Font(family=conf.font_d[family], **kwargs)
+
     def show_rank(self, rank_info: List[Tuple[int, uname_t, uid_t, score_t, score_t, Optional[str]]]):
         self.__set_rank_info(rank_info)
         self.rank_title_var.set("Ranking")
@@ -352,10 +360,6 @@ class RankingStation(RankingStationBase):
             self.rank_btn[1]['command'] = lambda: self.rank_auto(True)
             self.rank_btn[1]['text'] = 'auto'
 
-    @staticmethod
-    def __make_font(family: str = 'noto', **kwargs):
-        return font.Font(family=conf.font_d[family], **kwargs)
-
     def set_next_btn(self, disable: False):
         if disable or self.auto:  # auto 模式令btn失效
             self.rank_btn[2]['state'] = 'disable'
@@ -386,9 +390,6 @@ class RankingStation(RankingStationBase):
     def is_able_next(self):
         return self.next_btn
 
-    def set_after_run(self, ms, func, *args):
-        self.window.after(ms, func, *args)
-
     def mainloop(self):
         self.window.mainloop()
 

+ 185 - 133
control/station.py

@@ -5,6 +5,7 @@ import cv2
 import sys
 import random
 import traceback
+import abc
 import tkinter as tk
 from tkinter import ttk
 import tkinter.font as font
@@ -48,9 +49,8 @@ class RankingUserError(GarbageStationException):
 
 
 class StationEventBase(TkEventBase):
-    def __init__(self, win, status, db: DB, title: str = 'unknown'):
-        self._win: GarbageStationTkinter = win
-        self._status: GarbageStation = status
+    def __init__(self, gb_station, db: DB, title: str = 'unknown'):
+        self.station: GarbageStationBase = gb_station
         self._db: DB = db
         self._title = title
 
@@ -64,7 +64,7 @@ class StationEventBase(TkEventBase):
         raise GarbageStationException
 
 
-class GarbageStation:
+class GarbageStationBase(metaclass=abc.ABCMeta):
     status_normal = 1
     status_get_garbage_type = 2
     status_get_garbage_check = 3
@@ -82,7 +82,6 @@ class GarbageStation:
         self._db: DB = db
         self._cap: HGSCapture = cap
         self._qr: HGSQRCoder = qr
-        self._win: GarbageStationTkinter = GarbageStationTkinter(self)
         self._loc: location_t = loc
 
         self._user: Optional[User] = None  # 操作者
@@ -90,12 +89,13 @@ class GarbageStation:
 
         self._garbage: Optional[GarbageBag] = None
 
-        self._flat = GarbageStation.status_normal
+        self._flat = GarbageStationBase.status_normal
         self._have_easter_eggs = False
 
         self.rank = None
         self.rank_index = 0
         self._event_list: List[StationEventBase] = []
+        self.set_after_run(conf.tk_refresh_delay, lambda: self.run_event())
 
     def update_user_time(self):
         if self.check_user():
@@ -204,11 +204,11 @@ class GarbageStation:
         return list(cur.fetchall())
 
     def to_get_garbage_type(self, garbage: GarbageBag):
-        self._flat = GarbageStation.status_get_garbage_type
+        self._flat = GarbageStationBase.status_get_garbage_type
         self.set_garbage(garbage)
 
     def to_get_garbage_check(self, garbage: GarbageBag):
-        self._flat = GarbageStation.status_get_garbage_check
+        self._flat = GarbageStationBase.status_get_garbage_check
         self.set_garbage(garbage)
 
     def set_garbage(self, garbage: GarbageBag):
@@ -221,34 +221,34 @@ class GarbageStation:
 
     def throw_garbage(self, garbage_type: enum):
         self.update_user_time()
-        if self._flat != GarbageStation.status_get_garbage_type or self._garbage is None:
-            self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
+        if self._flat != GarbageStationBase.status_get_garbage_type or self._garbage is None:
+            self.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             return
 
-        event = ThrowGarbageEvent(self._win, self, self._db).start(self._garbage, garbage_type)
+        event = ThrowGarbageEvent(self, self._db).start(self._garbage, garbage_type)
         self.push_event(event)
-        self._flat = GarbageStation.status_normal
+        self._flat = GarbageStationBase.status_normal
         self._garbage = None
 
     def check_garbage(self, check: bool):
         self.update_user_time()
-        if self._flat != GarbageStation.status_get_garbage_check or self._garbage is None:
-            self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
+        if self._flat != GarbageStationBase.status_get_garbage_check or self._garbage is None:
+            self.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             return
 
-        event = CheckGarbageEvent(self._win, self, self._db).start(self._garbage, check)
+        event = CheckGarbageEvent(self, self._db).start(self._garbage, check)
         self.push_event(event)
-        self._flat = GarbageStation.status_normal
+        self._flat = GarbageStationBase.status_normal
         self._garbage = None
 
     def show_garbage_info(self):
         self.update_user_time()
-        if self._flat != GarbageStation.status_get_garbage_check or self._garbage is None:
-            self._win.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
+        if self._flat != GarbageStationBase.status_get_garbage_check or self._garbage is None:
+            self.show_warning("Operation Fail", "You should login first and scan the QR code of the trash bag")
             return
 
         if not self._garbage.is_use():
-            self._win.show_warning("Operation Fail", "The garbage bag has not been used")
+            self.show_warning("Operation Fail", "The garbage bag has not been used")
             return
 
         info = self._garbage.get_info()
@@ -260,42 +260,42 @@ class GarbageStation:
                 check += f'CheckResult is Pass\n'
             else:
                 check += f'CheckResult is Fail\n'
-            self._win.show_msg("Garbage Info", (f"Type is {garbage_type}\n"
-                                                f"User is {info['user'][0:conf.tk_show_uid_len]}\n"
-                                                f"Location:\n  {info['loc']}\n"
-                                                f"{check}"
-                                                f"Date:\n  {time_str}"))  # 遮蔽Pass和Fail按键
+            self.show_msg("Garbage Info", (f"Type is {garbage_type}\n"
+                                           f"User is {info['user'][0:conf.tk_show_uid_len]}\n"
+                                           f"Location:\n  {info['loc']}\n"
+                                           f"{check}"
+                                           f"Date:\n  {time_str}"))  # 遮蔽Pass和Fail按键
         elif self._garbage.is_use():
             time_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(info['use_time'])))
-            self._win.show_msg("Garbage Info", (f"Type is {garbage_type}\n"
-                                                f"User is {info['user'][0:conf.tk_show_uid_len]}\n"
-                                                f"Location:\n  {info['loc']}\n"
-                                                f"Date:\n  {time_str}"), big=False)  # 不遮蔽Pass和Fail按键
+            self.show_msg("Garbage Info", (f"Type is {garbage_type}\n"
+                                           f"User is {info['user'][0:conf.tk_show_uid_len]}\n"
+                                           f"Location:\n  {info['loc']}\n"
+                                           f"Date:\n  {time_str}"), big=False)  # 不遮蔽Pass和Fail按键
         else:
-            self._win.show_msg("Garbage Info", f"Garbage has not use")  # 遮蔽Pass和Fail按键
+            self.show_msg("Garbage Info", f"Garbage has not use")  # 遮蔽Pass和Fail按键
 
     def show_user_info(self):
         self.update_user_time()
         if not self.check_user():
-            self._win.show_warning("Operation Fail", "You should login first")
+            self.show_warning("Operation Fail", "You should login first")
             return
 
         info = self.get_user_info()
         if info.get('manager', '0') == '1':
-            self._win.show_msg("About User", (f"Manager User\n"
-                                              f"UserName: {info['name']}\n"
-                                              f"UserID:\n  {info['uid']}"))
+            self.show_msg("About User", (f"Manager User\n"
+                                         f"UserName: {info['name']}\n"
+                                         f"UserID:\n  {info['uid']}"))
         else:
-            self._win.show_msg("About User", (f"Normal User\n"
-                                              f"UserName: {info['name']}\n"
-                                              f"UserID:\n  {info['uid']}\n"
-                                              f"Score: {info['score']}\n"
-                                              f"Reputation: {info['reputation']}\n"
-                                              f"Rubbish: {info['rubbish']}"))
+            self.show_msg("About User", (f"Normal User\n"
+                                         f"UserName: {info['name']}\n"
+                                         f"UserID:\n  {info['uid']}\n"
+                                         f"Score: {info['score']}\n"
+                                         f"Reputation: {info['reputation']}\n"
+                                         f"Rubbish: {info['rubbish']}"))
 
     def show_help_info(self):
         self.update_user_time()
-        self._win.show_msg("Help", f'''
+        self.show_msg("Help", f'''
 HGSSystem:
   1) Scan User QR code
   2) Scan Garbage QR code
@@ -307,7 +307,7 @@ HGSSystem:
 
     def show_about_info(self):
         self.update_user_time()
-        self._win.show_msg("About", f'''
+        self.show_msg("About", f'''
 HGSSystem (c) SuperHuan
 From github
 HGSSystem is Garbage Sorting System
@@ -318,16 +318,16 @@ Run on python {sys.version}
     def show_exit(self):
         self.update_user_time()
         if self.is_manager():
-            self._win.exit_win()
+            self.exit_win()
             return
-        self._win.show_warning("Exit", f'Permission not permitted'.strip())
+        self.show_warning("Exit", f'Permission not permitted'.strip())
 
     def easter_eggs(self):
         self.update_user_time()
         if (not self._have_easter_eggs) and random.randint(0, 10) != 1:  # 10% 概率触发
             return
         self._have_easter_eggs = True
-        self._win.show_msg("Easter Agg", f'''
+        self.show_msg("Easter Agg", f'''
 恭喜触发彩蛋[中文]
 尝试一下新的编程语言: aFunlang.
 来自: github
@@ -337,7 +337,7 @@ Run on python {sys.version}
 
     def show_search_info(self):
         self.update_user_time()
-        self._win.show_msg("Search", f'''
+        self.show_msg("Search", f'''
 He will get the camera content and feedback the garbage type.
 The function has not yet been implemented.
                 '''.strip())
@@ -359,20 +359,20 @@ The function has not yet been implemented.
             self.rank[-1].append((i + 1, r[1], r[0], r[2], r[3], color))
         if len(self.rank[0]) == 0:
             self.rank = None
-            self._win.show_warning("RankError", f'Unable to get leaderboard data')
+            self.show_warning("RankError", f'Unable to get leaderboard data')
             return
         self.rank_index = 0
-        self.show_rank(0)
+        self.get_rank(0)
 
-    def show_rank(self, n: int):
+    def get_rank(self, n: int):
         self.update_user_time()
         self.rank_index += n
 
         if self.rank_index < 0 or self.rank_index >= len(self.rank):
-            self._win.show_msg("RankError", f'Unable to get leaderboard data')
+            self.show_msg("RankError", f'Unable to get leaderboard data')
             return
 
-        self._win.show_rank(self.rank_index + 1, len(self.rank), self.rank[self.rank_index])
+        self.show_rank(self.rank_index + 1, len(self.rank), self.rank[self.rank_index])
 
     def scan(self):
         """
@@ -383,21 +383,18 @@ The function has not yet been implemented.
         self._cap.get_image()
         qr_code = self._qr.get_qr_code()
         if qr_code is None:
-            return GarbageStation.scan_no_to_done, None
+            return GarbageStationBase.scan_no_to_done, None
 
-        user_scan_event = ScanUserEvent(self._win, self, self._db).start(qr_code)
+        user_scan_event = ScanUserEvent(self, self._db).start(qr_code)
         self.push_event(user_scan_event)
 
     def get_show_rank(self):
-        event = RankingEvent(self._win, self, self._db)
+        event = RankingEvent(self, self._db)
         self.push_event(event)
 
-    def mainloop(self):
-        self._win.mainloop()
-
     def push_event(self, event: StationEventBase):
         self._event_list.append(event)
-        self._win.show_loading(event.get_title())
+        self.show_loading(event.get_title())
         self.run_event()
 
     def run_event(self):
@@ -413,7 +410,7 @@ The function has not yet been implemented.
                 new_event.append(event)
         self._event_list = new_event
         if len(self._event_list) == 0:
-            self._win.stop_loading()
+            self.stop_loading()
 
         for event in done_event:  # 隐藏进度条后执行Event-GUI任务
             try:
@@ -421,13 +418,75 @@ The function has not yet been implemented.
             except:
                 traceback.print_exc()
 
+    @abc.abstractmethod
+    def show_msg(self, title, info, msg_type='info', big: bool = True):
+        ...
+
+    @abc.abstractmethod
+    def show_warning(self, title, info):
+        ...
+
+    @abc.abstractmethod
+    def show_rank(self, page: int, page_c: int,
+                  rank_info: List[Tuple[int, uname_t, uid_t, score_t, score_t, Optional[str]]],
+                  title: str = 'Ranking'):
+        ...
+
+    @abc.abstractmethod
+    def hide_msg_rank(self, update: bool = False):
+        ...
+
+    @abc.abstractmethod
+    def show_loading(self, title: str):
+        ...
+
+    @abc.abstractmethod
+    def stop_loading(self):
+        ...
+
+    @abc.abstractmethod
+    def set_after_run(self, ms, func, *args):
+        ...
+
+    @abc.abstractmethod
+    def update_control(self):
+        ...
+
+    @abc.abstractmethod
+    def update_scan(self):
+        ...
+
+    @abc.abstractmethod
+    def update_msg(self):
+        ...
+
+    @abc.abstractmethod
+    def mainloop(self):
+        ...
+
+    @abc.abstractmethod
+    def exit_win(self):
+        ...
+
+
+class GarbageStation(GarbageStationBase):
+    def set_after_run(self, ms, func, *args):  # super.__init__可能会调用
+        self.init_after_run_list.append((ms, func, args))
+
+    def __conf_set_after_run(self):
+        for ms, func, args in self.init_after_run_list:
+            self.__define_after(ms, func, *args)
 
-class GarbageStationTkinter:
     def __init__(self,
-                 status: GarbageStation,
+                 db: DB,
+                 cap: HGSCapture,
+                 qr: HGSQRCoder,
+                 loc: location_t = conf.base_location,
                  refresh_delay: int = conf.tk_refresh_delay):
+        self.init_after_run_list: List[Tuple[int, Callable, Tuple]] = []
+
+        super(GarbageStation, self).__init__(db, cap, qr, loc)
         self.refresh_delay = refresh_delay
-        self._status = status
 
         self._window = tk.Tk()
         self._sys_height = self._window.winfo_screenheight()
@@ -548,7 +607,7 @@ class GarbageStationTkinter:
         self._window['bg'] = "#F0FFF0"  # 蜜瓜绿
         self._window.attributes("-topmost", True)
         self._window.resizable(False, False)
-        self._window.protocol("WM_DELETE_WINDOW", lambda: self._status.show_exit())
+        self._window.protocol("WM_DELETE_WINDOW", lambda: self.show_exit())
         self._window.overrideredirect(False)  # 显示标题栏
         self._window.bind("<Alt-Control-KeyPress-s>", lambda _: self.__set_windows_overrideredirect(True))  # 锁定窗口
 
@@ -560,7 +619,7 @@ class GarbageStationTkinter:
         def unlock_windows(_):
             if self._disable_all_btn:
                 return
-            if self._status.is_manager():
+            if self.is_manager():
                 self.__set_windows_overrideredirect(False)
                 return
             self.show_warning("Exit", f'Permission not permitted'.strip())
@@ -568,7 +627,7 @@ class GarbageStationTkinter:
         def full_screen_windows(_):
             if self._disable_all_btn:
                 return
-            if not self._full_screen or self._status.is_manager():
+            if not self._full_screen or self.is_manager():
                 self.__full_screen(not self._full_screen)
                 return
             self.show_warning("Exit", f'Permission not permitted'.strip())
@@ -576,7 +635,7 @@ class GarbageStationTkinter:
         def easter_eggs(_):
             if self._disable_all_btn:
                 return
-            self._status.easter_eggs()
+            self.easter_eggs()
 
         self._window.bind("<Alt-Control-KeyPress-s>", lock_windows)  # 锁定窗口
         self._window.bind("<Alt-Control-KeyPress-e>", unlock_windows)
@@ -617,19 +676,19 @@ class GarbageStationTkinter:
         bt_help: tk.Button = self._win_ctrl_button[0]
         bt_help['text'] = 'Help'
         bt_help['bg'] = '#A9A9A9'
-        bt_help['command'] = lambda: self._status.show_help_info()
+        bt_help['command'] = lambda: self.show_help_info()
         bt_help.place(relx=0.81, rely=0.01, relwidth=0.05, relheight=0.05)
 
         bt_about: tk.Button = self._win_ctrl_button[1]
         bt_about['text'] = 'About'
         bt_about['bg'] = '#A9A9A9'
-        bt_about['command'] = lambda: self._status.show_about_info()
+        bt_about['command'] = lambda: self.show_about_info()
         bt_about.place(relx=0.87, rely=0.01, relwidth=0.05, relheight=0.05)
 
         bt_exit: tk.Button = self._win_ctrl_button[2]
         bt_exit['text'] = 'Exit'
         bt_exit['bg'] = '#A9A9A9'
-        bt_exit['command'] = lambda: self._status.show_exit()
+        bt_exit['command'] = lambda: self.show_exit()
         bt_exit.place(relx=0.93, rely=0.01, relwidth=0.05, relheight=0.05)
 
     def __conf_user_info_label(self):
@@ -701,10 +760,10 @@ class GarbageStationTkinter:
             btn['bg'] = info[1]
             btn['text'] = info[0]
 
-        self._throw_ctrl_btn[0]['command'] = lambda: self._status.throw_garbage(GarbageType.recyclable)
-        self._throw_ctrl_btn[1]['command'] = lambda: self._status.throw_garbage(GarbageType.other)
-        self._throw_ctrl_btn[2]['command'] = lambda: self._status.throw_garbage(GarbageType.hazardous)
-        self._throw_ctrl_btn[3]['command'] = lambda: self._status.throw_garbage(GarbageType.kitchen)
+        self._throw_ctrl_btn[0]['command'] = lambda: self.throw_garbage(GarbageType.recyclable)
+        self._throw_ctrl_btn[1]['command'] = lambda: self.throw_garbage(GarbageType.other)
+        self._throw_ctrl_btn[2]['command'] = lambda: self.throw_garbage(GarbageType.hazardous)
+        self._throw_ctrl_btn[3]['command'] = lambda: self.throw_garbage(GarbageType.kitchen)
 
         self._throw_ctrl_btn[0].place(relx=0.000, rely=0.000, relwidth=0.495, relheight=0.495)
         self._throw_ctrl_btn[1].place(relx=0.505, rely=0.000, relwidth=0.495, relheight=0.495)
@@ -723,8 +782,8 @@ class GarbageStationTkinter:
             btn['text'] = info[0]
             btn['bg'] = info[1]
 
-        self._check_ctrl_btn[0]['command'] = lambda: self._status.check_garbage(False)
-        self._check_ctrl_btn[1]['command'] = lambda: self._status.check_garbage(True)
+        self._check_ctrl_btn[0]['command'] = lambda: self.check_garbage(False)
+        self._check_ctrl_btn[1]['command'] = lambda: self.check_garbage(True)
 
         self._check_ctrl_btn[0].place(relx=0.000, rely=0.000, relwidth=0.495, relheight=1)
         self._check_ctrl_btn[1].place(relx=0.505, rely=0.000, relwidth=0.495, relheight=1)
@@ -786,8 +845,8 @@ class GarbageStationTkinter:
             height += height_label + h_label_s / height_count
 
         self._user_btn[0]['state'] = 'disable'
-        self._user_btn[1]['command'] = lambda: self._status.get_show_rank()
-        self._user_btn[2]['command'] = lambda: self._status.show_search_info()
+        self._user_btn[1]['command'] = lambda: self.get_show_rank()
+        self._user_btn[2]['command'] = lambda: self.show_search_info()
 
     def __conf_cap_label(self):
         self._cap_label['bg'] = "#000000"
@@ -878,13 +937,13 @@ class GarbageStationTkinter:
             btn['text'] = text
 
         self._rank_btn[0].place(relx=0.050, rely=0.88, relwidth=0.25, relheight=0.1)
-        self._rank_btn[0]['command'] = lambda: self._status.show_rank(-1)
+        self._rank_btn[0]['command'] = lambda: self.get_rank(-1)
 
         self._rank_btn[1].place(relx=0.375, rely=0.88, relwidth=0.25, relheight=0.1)
         self._rank_btn[1]['command'] = lambda: self.hide_msg_rank(True)
 
         self._rank_btn[2].place(relx=0.700, rely=0.88, relwidth=0.25, relheight=0.1)
-        self._rank_btn[2]['command'] = lambda: self._status.show_rank(+1)
+        self._rank_btn[2]['command'] = lambda: self.get_rank(+1)
 
     def __set_rank_info(self, rank_info: List[Tuple[int, uname_t, uid_t, score_t, score_t, Optional[str]]]):
         if len(rank_info) > 5:
@@ -941,7 +1000,7 @@ class GarbageStationTkinter:
         self._rank_frame.place_forget()
         self._msg_time = None
         if update:
-            self._status.update_user_time()
+            self.update_user_time()
 
     def __conf_loading(self):
         title_font = self.__make_font(size=self._loading_tile_font, weight="bold")
@@ -986,10 +1045,10 @@ class GarbageStationTkinter:
 
     def __conf_after(self):
         self.__define_after(self.refresh_delay, self.update_time)
-        self.__define_after(self.refresh_delay, self.update_event)
         self.__define_after(self.refresh_delay, self.update_control)
         self.__define_after(self.refresh_delay, self.update_scan)
         self.__define_after(self.refresh_delay, self.update_msg)
+        self.__conf_set_after_run()
 
     def __after_func_maker(self, func):
         def new_func(*args, **kwargs):
@@ -1003,9 +1062,6 @@ class GarbageStationTkinter:
 
         return new_func
 
-    def update_event(self):
-        self._status.run_event()
-
     def update_time(self):
         var: tk.Variable = self._sys_date[2]
         t = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
@@ -1018,7 +1074,7 @@ class GarbageStationTkinter:
         rubbish: tk.Variable = self._user_rubbish[2]
         eval_: tk.Variable = self._user_eval[2]
 
-        user_info: Dict[str, str] = self._status.get_user_info_no_update()
+        user_info: Dict[str, str] = self.get_user_info_no_update()
         if user_info.get('uid') is None:
             name.set('Not-Login')
             uid.set('Not-Login')
@@ -1049,7 +1105,7 @@ class GarbageStationTkinter:
             score.set(user_info.get('score'))
             self.__switch_to_normal_user()
 
-        garbage = self._status.get_garbage()
+        garbage = self.get_garbage()
         if garbage is None:
             self._garbage_id[2].set('---')
         else:
@@ -1059,10 +1115,10 @@ class GarbageStationTkinter:
             self._garbage_id[2].set(gid)
 
     def update_scan(self):
-        self._status.scan()
+        self.scan()
 
         # 需要存储一些数据 谨防被gc释放
-        _cap_img_info = (Image.fromarray(cv2.cvtColor(self._status.get_cap_img(), cv2.COLOR_BGR2RGB)).
+        _cap_img_info = (Image.fromarray(cv2.cvtColor(self.get_cap_img(), cv2.COLOR_BGR2RGB)).
                          transpose(Image.FLIP_LEFT_RIGHT))
         self._cap_img = ImageTk.PhotoImage(image=_cap_img_info)
         self._cap_label['image'] = self._cap_img
@@ -1097,13 +1153,13 @@ class GarbageStationTkinter:
         for btn in self._check_ctrl_btn:
             btn['state'] = 'disabled'
         self._user_btn[0]['state'] = 'normal'
-        self._user_btn[0]['command'] = lambda: self._status.show_user_info()
+        self._user_btn[0]['command'] = lambda: self.show_user_info()
 
     def manager_user_disable(self):
         for btn in self._throw_ctrl_btn:
             btn['state'] = 'disabled'
         self._user_btn[0]['state'] = 'normal'
-        self._user_btn[0]['command'] = lambda: self._status.show_garbage_info()
+        self._user_btn[0]['command'] = lambda: self.show_garbage_info()
 
     def normal_user_able(self):
         for btn in self._throw_ctrl_btn:
@@ -1152,10 +1208,10 @@ class ScanUserEvent(StationEventBase):
         def run(self):
             self.result = scan_user(self.thread_qr, self.thread_db)
 
-    def __init__(self, win: GarbageStationTkinter, status: GarbageStation, db: DB):
-        super(ScanUserEvent, self).__init__(win, status, db, "Scan User")
+    def __init__(self, gb_station: GarbageStationBase, db: DB):
+        super().__init__(gb_station, db, "Scan User")
 
-        self._user: User = status.get_user()
+        self._user: User = gb_station.get_user()
         self._qr_code: Optional[QRCode] = None
         self.thread: Optional[ScanUserEvent.ScanUserThread] = None
 
@@ -1171,11 +1227,11 @@ class ScanUserEvent(StationEventBase):
     def done_after_event(self):
         self.thread.join()
         if self.thread.result is not None:
-            self._status.switch_user(self.thread.result)
-            self._win.update_control()
+            self.station.switch_user(self.thread.result)
+            self.station.update_control()
         else:
-            event = ScanGarbageEvent(self._win, self._status, self._db).start(self._qr_code)
-            self._status.push_event(event)
+            event = ScanGarbageEvent(self.station, self._db).start(self._qr_code)
+            self.station.push_event(event)
 
 
 class ScanGarbageEvent(StationEventBase):
@@ -1189,10 +1245,10 @@ class ScanGarbageEvent(StationEventBase):
         def run(self):
             self.result = scan_garbage(self.thread_qr, self.thread_db)
 
-    def __init__(self, win: GarbageStationTkinter, status: GarbageStation, db: DB):
-        super().__init__(win, status, db, "Scan Garbage")
+    def __init__(self, gb_station: GarbageStationBase, db: DB):
+        super().__init__(gb_station, db, "Scan Garbage")
 
-        self._user: User = status.get_user()
+        self._user: User = gb_station.get_user()
         self._qr_code: Optional[QRCode] = None
         self.thread: Optional[ScanGarbageEvent.ScanUserThread] = None
 
@@ -1209,15 +1265,15 @@ class ScanGarbageEvent(StationEventBase):
         self.thread.join()
         if self.thread.result is not None:
             if self._user is None:
-                self._win.show_warning("Operation Fail", "The garbage bags have been used.")
+                self.station.show_warning("Operation Fail", "The garbage bags have been used.")
             elif self._user.is_manager():
-                self._status.to_get_garbage_check(self.thread.result)
-                self._status.show_garbage_info()  # 显示信息
-                self._win.update_control()
+                self.station.to_get_garbage_check(self.thread.result)
+                self.station.show_garbage_info()  # 显示信息
+                self.station.update_control()
             else:
-                self._status.to_get_garbage_type(self.thread.result)
-                self._win.hide_msg_rank()  # 如果有msg也马上隐藏
-                self._win.update_control()
+                self.station.to_get_garbage_type(self.thread.result)
+                self.station.hide_msg_rank()  # 如果有msg也马上隐藏
+                self.station.update_control()
 
 
 class RankingEvent(StationEventBase):
@@ -1237,10 +1293,10 @@ class RankingEvent(StationEventBase):
                 self.result = []
             self.result = list(cur.fetchall())
 
-    def __init__(self, win: GarbageStationTkinter, status: GarbageStation, db: DB):
-        super().__init__(win, status, db, "Ranking")
+    def __init__(self, gb_station: GarbageStationBase, db: DB):
+        super().__init__(gb_station, db, "Ranking")
 
-        self._user: User = status.get_user()
+        self._user: User = gb_station.get_user()
         self.thread: Optional[RankingEvent.RankingThread] = RankingEvent.RankingThread(self._db)
         self.thread.start()
 
@@ -1250,16 +1306,14 @@ class RankingEvent(StationEventBase):
     def done_after_event(self):
         self.thread.join()
         if self.thread.result is not None:
-            self._status.thread_show_rank(self.thread.result)
+            self.station.thread_show_rank(self.thread.result)
 
 
 class ThrowGarbageEvent(StationEventBase):
     class ThrowGarbageThread(threading.Thread):
-        def __init__(self, win: GarbageStationTkinter, status: GarbageStation,
-                     garbage: GarbageBag, garbage_type: enum, db_: DB):
+        def __init__(self, gb_station: GarbageStationBase, garbage: GarbageBag, garbage_type: enum, db_: DB):
             threading.Thread.__init__(self)
-            self.thread_win = win
-            self.thread_status = status
+            self.thread_station = gb_station
             self.thread_db = db_
             self.thread_garbage = garbage
             self.thread_garbage_type = garbage_type
@@ -1267,21 +1321,21 @@ class ThrowGarbageEvent(StationEventBase):
 
         def run(self):
             try:
-                self.thread_status.throw_garbage_core(self.thread_garbage, self.thread_garbage_type)
+                self.thread_station.throw_garbage_core(self.thread_garbage, self.thread_garbage_type)
             except (ThrowGarbageError, UserNotSupportError, ControlNotLogin):
-                self.thread_win.show_warning("Operation Fail", "The garbage bags have been used.")
+                self.thread_station.show_warning("Operation Fail", "The garbage bags have been used.")
                 self.result = False
             finally:
                 self.result = True
 
-    def __init__(self, win: GarbageStationTkinter, status: GarbageStation, db: DB):
-        super().__init__(win, status, db, "ThrowGarbage")
+    def __init__(self, gb_station: GarbageStationBase, db: DB):
+        super().__init__(gb_station, db, "ThrowGarbage")
 
-        self._user: User = status.get_user()
+        self._user: User = gb_station.get_user()
         self.thread: Optional[ThrowGarbageEvent.ThrowGarbageThread] = None
 
     def start(self, garbage: GarbageBag, garbage_type: enum):
-        self.thread = ThrowGarbageEvent.ThrowGarbageThread(self._win, self._status, garbage, garbage_type, self._db)
+        self.thread = ThrowGarbageEvent.ThrowGarbageThread(self.station, garbage, garbage_type, self._db)
         self.thread.start()
         return self
 
@@ -1291,16 +1345,14 @@ class ThrowGarbageEvent(StationEventBase):
     def done_after_event(self):
         self.thread.join()
         if not self.thread.result:
-            self._win.show_warning("Operation Fail", "The garbage bag throw error")
+            self.station.show_warning("Operation Fail", "The garbage bag throw error")
 
 
 class CheckGarbageEvent(StationEventBase):
     class CheckGarbageThread(threading.Thread):
-        def __init__(self, win: GarbageStationTkinter, status: GarbageStation,
-                     garbage: GarbageBag, check: bool, db_: DB):
+        def __init__(self, gb_station: GarbageStationBase, garbage: GarbageBag, check: bool, db_: DB):
             threading.Thread.__init__(self)
-            self.thread_win = win
-            self.thread_status = status
+            self.thread_station = gb_station
             self.thread_db = db_
             self.thread_garbage = garbage
             self.thread_garbage_check = check
@@ -1308,21 +1360,21 @@ class CheckGarbageEvent(StationEventBase):
 
         def run(self):
             try:
-                self.thread_status.check_garbage_core(self.thread_garbage, self.thread_garbage_check)
-            except (ThrowGarbageError, UserNotSupportError, ControlNotLogin):
-                self.thread_win.show_warning("Operation Fail", "The garbage bag has been checked")
+                self.thread_station.check_garbage_core(self.thread_garbage, self.thread_garbage_check)
+            except (ThrowGarbageError, UserNotSupportError, ControlNotLogin, CheckGarbageError):
+                self.thread_station.show_warning("Operation Fail", "The garbage bag has been checked")
                 self.result = False
             finally:
                 self.result = True
 
-    def __init__(self, win: GarbageStationTkinter, status: GarbageStation, db: DB):
-        super().__init__(win, status, db, "CheckGarbage")
+    def __init__(self, gb_station: GarbageStationBase, db: DB):
+        super().__init__(gb_station, db, "CheckGarbage")
 
-        self._user: User = status.get_user()
+        self._user: User = gb_station.get_user()
         self.thread: Optional[CheckGarbageEvent.CheckGarbageThread] = None
 
     def start(self, garbage: GarbageBag, garbage_check: bool):
-        self.thread = CheckGarbageEvent.CheckGarbageThread(self._win, self._status, garbage, garbage_check, self._db)
+        self.thread = CheckGarbageEvent.CheckGarbageThread(self.station, garbage, garbage_check, self._db)
         self.thread.start()
         return self
 
@@ -1332,7 +1384,7 @@ class CheckGarbageEvent(StationEventBase):
     def done_after_event(self):
         self.thread.join()
         if not self.thread.result:
-            self._win.show_warning("Operation Fail", "The garbage bag check error")
+            self.station.show_warning("Operation Fail", "The garbage bag check error")
 
 
 if __name__ == '__main__':