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
class SpecificStageDroppedCanvas(Canvas): KEY_TITLE = 'title' KEY_TOTAL = 'total' KEY_DROPS = "drops" KEY_VALUES = "values" KEY_DEFAULTS = "defaults" def __init__(self, master, section, **kwargs): Canvas.__init__(self, master, **kwargs) self.title = StringVar() self.section = section self._init_frame() self._init_fields() def _init_frame(self): Label(self, textvariable=self.title, width=13, font=(MS_JH, 14)).place(x=12, y=5) self.box_1_button = ToggleButton(self, text='1st', width=3, font=(SCP, 11), relief=RIDGE) self.box_1_button.place(x=5 + 43 * 0, y=39) self.box_2_button = ToggleButton(self, text='2nd', width=3, font=(SCP, 11), relief=RIDGE) self.box_2_button.place(x=5 + 43 * 1, y=39) self.box_3_button = ToggleButton(self, text='3rd', width=3, font=(SCP, 11), relief=RIDGE) self.box_3_button.place(x=5 + 43 * 2, y=39) self.box_4_button = ToggleButton(self, text='4th', width=3, font=(SCP, 11), relief=RIDGE) self.box_4_button.place(x=5 + 43 * 3, y=39) submit_button = Button(self, text='Submit', width=17, font=(SCP, 11), relief=RIDGE) submit_button.place(x=5, y=76) submit_button.bind('<Button-1>', lambda event: self.submitting()) current_y = 114 self.total_desc = StringVar() Label(self, textvariable=self.total_desc, width=16, font=(SCP, 11)).place(x=13, y=current_y) current_y += 28 self.drop_vars = [IntVar(), IntVar(), IntVar(), IntVar()] for i in range(4): Label(self, textvariable=self.drop_vars[i], width=3, font=(SCP, 11), relief=GROOVE). \ place(x=6 + 43 * i, y=current_y) current_y += 29 self.values_desc = StringVar() Label(self, textvariable=self.values_desc, width=16, font=(SCP, 11)).place(x=13, y=current_y) def _init_fields(self): data_record = get_data_record(self.section) self.title.set(data_record[self.KEY_TITLE]) self.statistic_tacker = DroppedStatisticTacker(4) self.statistic_tacker.set(data_record[self.KEY_TOTAL], data_record[self.KEY_DROPS]) self.values = data_record[self.KEY_VALUES] self._init_buttons_state(data_record[self.KEY_DEFAULTS]) self._update_statistics() def _update_statistics(self): from itertools import izip self.total_desc.set('Times : %2d ' % self.statistic_tacker.times) for i in range(4): self.drop_vars[i].set(self.statistic_tacker.drops[i]) self.values_desc.set('Value : %1.2f' % (sum(p * q for p, q in izip( self.values, self.statistic_tacker.get_statistics_ratio())) / 100)) def _init_buttons_state(self, defaults): self.box_1_button.set_is_selected(defaults[0]) self.box_2_button.set_is_selected(defaults[1]) self.box_3_button.set_is_selected(defaults[2]) self.box_4_button.set_is_selected(defaults[3]) def submitting(self): self.statistic_tacker.record([self.box_1_button.is_selected, self.box_2_button.is_selected, self.box_3_button.is_selected, self.box_4_button.is_selected]) data_record = get_data_record(self.section) data_record[self.KEY_TOTAL] = self.statistic_tacker.times data_record[self.KEY_DROPS] = self.statistic_tacker.drops save_data_record() self._init_buttons_state(data_record[self.KEY_DEFAULTS]) self._update_statistics()
class CharacterPowerWindow(BasicWindow): def __init__(self, master, character_power, callback, width=558, height=222, **kwargs): BasicWindow.__init__(self, master, width=width, height=height, **kwargs) self.title("CharacterPower") self.character_power = character_power self.callback = callback self._init_widget() self._init_content() # 事件註冊,設定為更改角色詳細資訊 self.bind("-", lambda event: self.open_updating_character_window()) def _init_widget(self): current_y_diff = 28 current_y = 20 current_x = 23 self.character_selector = CharacterSelectorCanvas(self, self.character_power.character) self.character_selector.place(x=current_x, y=current_y - 3) callback_after_selection = lambda event: (self.filling_in_entries_by_character(), level_entry.focus_set()) self.character_selector.bind("<Return>", callback_after_selection) self.character_selector.bind("-", callback_after_selection) current_x += 145 Label(self, width=5, text="Level", font=(SCP, 12)).place(x=current_x, y=current_y) self.level = StringVar() level_entry = Entry(self, width=5, textvariable=self.level, font=(SCP, 12), justify=CENTER) level_entry.place(x=current_x + 2, y=current_y + current_y_diff) level_entry.bind("<Return>", lambda x: (self.filling_in_atk_by_level(), atk_entry.focus_set())) current_x += 62 Label(self, width=5, text="Atk", font=(SCP, 12)).place(x=current_x, y=current_y) self.atk = StringVar() atk_entry = Entry(self, width=5, textvariable=self.atk, font=(SCP, 12), justify=CENTER) atk_entry.place(x=current_x + 3, y=current_y + current_y_diff) atk_entry.bind("<Return>", lambda x: active_factor_entry.focus_set()) current_x += 70 Label(self, width=25, text="Addition", font=(SCP, 12)).place(x=current_x, y=current_y) self.addition = StringVar() addition_entry = Entry(self, width=25, textvariable=self.addition, font=(MS_JH, 12), justify=CENTER) addition_entry.place(x=current_x + 3, y=current_y + current_y_diff) addition_entry.bind("<Return>", lambda x: self.presently.focus_set()) current_y += 14 + current_y_diff * 2 current_x = 27 Label(self, width=8, text="AtkRaised", font=(SCP, 10)).place(x=current_x + 1, y=current_y + 3) self.atk_raised = StringVar() atk_raised_entry = Entry(self, width=7, textvariable=self.atk_raised, font=(SCP, 12), justify=CENTER) atk_raised_entry.place(x=current_x, y=current_y + current_y_diff) atk_raised_entry.bind("<Return>", lambda x: active_factor_entry.focus_set()) current_x += 90 Label(self, width=7, text="HitRate", font=(SCP, 11)).place(x=current_x, y=current_y) self.hit_rate = StringVar() hit_rate_entry = Entry(self, width=6, textvariable=self.hit_rate, font=(SCP, 12), justify=CENTER) hit_rate_entry.place(x=current_x + 2, y=current_y + current_y_diff) hit_rate_entry.bind("<Return>", lambda x: active_factor_entry.focus_set()) current_x += 83 Label(self, width=8, text="Cri.Ratio", font=(SCP, 10)).place(x=current_x, y=current_y + 3) self.critical_ratio = StringVar() critical_ratio_entry = Entry(self, width=6, textvariable=self.critical_ratio, font=(SCP, 12), justify=CENTER) critical_ratio_entry.place(x=current_x + 3, y=current_y + current_y_diff) critical_ratio_entry.bind("<Return>", lambda x: active_factor_entry.focus_set()) current_x += 85 Label(self, width=9, text="Cri.Factor", font=(SCP, 9)).place(x=current_x, y=current_y + 4) self.critical_factor = StringVar() critical_factor_entry = Entry(self, width=6, textvariable=self.critical_factor, font=(SCP, 12), justify=CENTER) critical_factor_entry.place(x=current_x + 3, y=current_y + current_y_diff) critical_factor_entry.bind("<Return>", lambda x: active_factor_entry.focus_set()) current_x += 84 Label(self, width=9, text="Act.Factor", font=(SCP, 9)).place(x=current_x, y=current_y + 4) self.active_factor = StringVar() active_factor_entry = Entry(self, width=6, textvariable=self.active_factor, font=(SCP, 12), justify=CENTER) active_factor_entry.place(x=current_x + 4, y=current_y + current_y_diff) active_factor_entry.bind("<Return>", lambda x: addition_entry.focus_set()) current_x += 86 Label(self, width=8, text="Act.Cost", font=(SCP, 11)).place(x=current_x, y=current_y + 3) self.active_cost = StringVar() active_cost_entry = Entry(self, width=6, textvariable=self.active_cost, font=(SCP, 12), justify=CENTER) active_cost_entry.place(x=current_x + 5, y=current_y + current_y_diff) active_cost_entry.bind("<Return>", lambda x: addition_entry.focus_set()) # 送出、取消的按鈕 current_y += 23 + current_y_diff * 2 self.presently = ToggleButton(self, text="Presently", width=9, font=(SCP, 11), relief=RIDGE) self.presently.place(x=22, y=current_y) self.presently.bind("<space>", lambda event: self.presently.toggling()) self.presently.bind("<Return>", lambda x: self.submitting()) Button(self, text="Submit", command=self.submitting, width=28, relief=RIDGE, font=(SCP, 11)).place( x=131, y=current_y ) Button(self, text="Cancel", command=self.destroy, width=13, relief=RIDGE, font=(SCP, 11)).place( x=405, y=current_y ) def _init_content(self): self.atk.set(self.character_power.atk) self.level.set(self.character_power.level) self.atk_raised.set(self.character_power.atk_raised) self.hit_rate.set(self.character_power.hit_rate) self.critical_ratio.set(self.character_power.critical_ratio) self.critical_factor.set(self.character_power.critical_factor) self.active_factor.set(self.character_power.active_factor) self.active_cost.set(self.character_power.active_cost) self.addition.set(self.character_power.addition) self.presently.set_is_selected(self.character_power.presently) def submitting(self): self.character_power.character = self.character_selector.get() self.character_power.atk = int(self.atk.get()) self.character_power.level = int(self.level.get()) self.character_power.atk_raised = float(self.atk_raised.get()) self.character_power.hit_rate = float(self.hit_rate.get()) self.character_power.critical_ratio = float(self.critical_ratio.get()) self.character_power.critical_factor = float(self.critical_factor.get()) self.character_power.active_factor = float(self.active_factor.get()) self.character_power.active_cost = int(self.active_cost.get()) self.character_power.addition = self.addition.get() self.character_power.presently = self.presently.is_selected self.callback() self.destroy() def filling_in_entries_by_character(self): character = self.character_selector.get() self.atk_raised.set(1.0) self.hit_rate.set(character.atk_speed) self.critical_ratio.set(character.critical_rate) self.critical_factor.set(1.5) self.active_cost.set(character.active_cost) def filling_in_atk_by_level(self): atk = self.character_selector.get().estimate_atk_by_level(int(self.level.get())) if atk: self.atk.set(atk) def open_updating_character_window(self): open_updating_character_window(self.master, self.character_selector.get(), position_y_shift=-300)
class FriendInfoFrame(MainFrameWithTable): def __init__(self, master): MainFrameWithTable.__init__(self, master) self.model = FriendModel.FriendInfoModel() self.set_table_place(34, 29) self.table_model = TableModelAdvance() self.table_model.set_columns(FriendInfo.TABLE_VIEW_COLUMNS, main_column='UsedNames') self.table_view.setModel(self.table_model) # 滑鼠中鍵事件註冊,若為設定為更新好友資訊,並選取該列 self.table_view.bind( "<Button-2>", lambda event: (self.table_view.handle_left_click(event), open_updating_friend_info_window( self, self.get_corresponding_friend_info_in_row( self.table_view.get_row_clicked(event)), self.update_table ))) self._init_left_frame() self._init_upper_frame() self.model.update_data() self.update_all() def _init_upper_frame(self): basic_y = 3 basic_x = 52 button = Button(self, text="新增好友", width=8, font=(MS_JH, 11)) button.place(x=basic_x, y=-1) button["command"] = self.adding_new_friend basic_x = 153 Label(self, text='Order:', font=(MS_JH, 12)).place(x=basic_x, y=basic_y) self.order_selector = ttk.Combobox(self, state='readonly', width=10, justify=CENTER) self.order_selector.set(FriendInfo.TABLE_VIEW_SORTABLE_COLUMNS[0]) self.order_selector['values'] = FriendInfo.TABLE_VIEW_SORTABLE_COLUMNS self.order_selector.place(x=basic_x + 55, y=basic_y + 1) self.order_selector.bind( '<<ComboboxSelected>>', lambda x: self.redisplay_table_by_order_rule()) # 角色部分名稱篩選 basic_x = 322 Label(self, text='篩選:', font=(MS_JH, 12)).place(x=basic_x, y=basic_y) self.queried_name = StringVar() entry = Entry(self, width=8, textvariable=self.queried_name, font=(MS_JH, 11)) entry.place(x=basic_x + 42, y=basic_y + 2) entry.bind('<Return>', lambda x: self.update_table()) basic_x = 460 self.friend_count_var = StringVar() Label(self, textvariable=self.friend_count_var, font=(MS_JH, 12)).place(x=basic_x + 17, y=basic_y) basic_x = 565 since_last_record = 'Since: {0} days ago'.format( FriendModel.get_since_all_record_date()) Label(self, text=since_last_record, font=(MS_JH, 12)).place(x=basic_x + 17, y=basic_y) def _init_left_frame(self): button = Button(self, text="記錄好友現況", width=2, height=12, wraplength=1, font=(MS_JH, 12)) button.place(x=4, y=40) button["command"] = self.switching_to_friend_record self.friend_existent_mode_button = \ ToggleButton(self, text="好友整理", width=2, height=5, wraplength=1, font=(MS_JH, 11)) self.friend_existent_mode_button.place(x=5, y=304) self.friend_existent_mode_button[ "command"] = self.switching_friend_existent_mode def update_all(self): self.update_friend_count_var() self.update_table() def update_table(self): # 將符合名稱篩選的好友加入欲呈現表格中 self.table_model.set_rows( self.model.get_displaying_data(self.queried_name.get())) self.redisplay_table_by_order_rule() def redisplay_table_by_order_rule(self): # 先根據目前的選擇設定排序方法 self.table_model.setSortOrder(columnName=self.order_selector.get()) self.redisplay_table() self.table_view.hide_column('ID') self.table_view.hide_column('LastProfession') # 不限制會太寬,難以瀏覽全部資訊 self.table_view.resizeColumn(1, 125) # UsedNames self.table_view.resizeColumn(2, 90) # Excellence self.table_view.resizeColumn(3, 75) # Defect self.table_view.resizeColumn(4, 85) # Relation self.table_view.resizeColumn(5, 70) # Offline self.table_view.resizeColumn(6, 155) # UsedCharacters def switching_to_friend_record(self): self.master.change_main_frame(FriendRecordFrame(self.master)) def switching_friend_existent_mode(self): if self.friend_existent_mode_button.is_selected: pass else: self.model.clear_existed_ids() self.update_table() def update_friend_count_var(self): self.friend_count_var.set('Friends: %02d' % self.model.get_friend_number()) # 好友總數 # 取得未使用的 ID,並將新好友指定到該 ID def adding_new_friend(self): self.model.try_adding_new_friend( lambda info, callback: open_updating_friend_info_window( self, info, lambda: (callback(), self.update_all())), lambda: tkMessageBox.showwarning( "Can not add any friend", '已達好友上限', parent=self)) # 記錄該好友存在,或更改好友資訊,或顯示其歷史角色訊息 def do_double_clicking(self, event): friend_info = self.get_corresponding_friend_info_in_row( self.table_view.get_row_clicked(event)) if self.friend_existent_mode_button.is_selected: self.model.set_friend_existed(friend_info) self.queried_name.set('') # 此時的篩選應是為了找此人,故處理後清空條件 self.update_table() else: # 雙擊歷史角色欄位時顯示其訊息,否則更改好友資訊 if self.table_view.get_col_clicked(event) == 6: tkMessageBox.showinfo("Characters", friend_info.used_characters, parent=self) else: open_updating_friend_info_window(self, friend_info, self.update_table) def do_dragging_along_right(self, row_number): friend_info = self.get_corresponding_friend_info_in_row(row_number) delete_friend_with_conforming( self, friend_info, lambda: (self.callback_after_deleting_friend(friend_info))) def callback_after_deleting_friend(self, friend_info): self.model.remove(friend_info) # 直接從 list 中拿掉,不用重撈 self.update_friend_count_var() self.queried_name.set('') # 此時的篩選應是為了找此人,故處理後清空條件 self.update_table() def get_corresponding_friend_info_in_row(self, row_number): selected_id = self.table_model.getCellRecord(row_number, 0) return self.model.get_specific_datum('f_id', selected_id)
class MonthlyDroppedCanvas(Canvas): KEY_TOTAL = 'total' KEY_FERTILIZER = 'fertilizer' KEY_CHARACTER = 'character' def __init__(self, master, section, **kwargs): Canvas.__init__(self, master, **kwargs) self.title = StringVar() self.section = section self._init_frame() self._init_fields() def _init_frame(self): Label(self, textvariable=self.title, width=8, font=(MS_JH, 14)).place(x=43, y=5) self.box_12_button = ToggleButton(self, text='1&2', width=4, font=(SCP, 11), relief=RIDGE) self.box_12_button.place(x=18 + 51 * 0, y=39) self.box_3_button = ToggleButton(self, text='3', width=4, font=(SCP, 11), relief=RIDGE) self.box_3_button.place(x=18 + 51 * 1, y=39) self.box_4_button = ToggleButton(self, text='4', width=4, font=(SCP, 11), relief=RIDGE) self.box_4_button.place(x=18 + 51 * 2, y=39) submit_button = Button(self, text='Submit', width=15, font=(SCP, 11), relief=RIDGE) submit_button.place(x=20, y=76) submit_button.bind('<Button-1>', lambda event: self.submitting()) label_x = 12 var_x = label_x + 98 current_y = 114 Label(self, text=' Times :', width=12, font=(SCP, 10)).place(x=label_x, y=current_y) Label(self, text='Fertilizer:', width=12, font=(SCP, 10)).place(x=label_x, y=current_y + 20) self.times_var = StringVar() self.fertilizer_var = StringVar() Label(self, textvariable=self.times_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y) Label(self, textvariable=self.fertilizer_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y + 20) current_y += 45 Label(self, text=' Avg.Fer. :', width=12, font=(SCP, 10)).place(x=label_x, y=current_y) Label(self, text='Character :', width=12, font=(SCP, 10)).place(x=label_x, y=current_y + 20) self.avg_fertilizer_var = StringVar() self.character_var = StringVar() Label(self, textvariable=self.avg_fertilizer_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y) Label(self, textvariable=self.character_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y + 20) self._init_buttons_state() def _init_fields(self): data_record = get_data_record(self.section) self.title.set(data_record['title']) self.statistic_tacker = DroppedStatisticTacker(2) self.statistic_tacker.set(data_record[self.KEY_TOTAL], [data_record[self.KEY_FERTILIZER], data_record[self.KEY_CHARACTER]]) self._update_statistics() def _update_statistics(self): self.times_var.set(self.statistic_tacker.times) self.fertilizer_var.set(self.statistic_tacker.drops[0]) avg_count = self.statistic_tacker.get_statistics_count() self.avg_fertilizer_var.set('%.2f' % (avg_count[0])) self.character_var.set(' %.1f %%' % ((avg_count[1]) * 100)) def _init_buttons_state(self): self.box_12_button.set_is_selected(True) self.box_3_button.set_is_selected(False) self.box_4_button.set_is_selected(False) def submitting(self): self.statistic_tacker.record([int(self.box_12_button.is_selected) * 2 + self.box_3_button.is_selected, self.box_4_button.is_selected]) data_record = get_data_record(self.section) data_record[self.KEY_TOTAL] = self.statistic_tacker.times data_record[self.KEY_FERTILIZER] = self.statistic_tacker.drops[0] data_record[self.KEY_CHARACTER] = self.statistic_tacker.drops[1] save_data_record() self._init_buttons_state() self._update_statistics()
class FriendInfoFrame(MainFrameWithTable): def __init__(self, master): MainFrameWithTable.__init__(self, master) self.model = FriendModel.FriendInfoModel() self.set_table_place(34, 29) self.table_model = TableModelAdvance() self.table_model.set_columns(FriendInfo.TABLE_VIEW_COLUMNS, main_column='UsedNames') self.table_view.setModel(self.table_model) # 滑鼠中鍵事件註冊,若為設定為更新好友資訊,並選取該列 self.table_view.bind("<Button-2>", lambda event: ( self.table_view.handle_left_click(event), open_updating_friend_info_window( self, self.get_corresponding_friend_info_in_row(self.table_view.get_row_clicked(event)), self.update_table))) self._init_left_frame() self._init_upper_frame() self.model.update_data() self.update_all() def _init_upper_frame(self): basic_y = 3 basic_x = 52 button = Button(self, text="新增好友", width=8, font=(MS_JH, 11)) button.place(x=basic_x, y=-1) button["command"] = self.adding_new_friend basic_x = 153 Label(self, text='Order:', font=(MS_JH, 12)).place(x=basic_x, y=basic_y) self.order_selector = ttk.Combobox(self, state='readonly', width=10, justify=CENTER) self.order_selector.set(FriendInfo.TABLE_VIEW_SORTABLE_COLUMNS[0]) self.order_selector['values'] = FriendInfo.TABLE_VIEW_SORTABLE_COLUMNS self.order_selector.place(x=basic_x + 55, y=basic_y + 1) self.order_selector.bind('<<ComboboxSelected>>', lambda x: self.redisplay_table_by_order_rule()) # 角色部分名稱篩選 basic_x = 322 Label(self, text='篩選:', font=(MS_JH, 12)).place(x=basic_x, y=basic_y) self.queried_name = StringVar() entry = Entry(self, width=8, textvariable=self.queried_name, font=(MS_JH, 11)) entry.place(x=basic_x + 42, y=basic_y + 2) entry.bind('<Return>', lambda x: self.update_table()) basic_x = 460 self.friend_count_var = StringVar() Label(self, textvariable=self.friend_count_var, font=(MS_JH, 12)).place(x=basic_x + 17, y=basic_y) basic_x = 565 since_last_record = 'Since: {0} days ago'.format(FriendModel.get_since_all_record_date()) Label(self, text=since_last_record, font=(MS_JH, 12)).place(x=basic_x + 17, y=basic_y) def _init_left_frame(self): button = Button(self, text="記錄好友現況", width=2, height=12, wraplength=1, font=(MS_JH, 12)) button.place(x=4, y=40) button["command"] = self.switching_to_friend_record self.friend_existent_mode_button = \ ToggleButton(self, text="好友整理", width=2, height=5, wraplength=1, font=(MS_JH, 11)) self.friend_existent_mode_button.place(x=5, y=304) self.friend_existent_mode_button["command"] = self.switching_friend_existent_mode def update_all(self): self.update_friend_count_var() self.update_table() def update_table(self): # 將符合名稱篩選的好友加入欲呈現表格中 self.table_model.set_rows(self.model.get_displaying_data(self.queried_name.get())) self.redisplay_table_by_order_rule() def redisplay_table_by_order_rule(self): # 先根據目前的選擇設定排序方法 self.table_model.setSortOrder(columnName=self.order_selector.get()) self.redisplay_table() self.table_view.hide_column('ID') self.table_view.hide_column('LastProfession') # 不限制會太寬,難以瀏覽全部資訊 self.table_view.resizeColumn(1, 125) # UsedNames self.table_view.resizeColumn(2, 90) # Excellence self.table_view.resizeColumn(3, 75) # Defect self.table_view.resizeColumn(4, 85) # Relation self.table_view.resizeColumn(5, 70) # Offline self.table_view.resizeColumn(6, 155) # UsedCharacters def switching_to_friend_record(self): self.master.change_main_frame(FriendRecordFrame(self.master)) def switching_friend_existent_mode(self): if self.friend_existent_mode_button.is_selected: pass else: self.model.clear_existed_ids() self.update_table() def update_friend_count_var(self): self.friend_count_var.set('Friends: %02d' % self.model.get_friend_number()) # 好友總數 # 取得未使用的 ID,並將新好友指定到該 ID def adding_new_friend(self): self.model.try_adding_new_friend( lambda info, callback: open_updating_friend_info_window( self, info, lambda: (callback(), self.update_all())), lambda: tkMessageBox.showwarning("Can not add any friend", '已達好友上限', parent=self)) # 記錄該好友存在,或更改好友資訊,或顯示其歷史角色訊息 def do_double_clicking(self, event): friend_info = self.get_corresponding_friend_info_in_row(self.table_view.get_row_clicked(event)) if self.friend_existent_mode_button.is_selected: self.model.set_friend_existed(friend_info) self.queried_name.set('') # 此時的篩選應是為了找此人,故處理後清空條件 self.update_table() else: # 雙擊歷史角色欄位時顯示其訊息,否則更改好友資訊 if self.table_view.get_col_clicked(event) == 6: tkMessageBox.showinfo("Characters", friend_info.used_characters, parent=self) else: open_updating_friend_info_window(self, friend_info, self.update_table) def do_dragging_along_right(self, row_number): friend_info = self.get_corresponding_friend_info_in_row(row_number) delete_friend_with_conforming(self, friend_info, lambda: (self.callback_after_deleting_friend(friend_info))) def callback_after_deleting_friend(self, friend_info): self.model.remove(friend_info) # 直接從 list 中拿掉,不用重撈 self.update_friend_count_var() self.queried_name.set('') # 此時的篩選應是為了找此人,故處理後清空條件 self.update_table() def get_corresponding_friend_info_in_row(self, row_number): selected_id = self.table_model.getCellRecord(row_number, 0) return self.model.get_specific_datum('f_id', selected_id)
class CharacterPowerWindow(BasicWindow): def __init__(self, master, character_power, callback, width=558, height=222, **kwargs): BasicWindow.__init__(self, master, width=width, height=height, **kwargs) self.title('CharacterPower') self.character_power = character_power self.callback = callback self._init_widget() self._init_content() # 事件註冊,設定為更改角色詳細資訊 self.bind("-", lambda event: self.open_updating_character_window()) def _init_widget(self): current_y_diff = 28 current_y = 20 current_x = 23 self.character_selector = CharacterSelectorCanvas( self, self.character_power.character) self.character_selector.place(x=current_x, y=current_y - 3) callback_after_selection = lambda event: ( self.filling_in_entries_by_character(), level_entry.focus_set()) self.character_selector.bind('<Return>', callback_after_selection) self.character_selector.bind('-', callback_after_selection) current_x += 145 Label(self, width=5, text='Level', font=(SCP, 12)).place(x=current_x, y=current_y) self.level = StringVar() level_entry = Entry(self, width=5, textvariable=self.level, font=(SCP, 12), justify=CENTER) level_entry.place(x=current_x + 2, y=current_y + current_y_diff) level_entry.bind( '<Return>', lambda x: (self.filling_in_atk_by_level(), atk_entry.focus_set())) current_x += 62 Label(self, width=5, text='Atk', font=(SCP, 12)).place(x=current_x, y=current_y) self.atk = StringVar() atk_entry = Entry(self, width=5, textvariable=self.atk, font=(SCP, 12), justify=CENTER) atk_entry.place(x=current_x + 3, y=current_y + current_y_diff) atk_entry.bind('<Return>', lambda x: active_factor_entry.focus_set()) current_x += 70 Label(self, width=25, text='Addition', font=(SCP, 12)).place(x=current_x, y=current_y) self.addition = StringVar() addition_entry = Entry(self, width=25, textvariable=self.addition, font=(MS_JH, 12), justify=CENTER) addition_entry.place(x=current_x + 3, y=current_y + current_y_diff) addition_entry.bind('<Return>', lambda x: self.presently.focus_set()) current_y += 14 + current_y_diff * 2 current_x = 27 Label(self, width=8, text='AtkRaised', font=(SCP, 10)).place(x=current_x + 1, y=current_y + 3) self.atk_raised = StringVar() atk_raised_entry = Entry(self, width=7, textvariable=self.atk_raised, font=(SCP, 12), justify=CENTER) atk_raised_entry.place(x=current_x, y=current_y + current_y_diff) atk_raised_entry.bind('<Return>', lambda x: active_factor_entry.focus_set()) current_x += 90 Label(self, width=7, text='HitRate', font=(SCP, 11)).place(x=current_x, y=current_y) self.hit_rate = StringVar() hit_rate_entry = Entry(self, width=6, textvariable=self.hit_rate, font=(SCP, 12), justify=CENTER) hit_rate_entry.place(x=current_x + 2, y=current_y + current_y_diff) hit_rate_entry.bind('<Return>', lambda x: active_factor_entry.focus_set()) current_x += 83 Label(self, width=8, text='Cri.Ratio', font=(SCP, 10)).place(x=current_x, y=current_y + 3) self.critical_ratio = StringVar() critical_ratio_entry = Entry(self, width=6, textvariable=self.critical_ratio, font=(SCP, 12), justify=CENTER) critical_ratio_entry.place(x=current_x + 3, y=current_y + current_y_diff) critical_ratio_entry.bind('<Return>', lambda x: active_factor_entry.focus_set()) current_x += 85 Label(self, width=9, text='Cri.Factor', font=(SCP, 9)).place(x=current_x, y=current_y + 4) self.critical_factor = StringVar() critical_factor_entry = Entry(self, width=6, textvariable=self.critical_factor, font=(SCP, 12), justify=CENTER) critical_factor_entry.place(x=current_x + 3, y=current_y + current_y_diff) critical_factor_entry.bind('<Return>', lambda x: active_factor_entry.focus_set()) current_x += 84 Label(self, width=9, text='Act.Factor', font=(SCP, 9)).place(x=current_x, y=current_y + 4) self.active_factor = StringVar() active_factor_entry = Entry(self, width=6, textvariable=self.active_factor, font=(SCP, 12), justify=CENTER) active_factor_entry.place(x=current_x + 4, y=current_y + current_y_diff) active_factor_entry.bind('<Return>', lambda x: addition_entry.focus_set()) current_x += 86 Label(self, width=8, text='Act.Cost', font=(SCP, 11)).place(x=current_x, y=current_y + 3) self.active_cost = StringVar() active_cost_entry = Entry(self, width=6, textvariable=self.active_cost, font=(SCP, 12), justify=CENTER) active_cost_entry.place(x=current_x + 5, y=current_y + current_y_diff) active_cost_entry.bind('<Return>', lambda x: addition_entry.focus_set()) # 送出、取消的按鈕 current_y += 23 + current_y_diff * 2 self.presently = ToggleButton(self, text='Presently', width=9, font=(SCP, 11), relief=RIDGE) self.presently.place(x=22, y=current_y) self.presently.bind('<space>', lambda event: self.presently.toggling()) self.presently.bind('<Return>', lambda x: self.submitting()) Button(self, text="Submit", command=self.submitting, width=28, relief=RIDGE, font=(SCP, 11)).place(x=131, y=current_y) Button(self, text="Cancel", command=self.destroy, width=13, relief=RIDGE, font=(SCP, 11)).place(x=405, y=current_y) def _init_content(self): self.atk.set(self.character_power.atk) self.level.set(self.character_power.level) self.atk_raised.set(self.character_power.atk_raised) self.hit_rate.set(self.character_power.hit_rate) self.critical_ratio.set(self.character_power.critical_ratio) self.critical_factor.set(self.character_power.critical_factor) self.active_factor.set(self.character_power.active_factor) self.active_cost.set(self.character_power.active_cost) self.addition.set(self.character_power.addition) self.presently.set_is_selected(self.character_power.presently) def submitting(self): self.character_power.character = self.character_selector.get() self.character_power.atk = int(self.atk.get()) self.character_power.level = int(self.level.get()) self.character_power.atk_raised = float(self.atk_raised.get()) self.character_power.hit_rate = float(self.hit_rate.get()) self.character_power.critical_ratio = float(self.critical_ratio.get()) self.character_power.critical_factor = float( self.critical_factor.get()) self.character_power.active_factor = float(self.active_factor.get()) self.character_power.active_cost = int(self.active_cost.get()) self.character_power.addition = self.addition.get() self.character_power.presently = self.presently.is_selected self.callback() self.destroy() def filling_in_entries_by_character(self): character = self.character_selector.get() self.atk_raised.set(1.0) self.hit_rate.set(character.atk_speed) self.critical_ratio.set(character.critical_rate) self.critical_factor.set(1.5) self.active_cost.set(character.active_cost) def filling_in_atk_by_level(self): atk = self.character_selector.get().estimate_atk_by_level( int(self.level.get())) if atk: self.atk.set(atk) def open_updating_character_window(self): open_updating_character_window(self.master, self.character_selector.get(), position_y_shift=-300)
class SpecificStageDroppedCanvas(Canvas): KEY_TITLE = 'title' KEY_TOTAL = 'total' KEY_DROPS = "drops" KEY_VALUES = "values" KEY_DEFAULTS = "defaults" def __init__(self, master, section, **kwargs): Canvas.__init__(self, master, **kwargs) self.title = StringVar() self.section = section self._init_frame() self._init_fields() def _init_frame(self): Label(self, textvariable=self.title, width=13, font=(MS_JH, 14)).place(x=12, y=5) self.box_1_button = ToggleButton(self, text='1st', width=3, font=(SCP, 11), relief=RIDGE) self.box_1_button.place(x=5 + 43 * 0, y=39) self.box_2_button = ToggleButton(self, text='2nd', width=3, font=(SCP, 11), relief=RIDGE) self.box_2_button.place(x=5 + 43 * 1, y=39) self.box_3_button = ToggleButton(self, text='3rd', width=3, font=(SCP, 11), relief=RIDGE) self.box_3_button.place(x=5 + 43 * 2, y=39) self.box_4_button = ToggleButton(self, text='4th', width=3, font=(SCP, 11), relief=RIDGE) self.box_4_button.place(x=5 + 43 * 3, y=39) submit_button = Button(self, text='Submit', width=17, font=(SCP, 11), relief=RIDGE) submit_button.place(x=5, y=76) submit_button.bind('<Button-1>', lambda event: self.submitting()) current_y = 114 self.total_desc = StringVar() Label(self, textvariable=self.total_desc, width=16, font=(SCP, 11)).place(x=13, y=current_y) current_y += 28 self.drop_vars = [IntVar(), IntVar(), IntVar(), IntVar()] for i in range(4): Label(self, textvariable=self.drop_vars[i], width=3, font=(SCP, 11), relief=GROOVE). \ place(x=6 + 43 * i, y=current_y) current_y += 29 self.values_desc = StringVar() Label(self, textvariable=self.values_desc, width=16, font=(SCP, 11)).place(x=13, y=current_y) def _init_fields(self): data_record = get_data_record(self.section) self.title.set(data_record[self.KEY_TITLE]) self.statistic_tacker = DroppedStatisticTacker(4) self.statistic_tacker.set(data_record[self.KEY_TOTAL], data_record[self.KEY_DROPS]) self.values = data_record[self.KEY_VALUES] self._init_buttons_state(data_record[self.KEY_DEFAULTS]) self._update_statistics() def _update_statistics(self): from itertools import izip self.total_desc.set('Times : %2d ' % self.statistic_tacker.times) for i in range(4): self.drop_vars[i].set(self.statistic_tacker.drops[i]) self.values_desc.set('Value : %1.2f' % (sum(p * q for p, q in izip( self.values, self.statistic_tacker.get_statistics_ratio())) / 100)) def _init_buttons_state(self, defaults): self.box_1_button.set_is_selected(defaults[0]) self.box_2_button.set_is_selected(defaults[1]) self.box_3_button.set_is_selected(defaults[2]) self.box_4_button.set_is_selected(defaults[3]) def submitting(self): self.statistic_tacker.record([ self.box_1_button.is_selected, self.box_2_button.is_selected, self.box_3_button.is_selected, self.box_4_button.is_selected ]) data_record = get_data_record(self.section) data_record[self.KEY_TOTAL] = self.statistic_tacker.times data_record[self.KEY_DROPS] = self.statistic_tacker.drops save_data_record() self._init_buttons_state(data_record[self.KEY_DEFAULTS]) self._update_statistics()
class MonthlyDroppedCanvas(Canvas): KEY_TOTAL = 'total' KEY_FERTILIZER = 'fertilizer' KEY_CHARACTER = 'character' def __init__(self, master, section, **kwargs): Canvas.__init__(self, master, **kwargs) self.title = StringVar() self.section = section self._init_frame() self._init_fields() def _init_frame(self): Label(self, textvariable=self.title, width=8, font=(MS_JH, 14)).place(x=43, y=5) self.box_12_button = ToggleButton(self, text='1&2', width=4, font=(SCP, 11), relief=RIDGE) self.box_12_button.place(x=18 + 51 * 0, y=39) self.box_3_button = ToggleButton(self, text='3', width=4, font=(SCP, 11), relief=RIDGE) self.box_3_button.place(x=18 + 51 * 1, y=39) self.box_4_button = ToggleButton(self, text='4', width=4, font=(SCP, 11), relief=RIDGE) self.box_4_button.place(x=18 + 51 * 2, y=39) submit_button = Button(self, text='Submit', width=15, font=(SCP, 11), relief=RIDGE) submit_button.place(x=20, y=76) submit_button.bind('<Button-1>', lambda event: self.submitting()) label_x = 12 var_x = label_x + 98 current_y = 114 Label(self, text=' Times :', width=12, font=(SCP, 10)).place(x=label_x, y=current_y) Label(self, text='Fertilizer:', width=12, font=(SCP, 10)).place(x=label_x, y=current_y + 20) self.times_var = StringVar() self.fertilizer_var = StringVar() Label(self, textvariable=self.times_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y) Label(self, textvariable=self.fertilizer_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y + 20) current_y += 45 Label(self, text=' Avg.Fer. :', width=12, font=(SCP, 10)).place(x=label_x, y=current_y) Label(self, text='Character :', width=12, font=(SCP, 10)).place(x=label_x, y=current_y + 20) self.avg_fertilizer_var = StringVar() self.character_var = StringVar() Label(self, textvariable=self.avg_fertilizer_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y) Label(self, textvariable=self.character_var, width=6, font=(SCP, 11)).place(x=var_x, y=current_y + 20) self._init_buttons_state() def _init_fields(self): data_record = get_data_record(self.section) self.title.set(data_record['title']) self.statistic_tacker = DroppedStatisticTacker(2) self.statistic_tacker.set(data_record[self.KEY_TOTAL], [ data_record[self.KEY_FERTILIZER], data_record[self.KEY_CHARACTER] ]) self._update_statistics() def _update_statistics(self): self.times_var.set(self.statistic_tacker.times) self.fertilizer_var.set(self.statistic_tacker.drops[0]) avg_count = self.statistic_tacker.get_statistics_count() self.avg_fertilizer_var.set('%.2f' % (avg_count[0])) self.character_var.set(' %.1f %%' % ((avg_count[1]) * 100)) def _init_buttons_state(self): self.box_12_button.set_is_selected(True) self.box_3_button.set_is_selected(False) self.box_4_button.set_is_selected(False) def submitting(self): self.statistic_tacker.record([ int(self.box_12_button.is_selected) * 2 + self.box_3_button.is_selected, self.box_4_button.is_selected ]) data_record = get_data_record(self.section) data_record[self.KEY_TOTAL] = self.statistic_tacker.times data_record[self.KEY_FERTILIZER] = self.statistic_tacker.drops[0] data_record[self.KEY_CHARACTER] = self.statistic_tacker.drops[1] save_data_record() self._init_buttons_state() self._update_statistics()
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