def _init_upper_frame(self): self.insufficiently = ToggleButton(self, text='Insufficiently', width=14, font=(SCP, 8), relief=RIDGE) self.insufficiently.bind( '<Button-1>', lambda event: (self.filter_manager.set_specific_condition( 'unforged', 0 if self.insufficiently.is_selected else CONDITIONLESS, rule=not_match_request), self.update_table()), add='+') self.insufficiently.place(x=380, y=3) Label(self, text='Type:', width=5, font=(MS_JH, 11)).place(x=510, y=3) self.type_selector = FilteredCombobox(self, width=4, font=(MS_JH, 9), justify=CENTER, state='readonly') self.type_selector['values'] = WEAPONS self.type_selector.place(x=558, y=5) self.type_selector.bind( '<<ComboboxSelected>>', lambda event: (self.filter_manager.set_specific_condition( 'weapon_type', self.type_selector.get()), self.update_table())) button = Button(self, text='新增', width=8, font=(MS_JH, 10)) button.place(x=640, y=1) button["command"] = lambda: open_adding_new_character_weapon_window( self, callback=lambda cw: (self.characters.append(cw), self.update_table()))
def _init_upper_frame(self): filter_frame = Frame(self, width=self["width"], height=40) filter_frame.place(x=0, y=0) current_x = 45 self.profession_selector = ProfessionSelector(filter_frame, self.updating_profession) self.profession_selector.place(x=current_x, y=-4) current_x += 199 self.rank_selector = RankSelector(filter_frame, self.updating_rank) self.rank_selector.place(x=current_x, y=-4) # 所屬篩選 current_x = 448 Label(filter_frame, text="所屬:", font=(MS_JH, 10)).place(x=current_x + 10, y=-3) self.belonged = FilteredCombobox(filter_frame, width=6, justify=CENTER) self.belonged["values"] = BELONGEDS self.belonged.place(x=current_x, y=16) self.belonged.bind("<<ComboboxSelected>>", lambda event: self.updating_belonged()) # 角色部分名稱篩選 current_x += 75 Label(filter_frame, text="篩選:", font=(MS_JH, 12)).place(x=current_x, y=7) self.request = StringVar() entry = Entry(filter_frame, width=9, textvariable=self.request, font=(MS_JH, 11)) entry.place(x=current_x + 42, y=9) entry.bind("<Return>", lambda event: self.update_table()) # 清空進行篩選的條件 button = Button(filter_frame, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=667, y=3) button["command"] = self.clearing_filters
def _init_widgets(self): self.profession_selector = ProfessionSelector(self, self.updating_request_profession) self.profession_selector.place(x=5, y=5) self.rank_selector = RankSelector(self, self.updating_request_rank) self.rank_selector.place(x=5, y=53) Label(self, text='所屬', width=5, font=("", 10)).place(x=221, y=5) self.belonged_selector = FilteredCombobox(self, width=7, font=("", 11), justify=CENTER) self.belonged_selector['values'] = BELONGEDS self.belonged_selector.place(x=213, y=22) self.belonged_selector.bind('<<ComboboxSelected>>', lambda x: self.updating_request_belonged(self.belonged_selector.get())) self.belonged_selector.bind('<Return>', lambda x: self.character_selector.focus_set()) Label(self, text='篩選', width=5, font=("", 11)).place(x=222, y=54) self.name_request = StringVar(value='') entry = Entry(self, width=8, textvariable=self.name_request, font=("", 12)) entry.place(x=214, y=73) entry.bind('<Return>', lambda x: self.updating_request_name()) entry.bind('<Escape>', lambda x: (self.name_request.set(''), self.updating_request_name())) Label(self, text='Character', width=10, font=("", 12)).place(x=304, y=26) self.character_selector = ttk.Combobox(self, state='readonly', width=10, font=("", 12), justify=CENTER) self.character_selector.place(x=305, y=48) self.character_selector.bind('<Return>', lambda x: self.submitting()) # 熱鍵,直接指過來 self.bind('<f>', lambda x: self.character_selector.focus_set()) y_position = 115 # 送交的按鈕 button = Button(self, text="選擇此角色", width=25, borderwidth=3) button.place(x=17, y=y_position) button["command"] = self.submitting # 新增角色的按鈕 button = Button(self, text="新增角色", width=9, borderwidth=3) button.place(x=225, y=y_position) button["command"] = lambda: open_adding_new_jp_character_window( self, lambda new_character: (self.update_records(), self.updating_character_selector())) # 取消並結束的按鈕 button = Button(self, text="放棄選擇", width=9, borderwidth=3) button.place(x=317, y=y_position) button["command"] = self.destroy
def _init_upper_frame(self): filter_frame = Frame(self, width=self['width'], height=40) filter_frame.place(x=0, y=0) current_x = 45 self.profession_selector = ProfessionSelector(filter_frame, self.updating_profession) self.profession_selector.place(x=current_x, y=-4) current_x += 199 self.rank_selector = RankSelector(filter_frame, self.updating_rank) self.rank_selector.place(x=current_x, y=-4) # 所屬篩選 current_x = 448 Label(filter_frame, text='所屬:', font=(MS_JH, 10)).place(x=current_x + 10, y=-3) self.belonged = FilteredCombobox(filter_frame, width=6, justify=CENTER) self.belonged['values'] = BELONGEDS self.belonged.place(x=current_x, y=16) self.belonged.bind('<<ComboboxSelected>>', lambda event: self.updating_belonged()) # 角色部分名稱篩選 current_x += 75 Label(filter_frame, text='篩選:', font=(MS_JH, 12)).place(x=current_x, y=7) self.request = StringVar() entry = Entry(filter_frame, width=9, textvariable=self.request, font=(MS_JH, 11)) entry.place(x=current_x + 42, y=9) entry.bind('<Return>', lambda event: self.update_table()) # 清空進行篩選的條件 button = Button(filter_frame, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=667, y=3) button["command"] = self.clearing_filters
def _init_upper_frame(self): self.insufficiently = ToggleButton(self, text='Insufficiently', width=14, font=(SCP, 8), relief=RIDGE) self.insufficiently.bind('<Button-1>', lambda event: ( self.filter_manager.set_specific_condition( 'unforged', 0 if self.insufficiently.is_selected else CONDITIONLESS, rule=not_match_request), self.update_table()), add='+') self.insufficiently.place(x=380, y=3) Label(self, text='Type:', width=5, font=(MS_JH, 11)).place(x=510, y=3) self.type_selector = FilteredCombobox(self, width=4, font=(MS_JH, 9), justify=CENTER, state='readonly') self.type_selector['values'] = WEAPONS self.type_selector.place(x=558, y=5) self.type_selector.bind('<<ComboboxSelected>>', lambda event: ( self.filter_manager.set_specific_condition('weapon_type', self.type_selector.get()), self.update_table())) button = Button(self, text='新增', width=8, font=(MS_JH, 10)) button.place(x=640, y=1) button["command"] = lambda: open_adding_new_character_weapon_window( self, callback=lambda cw: (self.characters.append(cw), self.update_table()))
def _init_filter_frame(self): basic_x = 20 Label(self, text='E:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.event_filter = FilteredObjectCombobox(self, setter=lambda obj: obj.name, getter=lambda obj: obj.e_id, width=16, justify=CENTER) self.event_filter.set_objects(self.events) self.event_filter.place(x=basic_x + 18, y=3) self.event_filter.bind( '<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'event_id', self.event_filter.get()), self.update_table()), add='+') self.event_filter.bind( '<Button-2>', lambda event: (open_updating_event_window( self, self.event_filter.selected_object, lambda: self. event_filter.set_objects(self.events)))) basic_x += 158 Label(self, text='C:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.cost_filter = FilteredCombobox(self, width=6, justify=CENTER) self.cost_filter['values'] = DRAW_LOTS_COST self.cost_filter.place(x=basic_x + 20, y=3) self.cost_filter.bind( '<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'cost', self.cost_filter.get()), self.update_table())) basic_x += 90 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.rank_filter = IntFilteredCombobox(self, width=3, justify=CENTER) self.rank_filter['values'] = [5, 4, 3] self.rank_filter.place(x=basic_x + 20, y=3) self.rank_filter.bind( '<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'rank', self.rank_filter.get()), self.update_table())) basic_x = 342 Label(self, text='Total:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.total_count = Label(self, font=(MS_JH, 12)) self.total_count.place(x=basic_x + 44, y=2) basic_x += 83 Label(self, text='SSR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.ssr_count = Label(self, font=(MS_JH, 10)) self.ssr_count.place(x=basic_x + 34, y=-3) self.ssr_ratio = Label(self, font=(MS_JH, 9)) self.ssr_ratio.place(x=basic_x + 44, y=13) basic_x += 80 Label(self, text='SR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.sr_count = Label(self, font=(MS_JH, 10)) self.sr_count.place(x=basic_x + 25, y=-3) self.sr_ratio = Label(self, font=(MS_JH, 9)) self.sr_ratio.place(x=basic_x + 35, y=13) basic_x += 78 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.r_count = Label(self, font=(MS_JH, 10)) self.r_count.place(x=basic_x + 16, y=-3) self.r_ratio = Label(self, font=(MS_JH, 9)) self.r_ratio.place(x=basic_x + 26, y=13) # 清空進行篩選的條件 button = Button(self, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=658, y=-1) button["command"] = self.clearing_filter
class DrawLotsFrame(MainFrameWithTable): def __init__(self, master, **kwargs): MainFrameWithTable.__init__(self, master, **kwargs) self.set_table_place(34, 29) self.table_model = TableModelAdvance() self.table_model.set_columns(RecordOfDrawLots.TABLE_VIEW_COLUMNS) # 滑鼠中鍵事件註冊,設定為更改角色詳細資訊,並選取該列 self.table_view.bind( "<Button-2>", lambda event: self.opening_character_update_window(event)) self.table_view.setModel(self.table_model) self.filter_manager = FilterRuleManager() self.records = DrawLotsModel.select_record_list() self.events = DrawLotsModel.select_event_list() self._init_adding_frame() self._init_filter_frame() self.table.tkraise() # 放上層,避免被其他元件遮到 self.update_table() def _init_adding_frame(self): # 新增酒廠的按鈕 button = Button(self, text="新增酒廠", width=2, height=5, wraplength=1, font=(MS_JH, 11)) button.place(x=7, y=41) button["command"] = lambda: open_adding_event_window( self, lambda event: (self.events.insert(0, event), self.event_filter.set_objects(self.events))) # 新增記錄的按鈕 button = Button(self, text="新增記錄", width=2, height=12, wraplength=1, font=(MS_JH, 12)) button.place(x=5, y=155) button['command'] = self.adding_record button.bind('<Button-3>', lambda event: self.adding_record(limitation=False)) def _init_filter_frame(self): basic_x = 20 Label(self, text='E:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.event_filter = FilteredObjectCombobox(self, setter=lambda obj: obj.name, getter=lambda obj: obj.e_id, width=16, justify=CENTER) self.event_filter.set_objects(self.events) self.event_filter.place(x=basic_x + 18, y=3) self.event_filter.bind( '<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'event_id', self.event_filter.get()), self.update_table()), add='+') self.event_filter.bind( '<Button-2>', lambda event: (open_updating_event_window( self, self.event_filter.selected_object, lambda: self. event_filter.set_objects(self.events)))) basic_x += 158 Label(self, text='C:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.cost_filter = FilteredCombobox(self, width=6, justify=CENTER) self.cost_filter['values'] = DRAW_LOTS_COST self.cost_filter.place(x=basic_x + 20, y=3) self.cost_filter.bind( '<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'cost', self.cost_filter.get()), self.update_table())) basic_x += 90 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.rank_filter = IntFilteredCombobox(self, width=3, justify=CENTER) self.rank_filter['values'] = [5, 4, 3] self.rank_filter.place(x=basic_x + 20, y=3) self.rank_filter.bind( '<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'rank', self.rank_filter.get()), self.update_table())) basic_x = 342 Label(self, text='Total:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.total_count = Label(self, font=(MS_JH, 12)) self.total_count.place(x=basic_x + 44, y=2) basic_x += 83 Label(self, text='SSR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.ssr_count = Label(self, font=(MS_JH, 10)) self.ssr_count.place(x=basic_x + 34, y=-3) self.ssr_ratio = Label(self, font=(MS_JH, 9)) self.ssr_ratio.place(x=basic_x + 44, y=13) basic_x += 80 Label(self, text='SR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.sr_count = Label(self, font=(MS_JH, 10)) self.sr_count.place(x=basic_x + 25, y=-3) self.sr_ratio = Label(self, font=(MS_JH, 9)) self.sr_ratio.place(x=basic_x + 35, y=13) basic_x += 78 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.r_count = Label(self, font=(MS_JH, 10)) self.r_count.place(x=basic_x + 16, y=-3) self.r_ratio = Label(self, font=(MS_JH, 9)) self.r_ratio.place(x=basic_x + 26, y=13) # 清空進行篩選的條件 button = Button(self, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=658, y=-1) button["command"] = self.clearing_filter def update_table(self): results = self.filter_manager.filter(self.records) self.table_model.set_rows( [result.get_table_view_info() for result in results]) self.table_model.setSortOrder(columnName='Order', reverse=1) self.redisplay_table() self.table_view.resizeColumn(0, 55) # DrawOrder self.table_view.resizeColumn(1, 178) # Event self.table_view.resizeColumn(4, 120) # Character # 就篩選結果更新統計資料 self._update_statistic_by_specific_results(results) def _update_statistic_by_specific_results(self, results): # doing statistic: total, ssr, sr, r statistic = [0, 0, 0, 0] for record in results: record.take_statistic(statistic) # 特殊情況,顯示為 0 並結束 if statistic[0] == 0: self.total_count["text"] = 0 self.ssr_count["text"] = 0 self.ssr_ratio["text"] = 0 self.sr_count["text"] = 0 self.sr_ratio["text"] = 0 self.r_count["text"] = 0 self.r_ratio["text"] = 0 return self.total_count["text"] = '%3d' % statistic[0] self.ssr_count["text"] = statistic[1] self.ssr_ratio["text"] = self.convert_to_ratio(statistic[0], statistic[1]) self.sr_count["text"] = statistic[2] self.sr_ratio["text"] = self.convert_to_ratio(statistic[0], statistic[2]) self.r_count["text"] = statistic[3] self.r_ratio["text"] = self.convert_to_ratio(statistic[0], statistic[3]) @staticmethod def convert_to_ratio(total, numerator): ratio = round(100.0 * numerator / total, 1) return str(ratio) + '%' def clearing_filter(self): self.event_filter.set(None) self.cost_filter.set('') self.rank_filter.set('') self.filter_manager.clean_specific_condition() self.update_table() def adding_record(self, limitation=True): open_adding_new_record_window( self, DrawLotsModel.get_suitable_events(self.events, limitation), lambda record: (self.records.append(record), self.update_table())) def do_double_clicking(self, event): record = self.get_record_by_order( self.table_model.getCellRecord( self.table_view.get_row_clicked(event), 0)) open_updating_record_window(self, record, self.events, callback=self.update_table) def do_dragging_along_right(self, row_number): record = self.get_record_by_order( self.table_model.getCellRecord(row_number, 0)) delete_record_with_conforming( self, record, lambda: (self.records.remove(record), self.update_table())) # 直接從 list 中拿掉,不用重撈) def get_record_by_order(self, order): for each_record in self.records: if each_record.order == order: return each_record # 更改角色資訊 def opening_character_update_window(self, event): self.table_view.handle_left_click(event) character = self.get_record_by_order( self.table_model.getCellRecord( self.table_view.get_row_clicked(event), 0)).character open_updating_character_window(self, character, lambda: None)
class CharacterWeaponFrame(MainFrameWithTable): def __init__(self, master, **kwargs): MainFrameWithTable.__init__(self, master, **kwargs) # 滑鼠中鍵事件註冊,設定為更改角色詳細資訊,並選取該列 self.table_view.bind( "<Button-2>", lambda event: self.opening_character_update_window(event)) self.set_table_place(6, 31) self.filter_manager = FilterRuleManager() self.table_model = TableModelAdvance() self.table_model.set_columns(CharacterWeapon.TABLE_VIEW_COLUMNS) self.table_view.setModel(self.table_model) self.characters = CharacterWeaponModel.select_character_weapon_list() self._init_upper_frame() self.update_table() def _init_upper_frame(self): self.insufficiently = ToggleButton(self, text='Insufficiently', width=14, font=(SCP, 8), relief=RIDGE) self.insufficiently.bind( '<Button-1>', lambda event: (self.filter_manager.set_specific_condition( 'unforged', 0 if self.insufficiently.is_selected else CONDITIONLESS, rule=not_match_request), self.update_table()), add='+') self.insufficiently.place(x=380, y=3) Label(self, text='Type:', width=5, font=(MS_JH, 11)).place(x=510, y=3) self.type_selector = FilteredCombobox(self, width=4, font=(MS_JH, 9), justify=CENTER, state='readonly') self.type_selector['values'] = WEAPONS self.type_selector.place(x=558, y=5) self.type_selector.bind( '<<ComboboxSelected>>', lambda event: (self.filter_manager.set_specific_condition( 'weapon_type', self.type_selector.get()), self.update_table())) button = Button(self, text='新增', width=8, font=(MS_JH, 10)) button.place(x=640, y=1) button["command"] = lambda: open_adding_new_character_weapon_window( self, callback=lambda cw: (self.characters.append(cw), self.update_table())) def update_table(self): results = self.filter_manager.filter(self.characters) self.table_model.set_rows( [result.get_table_view_info() for result in results]) self.table_model.setSortOrder(columnName='Left', reverse=1) self.redisplay_table() # 更改角色資訊 def opening_character_update_window(self, event): self.table_view.handle_left_click(event) character = self.get_corresponding_character_weapon_in_row( self.table_view.get_row_clicked(event)).character open_updating_character_window(self, character, lambda: None) # 編輯武器狀態 def do_double_clicking(self, event): character_weapon = self.get_corresponding_character_weapon_in_row( self.table_view.get_row_clicked(event)) open_updating_character_weapon_window(self, character_weapon, self.update_table) def do_dragging_along_right(self, row_number): character = self.get_corresponding_character_weapon_in_row(row_number) delete_character_weapon_with_conforming( self, character, lambda: (self.characters.remove( character), self.update_table())) # 直接從 list 中拿掉,不用重撈 def get_corresponding_character_weapon_in_row(self, row_number): selected_name = self.table_model.getCellRecord(row_number, 0) for character in self.characters: if character.nickname.encode('utf-8') == selected_name: return character
def _init_filter_frame(self): basic_x = 20 Label(self, text='E:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.event_filter = FilteredObjectCombobox( self, setter=lambda obj: obj.name, getter=lambda obj: obj.e_id, width=16, justify=CENTER) self.event_filter.set_objects(self.events) self.event_filter.place(x=basic_x + 18, y=3) self.event_filter.bind('<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'event_id', self.event_filter.get()), self.update_table()), add='+') self.event_filter.bind('<Button-2>', lambda event: (open_updating_event_window( self, self.event_filter.selected_object, lambda: self.event_filter.set_objects(self.events)))) basic_x += 158 Label(self, text='C:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.cost_filter = FilteredCombobox(self, width=6, justify=CENTER) self.cost_filter['values'] = DRAW_LOTS_COST self.cost_filter.place(x=basic_x + 20, y=3) self.cost_filter.bind('<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition('cost', self.cost_filter.get()), self.update_table())) basic_x += 90 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.rank_filter = IntFilteredCombobox(self, width=3, justify=CENTER) self.rank_filter['values'] = [5, 4, 3] self.rank_filter.place(x=basic_x + 20, y=3) self.rank_filter.bind('<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition('rank', self.rank_filter.get()), self.update_table())) basic_x = 342 Label(self, text='Total:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.total_count = Label(self, font=(MS_JH, 12)) self.total_count.place(x=basic_x + 44, y=2) basic_x += 83 Label(self, text='SSR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.ssr_count = Label(self, font=(MS_JH, 10)) self.ssr_count.place(x=basic_x + 34, y=-3) self.ssr_ratio = Label(self, font=(MS_JH, 9)) self.ssr_ratio.place(x=basic_x + 44, y=13) basic_x += 80 Label(self, text='SR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.sr_count = Label(self, font=(MS_JH, 10)) self.sr_count.place(x=basic_x + 25, y=-3) self.sr_ratio = Label(self, font=(MS_JH, 9)) self.sr_ratio.place(x=basic_x + 35, y=13) basic_x += 78 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.r_count = Label(self, font=(MS_JH, 10)) self.r_count.place(x=basic_x + 16, y=-3) self.r_ratio = Label(self, font=(MS_JH, 9)) self.r_ratio.place(x=basic_x + 26, y=13) # 清空進行篩選的條件 button = Button(self, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=658, y=-1) button["command"] = self.clearing_filter
class DrawLotsFrame(MainFrameWithTable): def __init__(self, master, **kwargs): MainFrameWithTable.__init__(self, master, **kwargs) self.set_table_place(34, 29) self.table_model = TableModelAdvance() self.table_model.set_columns(RecordOfDrawLots.TABLE_VIEW_COLUMNS) # 滑鼠中鍵事件註冊,設定為更改角色詳細資訊,並選取該列 self.table_view.bind("<Button-2>", lambda event: self.opening_character_update_window(event)) self.table_view.setModel(self.table_model) self.filter_manager = FilterRuleManager() self.records = DrawLotsModel.select_record_list() self.events = DrawLotsModel.select_event_list() self._init_adding_frame() self._init_filter_frame() self.table.tkraise() # 放上層,避免被其他元件遮到 self.update_table() def _init_adding_frame(self): # 新增酒廠的按鈕 button = Button(self, text="新增酒廠", width=2, height=5, wraplength=1, font=(MS_JH, 11)) button.place(x=7, y=41) button["command"] = lambda: open_adding_event_window(self, lambda event: ( self.events.insert(0, event), self.event_filter.set_objects(self.events))) # 新增記錄的按鈕 button = Button(self, text="新增記錄", width=2, height=12, wraplength=1, font=(MS_JH, 12)) button.place(x=5, y=155) button['command'] = self.adding_record button.bind('<Button-3>', lambda event: self.adding_record(limitation=False)) def _init_filter_frame(self): basic_x = 20 Label(self, text='E:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.event_filter = FilteredObjectCombobox( self, setter=lambda obj: obj.name, getter=lambda obj: obj.e_id, width=16, justify=CENTER) self.event_filter.set_objects(self.events) self.event_filter.place(x=basic_x + 18, y=3) self.event_filter.bind('<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition( 'event_id', self.event_filter.get()), self.update_table()), add='+') self.event_filter.bind('<Button-2>', lambda event: (open_updating_event_window( self, self.event_filter.selected_object, lambda: self.event_filter.set_objects(self.events)))) basic_x += 158 Label(self, text='C:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.cost_filter = FilteredCombobox(self, width=6, justify=CENTER) self.cost_filter['values'] = DRAW_LOTS_COST self.cost_filter.place(x=basic_x + 20, y=3) self.cost_filter.bind('<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition('cost', self.cost_filter.get()), self.update_table())) basic_x += 90 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=3) self.rank_filter = IntFilteredCombobox(self, width=3, justify=CENTER) self.rank_filter['values'] = [5, 4, 3] self.rank_filter.place(x=basic_x + 20, y=3) self.rank_filter.bind('<<ComboboxSelected>>', lambda x: (self.filter_manager.set_specific_condition('rank', self.rank_filter.get()), self.update_table())) basic_x = 342 Label(self, text='Total:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.total_count = Label(self, font=(MS_JH, 12)) self.total_count.place(x=basic_x + 44, y=2) basic_x += 83 Label(self, text='SSR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.ssr_count = Label(self, font=(MS_JH, 10)) self.ssr_count.place(x=basic_x + 34, y=-3) self.ssr_ratio = Label(self, font=(MS_JH, 9)) self.ssr_ratio.place(x=basic_x + 44, y=13) basic_x += 80 Label(self, text='SR:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.sr_count = Label(self, font=(MS_JH, 10)) self.sr_count.place(x=basic_x + 25, y=-3) self.sr_ratio = Label(self, font=(MS_JH, 9)) self.sr_ratio.place(x=basic_x + 35, y=13) basic_x += 78 Label(self, text='R:', font=(MS_JH, 12)).place(x=basic_x, y=2) self.r_count = Label(self, font=(MS_JH, 10)) self.r_count.place(x=basic_x + 16, y=-3) self.r_ratio = Label(self, font=(MS_JH, 9)) self.r_ratio.place(x=basic_x + 26, y=13) # 清空進行篩選的條件 button = Button(self, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=658, y=-1) button["command"] = self.clearing_filter def update_table(self): results = self.filter_manager.filter(self.records) self.table_model.set_rows([result.get_table_view_info() for result in results]) self.table_model.setSortOrder(columnName='Order', reverse=1) self.redisplay_table() self.table_view.resizeColumn(0, 55) # DrawOrder self.table_view.resizeColumn(1, 178) # Event self.table_view.resizeColumn(4, 120) # Character # 就篩選結果更新統計資料 self._update_statistic_by_specific_results(results) def _update_statistic_by_specific_results(self, results): # doing statistic: total, ssr, sr, r statistic = [0, 0, 0, 0] for record in results: record.take_statistic(statistic) # 特殊情況,顯示為 0 並結束 if statistic[0] == 0: self.total_count["text"] = 0 self.ssr_count["text"] = 0 self.ssr_ratio["text"] = 0 self.sr_count["text"] = 0 self.sr_ratio["text"] = 0 self.r_count["text"] = 0 self.r_ratio["text"] = 0 return self.total_count["text"] = '%3d' % statistic[0] self.ssr_count["text"] = statistic[1] self.ssr_ratio["text"] = self.convert_to_ratio(statistic[0], statistic[1]) self.sr_count["text"] = statistic[2] self.sr_ratio["text"] = self.convert_to_ratio(statistic[0], statistic[2]) self.r_count["text"] = statistic[3] self.r_ratio["text"] = self.convert_to_ratio(statistic[0], statistic[3]) @staticmethod def convert_to_ratio(total, numerator): ratio = round(100.0 * numerator / total, 1) return str(ratio) + '%' def clearing_filter(self): self.event_filter.set(None) self.cost_filter.set('') self.rank_filter.set('') self.filter_manager.clean_specific_condition() self.update_table() def adding_record(self, limitation=True): open_adding_new_record_window(self, DrawLotsModel.get_suitable_events(self.events, limitation), lambda record: ( self.records.append(record), self.update_table())) def do_double_clicking(self, event): record = self.get_record_by_order(self.table_model.getCellRecord(self.table_view.get_row_clicked(event), 0)) open_updating_record_window(self, record, self.events, callback=self.update_table) def do_dragging_along_right(self, row_number): record = self.get_record_by_order(self.table_model.getCellRecord(row_number, 0)) delete_record_with_conforming( self, record, lambda: (self.records.remove(record), self.update_table())) # 直接從 list 中拿掉,不用重撈) def get_record_by_order(self, order): for each_record in self.records: if each_record.order == order: return each_record # 更改角色資訊 def opening_character_update_window(self, event): self.table_view.handle_left_click(event) character = self.get_record_by_order( self.table_model.getCellRecord(self.table_view.get_row_clicked(event), 0)).character open_updating_character_window(self, character, lambda: None)
class CharacterFrame(MainFrameWithTable): def __init__(self, master, **kwargs): MainFrameWithTable.__init__(self, master, **kwargs) self.model = CharacterModel.CharacterFrameModel() self.set_table_place(34, 38) self.table_model = TableModelAdvance() self.table_model.set_columns(Character.TABLE_VIEW_COLUMNS, main_column="Nickname") self.table_view.setModel(self.table_model) self._init_upper_frame() self._init_left_frame() self.model.update_data() self.update_table() def _init_left_frame(self): self.character_count = IntVar() Label(self, textvariable=self.character_count, width=3, font=(SCP, 9, "bold")).place(x=5, y=10) # 新增記錄的按鈕,分別是日、台服 button = Button(self, text="新增日服角色", width=2, height=10, wraplength=1, font=(MS_JH, 12)) button.place(x=4, y=50) button["command"] = lambda: open_adding_new_jp_character_window( self, lambda character: self.callback_after_adding_character(character) ) button = Button(self, text="台服角色", width=2, height=6, wraplength=1, font=(MS_JH, 11)) button.place(x=5, y=280) button["command"] = lambda: open_adding_new_cn_character_window( self, lambda character: self.callback_after_adding_character(character) ) def _init_upper_frame(self): filter_frame = Frame(self, width=self["width"], height=40) filter_frame.place(x=0, y=0) current_x = 45 self.profession_selector = ProfessionSelector(filter_frame, self.updating_profession) self.profession_selector.place(x=current_x, y=-4) current_x += 199 self.rank_selector = RankSelector(filter_frame, self.updating_rank) self.rank_selector.place(x=current_x, y=-4) # 所屬篩選 current_x = 448 Label(filter_frame, text="所屬:", font=(MS_JH, 10)).place(x=current_x + 10, y=-3) self.belonged = FilteredCombobox(filter_frame, width=6, justify=CENTER) self.belonged["values"] = BELONGEDS self.belonged.place(x=current_x, y=16) self.belonged.bind("<<ComboboxSelected>>", lambda event: self.updating_belonged()) # 角色部分名稱篩選 current_x += 75 Label(filter_frame, text="篩選:", font=(MS_JH, 12)).place(x=current_x, y=7) self.request = StringVar() entry = Entry(filter_frame, width=9, textvariable=self.request, font=(MS_JH, 11)) entry.place(x=current_x + 42, y=9) entry.bind("<Return>", lambda event: self.update_table()) # 清空進行篩選的條件 button = Button(filter_frame, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=667, y=3) button["command"] = self.clearing_filters def update_table(self): # 將符合篩選條件的角色加入欲呈現表格中 results = self.model.get_displaying_data(self.request.get()) self.character_count.set(len(results)) self.table_model.set_rows(results) self.table_model.setSortOrder(columnName="Rank", reverse=1) self.table_model.setSortOrder(columnName="Profession") self.redisplay_table() self.table_view.hide_column("ID") def callback_after_adding_character(self, character): self.model.append(character) self.update_table() def updating_profession(self, request): self.model.set_specific_condition("profession", request) self.update_table() def updating_rank(self, request): self.model.set_specific_condition("rank", request, match_requested_rank) self.update_table() def updating_belonged(self): self.model.set_specific_condition("belonged", self.belonged.get()) self.update_table() def clearing_filters(self): self.profession_selector.clean_current_selection() self.rank_selector.clean_current_selection() self.belonged.set("") self.model.clean_specific_condition() self.request.set("") self.update_table() def do_double_clicking(self, event): character = self.get_corresponding_character_in_row(self.table_view.get_row_clicked(event)) open_updating_character_window(self, character, lambda: self.update_table()) # 主要供方便刪除測試或誤加的角色用,未檢查其他 table 中使用到的該角色 def do_dragging_along_right(self, row_number): character = self.get_corresponding_character_in_row(row_number) delete_character_with_conforming( self, character, lambda: (self.model.remove(character), self.update_table()) ) # 直接從 list 中拿掉,不用重撈 def get_corresponding_character_in_row(self, row_number): selected_id = self.table_model.getCellRecord(row_number, 0) return self.model.get_specific_datum("c_id", selected_id)
class CharacterFrame(MainFrameWithTable): def __init__(self, master, **kwargs): MainFrameWithTable.__init__(self, master, **kwargs) self.model = CharacterModel.CharacterFrameModel() self.set_table_place(34, 38) self.table_model = TableModelAdvance() self.table_model.set_columns(Character.TABLE_VIEW_COLUMNS, main_column='Nickname') self.table_view.setModel(self.table_model) self._init_upper_frame() self._init_left_frame() self.model.update_data() self.update_table() def _init_left_frame(self): self.character_count = IntVar() Label(self, textvariable=self.character_count, width=3, font=(SCP, 9, 'bold')).place(x=5, y=10) # 新增記錄的按鈕,分別是日、台服 button = Button(self, text="新增日服角色", width=2, height=10, wraplength=1, font=(MS_JH, 12)) button.place(x=4, y=50) button["command"] = lambda: open_adding_new_jp_character_window( self, lambda character: self.callback_after_adding_character( character)) button = Button(self, text="台服角色", width=2, height=6, wraplength=1, font=(MS_JH, 11)) button.place(x=5, y=280) button["command"] = lambda: open_adding_new_cn_character_window( self, lambda character: self.callback_after_adding_character( character)) def _init_upper_frame(self): filter_frame = Frame(self, width=self['width'], height=40) filter_frame.place(x=0, y=0) current_x = 45 self.profession_selector = ProfessionSelector(filter_frame, self.updating_profession) self.profession_selector.place(x=current_x, y=-4) current_x += 199 self.rank_selector = RankSelector(filter_frame, self.updating_rank) self.rank_selector.place(x=current_x, y=-4) # 所屬篩選 current_x = 448 Label(filter_frame, text='所屬:', font=(MS_JH, 10)).place(x=current_x + 10, y=-3) self.belonged = FilteredCombobox(filter_frame, width=6, justify=CENTER) self.belonged['values'] = BELONGEDS self.belonged.place(x=current_x, y=16) self.belonged.bind('<<ComboboxSelected>>', lambda event: self.updating_belonged()) # 角色部分名稱篩選 current_x += 75 Label(filter_frame, text='篩選:', font=(MS_JH, 12)).place(x=current_x, y=7) self.request = StringVar() entry = Entry(filter_frame, width=9, textvariable=self.request, font=(MS_JH, 11)) entry.place(x=current_x + 42, y=9) entry.bind('<Return>', lambda event: self.update_table()) # 清空進行篩選的條件 button = Button(filter_frame, text="清空條件", width=7, font=(MS_JH, 11)) button.place(x=667, y=3) button["command"] = self.clearing_filters def update_table(self): # 將符合篩選條件的角色加入欲呈現表格中 results = self.model.get_displaying_data(self.request.get()) self.character_count.set(len(results)) self.table_model.set_rows(results) self.table_model.setSortOrder(columnName='Rank', reverse=1) self.table_model.setSortOrder(columnName='Profession') self.redisplay_table() self.table_view.hide_column('ID') def callback_after_adding_character(self, character): self.model.append(character) self.update_table() def updating_profession(self, request): self.model.set_specific_condition('profession', request) self.update_table() def updating_rank(self, request): self.model.set_specific_condition('rank', request, match_requested_rank) self.update_table() def updating_belonged(self): self.model.set_specific_condition('belonged', self.belonged.get()) self.update_table() def clearing_filters(self): self.profession_selector.clean_current_selection() self.rank_selector.clean_current_selection() self.belonged.set('') self.model.clean_specific_condition() self.request.set('') self.update_table() def do_double_clicking(self, event): character = self.get_corresponding_character_in_row( self.table_view.get_row_clicked(event)) open_updating_character_window(self, character, lambda: self.update_table()) # 主要供方便刪除測試或誤加的角色用,未檢查其他 table 中使用到的該角色 def do_dragging_along_right(self, row_number): character = self.get_corresponding_character_in_row(row_number) delete_character_with_conforming( self, character, lambda: (self.model.remove( character), self.update_table())) # 直接從 list 中拿掉,不用重撈 def get_corresponding_character_in_row(self, row_number): selected_id = self.table_model.getCellRecord(row_number, 0) return self.model.get_specific_datum('c_id', selected_id)
class CharacterSelectionWindow(BasicWindow): def __init__(self, master, callback, character_selected, width=422, height=155, **kwargs): BasicWindow.__init__(self, master, width=width, height=height, **kwargs) self.title('Character selection') self.records = None self.update_records() self.filter_manager = FilterRuleManager() self.filter_manager.set_comparison_rule(0) self.filter_manager.set_comparison_rule(1) self._init_widgets() self._init_character_selected(character_selected) self.callback = callback def _init_widgets(self): self.profession_selector = ProfessionSelector(self, self.updating_request_profession) self.profession_selector.place(x=5, y=5) self.rank_selector = RankSelector(self, self.updating_request_rank) self.rank_selector.place(x=5, y=53) Label(self, text='所屬', width=5, font=("", 10)).place(x=221, y=5) self.belonged_selector = FilteredCombobox(self, width=7, font=("", 11), justify=CENTER) self.belonged_selector['values'] = BELONGEDS self.belonged_selector.place(x=213, y=22) self.belonged_selector.bind('<<ComboboxSelected>>', lambda x: self.updating_request_belonged(self.belonged_selector.get())) self.belonged_selector.bind('<Return>', lambda x: self.character_selector.focus_set()) Label(self, text='篩選', width=5, font=("", 11)).place(x=222, y=54) self.name_request = StringVar(value='') entry = Entry(self, width=8, textvariable=self.name_request, font=("", 12)) entry.place(x=214, y=73) entry.bind('<Return>', lambda x: self.updating_request_name()) entry.bind('<Escape>', lambda x: (self.name_request.set(''), self.updating_request_name())) Label(self, text='Character', width=10, font=("", 12)).place(x=304, y=26) self.character_selector = ttk.Combobox(self, state='readonly', width=10, font=("", 12), justify=CENTER) self.character_selector.place(x=305, y=48) self.character_selector.bind('<Return>', lambda x: self.submitting()) # 熱鍵,直接指過來 self.bind('<f>', lambda x: self.character_selector.focus_set()) y_position = 115 # 送交的按鈕 button = Button(self, text="選擇此角色", width=25, borderwidth=3) button.place(x=17, y=y_position) button["command"] = self.submitting # 新增角色的按鈕 button = Button(self, text="新增角色", width=9, borderwidth=3) button.place(x=225, y=y_position) button["command"] = lambda: open_adding_new_jp_character_window( self, lambda new_character: (self.update_records(), self.updating_character_selector())) # 取消並結束的按鈕 button = Button(self, text="放棄選擇", width=9, borderwidth=3) button.place(x=317, y=y_position) button["command"] = self.destroy def _init_character_selected(self, character_selected): if character_selected is None: pass elif isinstance(character_selected, Character): self.profession_selector.select(character_selected.profession) self.rank_selector.select(character_selected.rank) self.updating_character_selector() self.character_selector.set(character_selected.nickname) else: raise TypeError('In CharacterSelectionWindow, arg: \"character_selected\"') def updating_request_profession(self, profession): self.filter_manager.set_specific_condition(2, profession) self.updating_character_selector() self.character_selector.focus_set() def updating_request_rank(self, rank): self.filter_manager.set_specific_condition(3, rank, match_requested_rank) self.updating_character_selector() self.character_selector.focus_set() def updating_request_belonged(self, belonged): self.filter_manager.set_specific_condition(4, belonged) self.updating_character_selector() def updating_request_name(self): self.updating_character_selector() self.character_selector.focus_set() # 清除原本的選擇,並更新可選擇的角色 def updating_character_selector(self): self.character_selector.set('') character_matched = [] for character_infos in self.filter_manager.filter(self.records, self.name_request.get()): character_matched.append(character_infos[0]) self.character_selector['values'] = character_matched # 有選擇的情況下才回傳,否則彈出錯誤視窗 def submitting(self): if self.character_selector.get() != '': self.callback(CharacterModel.select_character_by_specific_column('Nickname', self.character_selector.get())) self.destroy() else: tkMessageBox.showwarning("Character haven't selected", '\"Character\" 未選\n', parent=self) def update_records(self): self.records = CharacterModel.select_character_info_for_character_selector()
class CharacterWeaponFrame(MainFrameWithTable): def __init__(self, master, **kwargs): MainFrameWithTable.__init__(self, master, **kwargs) # 滑鼠中鍵事件註冊,設定為更改角色詳細資訊,並選取該列 self.table_view.bind("<Button-2>", lambda event: self.opening_character_update_window(event)) self.set_table_place(6, 31) self.filter_manager = FilterRuleManager() self.table_model = TableModelAdvance() self.table_model.set_columns(CharacterWeapon.TABLE_VIEW_COLUMNS) self.table_view.setModel(self.table_model) self.characters = CharacterWeaponModel.select_character_weapon_list() self._init_upper_frame() self.update_table() def _init_upper_frame(self): self.insufficiently = ToggleButton(self, text='Insufficiently', width=14, font=(SCP, 8), relief=RIDGE) self.insufficiently.bind('<Button-1>', lambda event: ( self.filter_manager.set_specific_condition( 'unforged', 0 if self.insufficiently.is_selected else CONDITIONLESS, rule=not_match_request), self.update_table()), add='+') self.insufficiently.place(x=380, y=3) Label(self, text='Type:', width=5, font=(MS_JH, 11)).place(x=510, y=3) self.type_selector = FilteredCombobox(self, width=4, font=(MS_JH, 9), justify=CENTER, state='readonly') self.type_selector['values'] = WEAPONS self.type_selector.place(x=558, y=5) self.type_selector.bind('<<ComboboxSelected>>', lambda event: ( self.filter_manager.set_specific_condition('weapon_type', self.type_selector.get()), self.update_table())) button = Button(self, text='新增', width=8, font=(MS_JH, 10)) button.place(x=640, y=1) button["command"] = lambda: open_adding_new_character_weapon_window( self, callback=lambda cw: (self.characters.append(cw), self.update_table())) def update_table(self): results = self.filter_manager.filter(self.characters) self.table_model.set_rows([result.get_table_view_info() for result in results]) self.table_model.setSortOrder(columnName='Left', reverse=1) self.redisplay_table() # 更改角色資訊 def opening_character_update_window(self, event): self.table_view.handle_left_click(event) character = self.get_corresponding_character_weapon_in_row(self.table_view.get_row_clicked(event)).character open_updating_character_window(self, character, lambda: None) # 編輯武器狀態 def do_double_clicking(self, event): character_weapon = self.get_corresponding_character_weapon_in_row(self.table_view.get_row_clicked(event)) open_updating_character_weapon_window(self, character_weapon, self.update_table) def do_dragging_along_right(self, row_number): character = self.get_corresponding_character_weapon_in_row(row_number) delete_character_weapon_with_conforming(self, character, lambda: ( self.characters.remove(character), self.update_table())) # 直接從 list 中拿掉,不用重撈 def get_corresponding_character_weapon_in_row(self, row_number): selected_name = self.table_model.getCellRecord(row_number, 0) for character in self.characters: if character.nickname.encode('utf-8') == selected_name: return character