class My_Tk(): def __init__(self, root, user_info=None, cookies=None, headers=None, tasklist_=None): self.tk = root self.user_info = user_info self.base_cookies = cookies self.base_headers = headers # self.tk.geometry('620x400') self.orm = {} self.val_map = {} self.create_button() self.create_heading() self.create_tv() self.tasklist_ = tasklist_ def create_button(self): frame = Frame(self.tk, width=200, height=50) frame.pack(fill=X, side=TOP) Button(frame, text='下载', width=6, command=self.download).place(x=28, y=21) # Button(frame, text='测试数据', command=self.insert_test_tree_data).pack(side=LEFT, anchor='w') Button(frame, text='清除列表', command=self.clear_tree_data).place(x=82, y=21) def get_tv(self): return self.tv def download(self): try: for k, v in self.orm.items(): button = self.orm[k][0] button_value = button.getvar(button['variable']) if button_value == '1': print(self.tv.item(k, 'values')) if self.user_info == None or len(self.user_info) == 0: messagebox.showinfo(title="提示", message="请先登录!") return else: media_type = self.tasklist_.media_type_var.get() if media_type and media_type == ".mp4": params = { 'fragmentId': self.val_map[k] + 1, 'token': self.user_info['token'], 'albumId': -8888888, 'programId': -8888888 } else: params = { 'fragmentId': self.val_map[k], 'token': self.user_info['token'], 'albumId': 0, 'programId': 0 } self.base_headers["Host"] = "api.dushu.io" response = requests.post( url="http://api.dushu.io/fragment/content", json=params, headers=self.base_headers, cookies=self.base_cookies) response_data = response.json() mediaUrls = response_data["mediaUrls"] mediaUrl = None if mediaUrls and type( mediaUrls) == list and len(mediaUrls) > 0: if len(mediaUrls) > 1: if media_type == r".mp4": for url_ in mediaUrls: if url_.find("video") != -1: mediaUrl = url_ elif media_type == r".mp3": media_type = r".mp3" for url_ in mediaUrls: if url_.find("audio") != -1: mediaUrl = url_ elif mediaUrls[0].find("audio") != -1: if media_type == '.mp4': messagebox.showinfo( title="提示", message="该资源只有音频,请在任务列表切换下载类型!") return else: mediaUrl = response_data['mediaUrls'][0] elif mediaUrls[0].find("video") != -1: mediaUrl = response_data['mediaUrls'][0] else: return else: return if media_type == '.mp3': file_name = response_data['title'] else: file_name = response_data['bookName'] print(mediaUrl) media_info_headers = {} if (mediaUrl.startswith("https")): mediaUrl = "http" + mediaUrl[5:] host_pattern = re.compile("\w+://(.*?)/.*") host_ = host_pattern.findall(mediaUrl)[0] if host_ != "cdn-ali.dushu.io": media_info_headers = { 'Host': "v-cc.dushu.io", 'Cookie': "grwng_uid=e7e51c80-ead6-43bb-9744-7531778d6c73; UM_distinctid=16be039d03e8aa-0f0e963eb0f589-621c740a-4a640-16be039d03f633; gr_user_id=ebc67f00-d109-4c29-80b0-7d631382debf", 'X-Playback-Session-Id': "A078D569-3595-4399-8240-EB42F542F073", 'Connection': "keep-alive, keep-alive", 'Accept': "*/*", 'User-Agent': "AppleCoreMedia/1.0.0.16D57 (iPhone; U; CPU OS 12_1_4 like Mac OS X; en_us)", 'Accept-Language': "en-us", 'Accept-Encoding': "gzip", 'cache-control': "no-cache" } else: media_info_headers = { 'Host': "cdn-ali.dushu.io", 'Cookie': "grwng_uid=e7e51c80-ead6-43bb-9744-7531778d6c73; UM_distinctid=16be039d03e8aa-0f0e963eb0f589-621c740a-4a640-16be039d03f633; gr_user_id=ebc67f00-d109-4c29-80b0-7d631382debf", 'X-Playback-Session-Id': "A9D630B7-54FF-4514-923C-A561AFA5C7BA", 'Range': "bytes=0-1", 'Accept': "*/*", 'User-Agent': "AppleCoreMedia/1.0.0.16D57 (iPhone; U; CPU OS 12_1_4 like Mac OS X; en_us)", 'Accept-Language': "en-us", 'Accept-Encoding': "identity", 'Connection': "keep-alive", 'cache-control': "no-cache", } media_info_headers["Range"] = "bytes=0-1" media_info_headers['Host'] = host_ media_info = requests.get(url=mediaUrl, headers=media_info_headers, cookies=self.base_cookies) file_des = self.tasklist_.download_dir.get( ) + r"\\" + file_name + media_type bytes_length = 0 if "Content-Range" in media_info.headers: range_ = media_info.headers['Content-Range'] bytes_length = range_[range_.rfind('/') + 1:] elif host_ == "cdn-ali.dushu.io": with open(file_des, "wb") as saved: saved.write(bytes(media_info.content)) return def down(): try: row = [ str(datetime.now().strftime( "%Y%m%d%H%M%S")), file_name + media_type, datetime.now().strftime( "%Y-%m-%d %H:%M:%S"), self.tasklist_.catch_progress_bar(), StringVar(value="0") ] with open(file_des, 'wb') as saved: self.tasklist_.insert_data(row) media_info_content = media_info.content play_list_pattern = re.compile( "(\w+\.mp4_[\d]+\.ts)", re.DOTALL) play_list = [] if type(media_info_content) != str: play_list = play_list_pattern.findall( str(media_info_content)) threading.Thread( target=lambda: { messagebox.showinfo( title="提示", message="请前往任务列表查看下载状态") }).start() if play_list != None and len( play_list) == 0: if int(bytes_length) <= 0: return print(type(bytes_length)) count = (int(bytes_length) + 1 - 131072) / 131072 print(count) print(type(count)) tmp = 0 for index in range(int(count)): if index == count - 1: media_info_headers[ 'Range'] = "bytes=" + str( index * 131072 ) + "-" + str(bytes_length) else: media_info_headers[ 'Range'] = "bytes=" + str( index * 131072) + "-" + str( (index + 1) * 131072 - 1) media_content = requests.get( url=mediaUrl, headers=media_info_headers, cookies=self.base_cookies) saved.write( bytes(media_content.content)) tmp = tmp + 1 print(count) if (tmp > count / 100): print(tmp) self.tasklist_.progress( row[3], index / count * 164 ) # 比其所在canvas宽度小1,百分之99即撑满整个进度条 tmp = 0 row[4].set( str(int(index / count * 100)) + "%") print("*************downloading" + str(index / count * 100) + "%************") else: for index, play_url in enumerate( play_list): tmp_media_url = mediaUrl[:mediaUrl. rfind("/" ) + 1] + play_url[ 1:] response = requests.get( url=tmp_media_url, headers=media_info_headers, cookies=self.base_cookies) if response.status_code == 200: saved.write( bytes(response.content)) self.tasklist_.progress( row[3], index / len(play_list) * 164 ) # 比其所在canvas宽度小1,百分之99即撑满整个进度条 print( "*************downloading" + str(index / len(play_list) * 100) + "%**************") row[4].set( str( int(index / len(play_list) * 100)) + "%") except BaseException as e: row[4].set("失败") row.pop(3) self.tasklist_.append_download_history(row) messagebox.showinfo("错误", message=str(e)) else: row[4].set("100%") row.pop(3) self.tasklist_.append_download_history(row) messagebox.showinfo("提示", message=file_name + "下载完成!") th = threading.Thread(target=down) th.setDaemon(True) th.start() print(self.val_map[k]) except BaseException as e: print(e) traceback.print_exc(file=open('error.txt', 'a+')) messagebox.showerror("提示", message="下载出错") print("下载出错") def create_heading(self, ): '''重新做一个treeview的头,不然滚动滚动条,看不到原先的头!!!''' heading_frame = Frame(self.tk) heading_frame.pack(fill=X) # 填充用 # button_frame = Label(heading_frame,bg='gray') # button_frame.pack(side=LEFT, expand=False) # 全选按钮 self.all_buttonvar = IntVar() self.all_button = Checkbutton(heading_frame, text='', variable=self.all_buttonvar, command=self.select_all) self.all_button.pack(side=LEFT) self.all_buttonvar.set(0) self.columns = ['no', 'name', 'author'] self.columns_header_name = ['序号', '名称', '作者'] self.header_label_widths = [40, 260, 100] self.colums_header_widths = [46, 292, 115] # 重建tree的头 for i in range(len(self.columns)): Label(heading_frame, text=self.columns_header_name[i], width=int(self.header_label_widths[i] * 0.16), anchor='center', relief=GROOVE).pack(side=LEFT) def insert_test_tree_data(self): rows = [] for i in range(30): rows.append((i + 1, 'B', 'C', 110)) self.insert_tv(rows) def clear_tree_data(self): self.init_tree() # 初始化表格 def init_tree(self): [self.tv.delete(item) for item in self.tv.get_children()] self.tv.update() for child in self.button_frame.winfo_children(): # 第一个构件是label,所以忽略 child.destroy() self.canvas.itemconfigure(self.tv_frame, height=300) # 设定窗口tv_frame的高度 self.tk.update() self.canvas.config(scrollregion=self.canvas.bbox("all")) # 滚动指定的范围 self.canvas.config(height=300) def create_tv(self): # 放置 canvas、滚动条的frame canvas_frame = Frame(self.tk, width=500, height=400) canvas_frame.pack(fill=X) # 只剩Canvas可以放置treeview和按钮,并且跟滚动条配合 self.canvas = Canvas(canvas_frame, width=400, height=500, scrollregion=(0, 0, 500, 400)) self.canvas.pack(side=LEFT, fill=BOTH, expand=1) # 滚动条 ysb = Scrollbar(canvas_frame, orient=VERTICAL, command=self.canvas.yview) self.canvas.configure(yscrollcommand=ysb.set) ysb.pack(side=RIGHT, fill=Y) # !!!!=======重点:鼠标滚轮滚动时,改变的页面是canvas 而不是treeview self.canvas.bind_all( "<MouseWheel>", lambda event: self.canvas.yview_scroll( int(-1 * (event.delta / 120)), "units")) # 想要滚动条起效,得在canvas创建一个windows(frame)!! tv_frame = Frame(self.canvas) self.tv_frame = self.canvas.create_window(0, 0, window=tv_frame, anchor='nw', width=600, height=400) # anchor该窗口在左上方 # 放置button的frame self.button_frame = Frame(tv_frame) self.button_frame.pack(side=LEFT, fill=Y) Label(self.button_frame, width=3).pack() # 填充用 # 创建treeview self.tv = Treeview(tv_frame, height=10, columns=self.columns, show='tree') # height好像设定不了行数,实际由插入的行数决定 self.tv.column("#0", width=0, stretch=0) self.tv.pack(expand=True, side=LEFT, fill=BOTH) # 设定每一列的属性 for i in range(len(self.columns)): self.tv.column(self.columns[i], width=self.colums_header_widths[i], anchor='w', stretch=False) # 设定treeview格式 # import tkinter.font as tkFont # ft = tkFont.Font(family='Fixdsys', size=20, weight=tkFont.BOLD) self.tv.tag_configure('oddrow', font='黑体 8') # 设定treeview里字体格式font=ft self.tv.tag_configure('select', background='SkyBlue', font='Arial 8') # 当对应的按钮被打勾,那么对于的行背景颜色改变! self.rowheight = 27 # 很蛋疼,好像tkinter里只能用整数! Style().configure('Treeview', rowheight=self.rowheight) # 设定每一行的高度 # 设定选中的每一行字体颜色、背景颜色 (被选中时,没有变化) Style().map("Treeview", foreground=[ ('focus', 'black'), ], background=[('active', 'white')]) self.tv.bind('<<TreeviewSelect>>', self.select_tree) # 绑定tree选中时的回调函数 def insert_tv(self, rows=None): if rows == None: rows = [] for i in range(20): item = (i + 1, 'A', "B") rows.append(item) # 清空tree、checkbutton items = self.tv.get_children() [self.tv.delete(item) for item in items] self.tv.update() for child in self.button_frame.winfo_children(): # 第一个构件是label,所以忽略 child.destroy() # 重设tree、button对应关系 self.orm = {} index = 0 for row in rows: tv_item = self.tv.insert('', index, value=row[0:3], tags=('oddrow')) # item默认状态tags import tkinter ck_button = tkinter.Checkbutton(self.button_frame, variable=IntVar()) ck_button['command'] = lambda item=tv_item: self.select_button(item ) ck_button.pack() # ck_button['fragementId']=row[3] self.orm[tv_item] = [ck_button] self.val_map[tv_item] = row[3] index = index + 1 # 每次点击插入tree,先设定全选按钮不打勾,接着打勾并且调用其函数 self.all_buttonvar.set(0) self.all_button.invoke() # 更新canvas的高度 height = (len(self.tv.get_children()) + 1) * self.rowheight # treeview实际高度 self.canvas.itemconfigure(self.tv_frame, height=height) # 设定窗口tv_frame的高度 self.tk.update() self.canvas.config(scrollregion=self.canvas.bbox("all")) # 滚动指定的范围 self.canvas.config(height=height) def select_all(self): '''全选按钮的回调函数 作用:所有多选按钮打勾、tree所有行都改变底色(被选中)''' for item, [button] in self.orm.items(): if self.all_buttonvar.get() == 1: button.select() self.tv.item(item, tags='select') else: button.deselect() self.tv.item(item, tags='oddrow') def select_button(self, item): '''多选按钮的回调函数 作用:1.根据按钮的状态,改变对应item的底色(被选中) 2.根据所有按钮被选的情况,修改all_button的状态''' button = self.orm[item][0] button_value = button.getvar(button['variable']) if button_value == '1': self.tv.item(item, tags='select') else: self.tv.item(item, tags='oddrow') self.all_button_select() # 根据所有按钮改变 全选按钮状态 def select_tree(self, event): '''tree绑定的回调函数 作用:根据所点击的item改变 对应的按钮''' select_item = self.tv.focus() button = self.orm[select_item][0] button.invoke() # 改变对应按钮的状态,而且调用其函数 def all_button_select(self): '''根据所有按钮改变 全选按钮状态 循环所有按钮,当有一个按钮没有被打勾时,全选按钮取消打勾''' for [button] in self.orm.values(): button_value = button.getvar(button['variable']) if button_value == '0': self.all_buttonvar.set(0) break else: self.all_buttonvar.set(1)
class ShowListUserDialog(Toplevel): def __init__(self,parent,**kw): Toplevel.__init__(self,parent,**kw) self.parent = parent self.numberTempUserAdd = 0 self.data = Database() self.listUser = self.data.getUserList() self.menu = Menu(self) self.config(menu = self.menu) self.drawMenu(self.menu) self.drawDialog() for user in self.listUser: self.addUserIntoTree(user) self.linkAccelerator() def linkAccelerator(self): self.bind_all("<Control-N>",self.onAddUser) self.bind_all("<Delete>", self.onDeleteUser) self.treeUser.bind(sequence="<Double-Button-1>",func=self.onEditUser) def drawMenu(self, parent): # Type Menu typeMenu = Menu(parent) typeMenu.add_command(label = "Thêm User", command = self.onAddUser, accelerator = "Ctrl+Shift+N") typeMenu.add_command(label = "Xóa User", command = self.onDeleteUser, accelerator = "Delete") parent.add_cascade(label = "Chức năng", menu = typeMenu) def drawDialog(self): layoutTreeUser = Frame(self) listAttribute = ["Password", "Họ tên"] yScrollTree = Scrollbar(layoutTreeUser, orient = VERTICAL) xScrollTree = Scrollbar(layoutTreeUser, orient = HORIZONTAL) # Create Delete, Add and Edit Button # Create Tree View self.treeUser = Treeview(layoutTreeUser, column = listAttribute, yscrollcommand = yScrollTree.set, xscrollcommand = xScrollTree.set ) self.treeUser.heading(column = "#0", text = "Username") self.treeUser.column(column = "#0", width = 100, minwidth = 100) for nameAttr in listAttribute: self.treeUser.heading(column = nameAttr, text = nameAttr) self.treeUser.column(column = nameAttr, width = 100, minwidth = 100) #Create Scrollbar for tree view yScrollTree.pack(side = RIGHT, fill = Y) xScrollTree.pack(side = BOTTOM, fill = X) self.treeUser.pack(side = TOP, anchor = "w", fill = BOTH, expand = True) yScrollTree.config(command = self.treeUser.yview) xScrollTree.config(command = self.treeUser.xview) layoutTreeUser.pack(side = TOP, fill = BOTH, expand = True) def addUserIntoTree(self,userInput): temp = userInput # if not self.treeUser.exists(temp.idParent) : # self.treeUser.insert("","end", str(temp.idParent), text = temp.idParent) # self.treeUser.item(temp.idParent, open = True) self.treeUser.insert("","end", str(temp.username), text = temp.username) self.treeUser.set(temp.username, "Password", temp.passWord) self.treeUser.set(temp.username, "Họ tên", temp.name) def onAddUser(self, event = None): if self.numberTempUserAdd > 9: messagebox.showwarning("Warning","Bạn chỉ có thể thêm tạm 10 username \n Hãy Sửa ID để lưu lại những loại tạm trên", parent = self) return userTemp = User(name = "#",username=str(self.numberTempUserAdd),passWord="******") self.addUserIntoTree(userTemp) self.numberTempUserAdd += 1 def onEditUser(self, event = None): listTemp = ["0","1","2","3","4","5","6","7","8","9"] curUser = self.treeUser.item(self.treeUser.focus()) col = self.treeUser.identify_column(event.x) print(curUser) print(col) if curUser["text"] in listTemp and col != "#0": if col != "#0": messagebox.showinfo("Thêm User","Sửa username tạm này để lưu lại vào Database",parent = self) return cellValue = None if col == "#0": temp = simpledialog.askstring("Đổi Username", "Nhập mới", parent = self) if temp != None: if len(temp)>0: cellValue = curUser["text"] try: if cellValue in listTemp: newUser = User(curUser["values"][1],temp,curUser["values"][0]) self.data.insertUser(newUser) self.treeUser.update() print("Sau khi sua:",self.treeUser.item(self.treeUser.focus())) else: self.data.updateUsernameOfUser(cellValue,temp) except (sqlite3.IntegrityError, TclError): messagebox.showwarning("Opps !!!!",message="Username bạn nhập đã tồn tại !!!!", parent = self) return if cellValue in listTemp: self.numberTempUserAdd -= 1 else: messagebox.showwarning("Empty !!!", "Username không thể để trống",parent = self) self.treeUser.insert("", str(self.treeUser.index(self.treeUser.focus())), temp ,text = temp, values = curUser["values"]) self.treeUser.delete(self.treeUser.focus()) return if col == "#1": temp = simpledialog.askstring("Đổi Password", "Nhập Password mới: ", parent = self) if temp != None: if len(temp) > 0: cellValue = curUser["values"][0] self.data.updatePassOfUser(curUser["text"],temp) curUser["values"][0] = temp print(curUser["text"]) self.treeUser.item(curUser["text"], values = curUser["values"]) self.treeUser.update() else: messagebox.showwarning("Empty !!!", "Password không thể để trống",parent = self) return if col == "#2": temp = simpledialog.askstring("Đổi tên", "Nhập tên mới",parent = self) if temp != None: if len(temp) > 0: cellValue = curUser["values"][1] self.data.updateNameOfuser(curUser["text"],temp) curUser["values"][1] = temp print(curUser["text"]) self.treeUser.item(curUser["text"], values = curUser["values"]) self.treeUser.update() else: messagebox.showwarning("Empty !!!", "Họ tên không thể để trống",parent = self) return print("Cell Values = ", cellValue) def onDeleteUser(self, event = None): curItem = self.treeUser.selection() accept = messagebox.askokcancel("Xóa User này","Bạn thật sự muốn xóa!!! Bạn không thể hoàn tác hành động này", parent = self) if accept == True: if len(curItem) == 0: messagebox.showwarning(title = "Empty !!!", message = "Xin hãy chọn User bạn muốn xóa", parent = self) return for choose in curItem: treeItem = self.treeUser.item(choose) self.data.deleteUser(treeItem["text"]) self.treeUser.delete(treeItem["text"]) def onDestroy(self, event): # ask = """ # Bạn thực sự muốn đóng ứng dụng # """ # messagebox.askokcancel("Closing!!!",) self.parent.linkAccelerator() self.destroy() # if __name__ == "__main__": # root = Tk() # ShowListUserDialog(root) # root.mainloop()
class NodeTree: def __init__(self): self._client = KazooClient(hosts='localhost:2181') # self._client = KazooClient(hosts='10.128.62.34:2181,10.128.62.34:2182,10.128.62.34:2183') self._client.start() self._selected_node = None self._win = None self._root = None self._tree_canvas = None self._tree_frame_id = None self.init_ui() self.init_tree() self._count = 0 # self.treeify() print(self._count) self._win.mainloop() def init_ui(self): self._win = tk.Tk() self._win.title("zk-client") self._win.geometry('900x700+500+300') self._win.resizable(height=False, width=False) tree_wrapper = tk.Frame(self._win, bg='red', width=300) tree_wrapper.pack(side=tk.LEFT, fill=tk.Y) canvas = self._tree_canvas = tk.Canvas(tree_wrapper, width=300, height=700, scrollregion=(0, 0, 300, 700), bg='gray') # 创建canvas canvas.place(x=0, y=0) # 放置canvas的位置 frame = tk.Frame(canvas) # 把frame放在canvas里 # frame.place(width=180, height=600) # frame的长宽,和canvas差不多的 vbar = Scrollbar(canvas, orient=tk.VERTICAL) # 竖直滚动条 vbar.place(x=281, width=20, height=700) vbar.configure(command=canvas.yview) hbar = Scrollbar(canvas, orient=tk.HORIZONTAL) # 水平滚动条 hbar.place(x=0, y=680, width=280, height=20) hbar.configure(command=canvas.xview) canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set) # 设置 canvas.bind_all( "<MouseWheel>", lambda event: canvas.yview_scroll( int(-1 * (event.delta / 120)), "units")) self._tree_frame_id = canvas.create_window( 0, 0, window=frame, anchor='nw') # create_window) self._root = Treeview(frame) # self._root.pack(expand=True, fill=tk.BOTH) # self._root.bind("<Button-1>", self.clear_pre_selected) # self._root.bind("<< TreeviewClose>>", self.clear_pre_selected) self._root.bind("<<TreeviewOpen>>", self.open_node) def adjust_size(self): self._root.update() width = self._root.winfo_width() height = self._root.winfo_height() print(width, height) self._tree_canvas.itemconfigure(self._tree_frame_id, height=height) # 设定窗口tv_frame的高度 self._tree_canvas.config(scrollregion=(0, 0, width, height)) self._tree_canvas.config( scrollregion=self._tree_canvas.bbox("all")) # 滚动指定的范围 self._tree_canvas.config(height=height) pass def init_tree(self): tops = self._client.get_children("/") for index, top in enumerate(tops): self._root.insert('', index, text=top) children = self._client.get_children("/" + top + "/") if children is not None and len(children) > 0: pass def clear_pre_selected(self, event): focus = self._root.focus() if focus == '': return children = self._root.get_children(focus) for child in children: self._root.delete(child) def open_node(self, event): iid = self._root.focus() path = self.get_current_path(iid) children = self._client.get_children(path) for index, p in enumerate(children): self._root.insert(iid, index, text=p) self.adjust_size() def get_current_path(self, item): curr_item = self._root.item(item) pid = self._root.parent(item) if pid == '': return '/' + curr_item['text'] + "/" else: return self.get_current_path(pid) + curr_item['text'] + "/" def treeify(self): self._client.start() self.treeify_recursive("/", parent='', index=0) def treeify_recursive(self, path, parent, index): self._count += 1 cd = self._client.get_children(path=path) if cd and len(cd) > 0: for i, c in enumerate(cd): tmp_path = path + c + '/' tc = self._client.get_children(tmp_path) if tc and len(tc) > 0: insert = self._root.insert(parent, i, text=c) self.treeify_recursive(path=tmp_path, parent=insert, index=i) else: self._root.insert(parent, i, text=c)
class TreeType(Frame): def __init__(self, parent, item, dialog): Frame.__init__(self, parent) self.parent = parent self.item = item self.numTypeAdded = 0 self.dialogParent = dialog self.listType = item.type self.data = Database() self.drawScreen() self.linkAccelerator() for typeItem in self.listType: self.addTypeIntoTree(typeItem) def linkAccelerator(self): self.bind_all("<Shift-Delete>", self.onDeleteItem) self.bind_all("<Control-N>", self.onAddType) self.bind_all("<Delete>", self.onDeleteType) def drawScreen(self): # self.pack(fill = BOTH, anchor = "w", expand = True) ########## Listing all Bills which has been created ########### layoutList = Frame(self) self.drawTreeOfType(layoutList) layoutList.pack(side=LEFT, fill=BOTH, expand=True) self.menu = Menu(self) self.dialogParent.config(menu=self.menu) self.drawMenu(self.menu) def drawTreeOfType(self, parent): self.pack(fill=BOTH, expand=True) listAttribute = ["Loại hàng", "Số lượng tồn", "Đơn giá"] yScrollTree = Scrollbar(parent, orient=VERTICAL) xScrollTree = Scrollbar(parent, orient=HORIZONTAL) # Create Delete, Add and Edit Button layoutButton = Frame(self) btnAddType = Button(layoutButton, text="+", fg="green", command=self.onAddType) btnDelType = Button(layoutButton, text="-", fg="red", command=self.onDeleteType) btnRefresh = Button(layoutButton, text="Refresh", fg="blue", command=self.dialogParent.onRefresh) btnAddType.pack(side=LEFT) btnDelType.pack(side=LEFT) btnRefresh.pack(side=RIGHT) layoutButton.pack(side=TOP, fill=X, anchor="w") # Create Tree View self.treeType = Treeview(parent, column=listAttribute, yscrollcommand=yScrollTree.set, xscrollcommand=xScrollTree.set) self.treeType.bind(sequence="<Double-Button-1>", func=self.onEditType) self.treeType.heading(column="#0", text="ID") self.treeType.column(column="#0", width=100, minwidth=100) for nameAttr in listAttribute: self.treeType.heading(column=nameAttr, text=nameAttr) self.treeType.column(column=nameAttr, width=100, minwidth=100) #Create Scrollbar for tree view yScrollTree.pack(side=RIGHT, fill=Y) xScrollTree.pack(side=BOTTOM, fill=X) self.treeType.pack(side=TOP, anchor="w", fill=BOTH, expand=True) yScrollTree.config(command=self.treeType.yview) xScrollTree.config(command=self.treeType.xview) def drawMenu(self, parent): # Item Menu itemMenu = Menu(parent) itemMenu.add_command(label="Thêm mặt hàng", command=self.dialogParent.onAddItem, accelerator="Ctrl+N") itemMenu.add_command(label="Xóa mặt hàng", command=self.onDeleteItem, accelerator="Shift+Delete") parent.add_cascade(label="Mặt hàng", menu=itemMenu) # Type Menu typeMenu = Menu(parent) typeMenu.add_command(label="Thêm loại hàng", command=self.onAddType, accelerator="Ctrl+Shift+N") typeMenu.add_command(label="Xóa loại hàng", command=self.onDeleteType, accelerator="Delete") parent.add_cascade(label="Loại hàng", menu=typeMenu) def addTypeIntoTree(self, typeInput): temp = typeInput # if not self.treeType.exists(temp.idParent) : # self.treeType.insert("","end", str(temp.idParent), text = temp.idParent) # self.treeType.item(temp.idParent, open = True) self.treeType.insert("", "end", str(temp.idType), text=temp.idType) self.treeType.set(temp.idType, "Loại hàng", temp.name) self.treeType.set(temp.idType, "Số lượng tồn", temp.amount) self.treeType.set(temp.idType, "Đơn giá", int(temp.unitPrice)) def onEditType(self, event=None): listTemp = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] curItem = self.treeType.item(self.treeType.focus()) col = self.treeType.identify_column(event.x) print(curItem) print(col) if curItem["text"] in listTemp and col != "#0": if col != "#0": messagebox.showinfo( "Thêm loại", "Sửa ID loại tạm này để lưu lại vào Database", parent=self) return cellValue = None if col == "#0": temp = simpledialog.askstring("Đổi ID", "Nhập ID mới", parent=self) if temp != None: if len(temp) > 0: cellValue = curItem["text"] try: if cellValue in listTemp: idTab = self.parent.select() frameChosen = self.parent._nametowidget(idTab) typeItem = TypeItem(curItem["values"][0], 0, 0, temp, frameChosen.item.id) self.data.insertTypeItem(typeItem) frameChosen.treeType.update() print("Sau khi sua:", self.treeType.item(self.treeType.focus())) else: self.data.updateIdOfType(cellValue, temp) except (sqlite3.IntegrityError, TclError): messagebox.showwarning( "Opps !!!!", message="ID bạn nhập đã tồn tại !!!!", parent=self) return if cellValue in listTemp: frameChosen.numTypeAdded -= 1 self.treeType.update() else: messagebox.showwarning("Empty !!!", "ID không thể để trống", parent=self) self.treeType.insert( "", str(self.treeType.index(self.treeType.focus())), temp, text=temp, values=curItem["values"]) self.treeType.delete(self.treeType.focus()) return if col == "#1": temp = simpledialog.askstring("Đổi tên loại hàng", "Nhập tên mới", parent=self) if temp != None: if len(temp) > 0: cellValue = curItem["values"][0] self.data.updateNameOfType(curItem["text"], temp) curItem["values"][0] = temp self.treeType.item(curItem["text"], values=curItem["values"]) self.treeType.update() else: messagebox.showwarning("Empty !!!", "Tên loại hàng không thể để trống", parent=self) return if col == "#2": temp = simpledialog.askinteger("Đổi số lượng tồn", "Nhập số lượng tồn mới: ", parent=self) if temp != None: if temp >= 0: cellValue = curItem["values"][1] self.data.updateAmountOfType(curItem["text"], temp) curItem["values"][1] = temp print(curItem["text"]) self.treeType.item(curItem["text"], values=curItem["values"]) self.treeType.update() else: messagebox.showwarning("Empty !!!", "Số lượng không thể là số âm", parent=self) return if col == "#3": temp = simpledialog.askfloat("Đổi đơn giá", "Nhập đơn giá mới: ", parent=self) if temp != None: if temp >= 0: cellValue = curItem["values"][2] self.data.updateUnitOfType(curItem["text"], temp) curItem["values"][2] = temp print(curItem["text"]) self.treeType.item(curItem["text"], values=curItem["values"]) self.treeType.update() else: messagebox.showwarning("Empty !!!", "Đơn giá không thể là số âm", parent=self) return print("Cell Values = ", cellValue) def onAddType(self, event=None): idTab = self.parent.select() frameChosen = self.parent._nametowidget(idTab) if frameChosen.numTypeAdded > 9: messagebox.showwarning( "Warning", "Bạn chỉ có thể thêm tạm 10 loại \n Hãy Sửa ID để lưu lại những loại tạm trên", parent=self) return typeItem = TypeItem(name=frameChosen.numTypeAdded, amount=0, unitPrice=0, idType="#", idParent=frameChosen.item.id) frameChosen.addTypeIntoTree(typeItem) frameChosen.numTypeAdded += 1 def onDeleteType(self, event=None): idTab = self.parent.select() frameChosen = self.parent._nametowidget(idTab) curItem = frameChosen.treeType.selection() accept = messagebox.askokcancel( "Xóa loại hàng này", "Bạn thật sự muốn xóa!!! Bạn không thể hoàn tác hành động này", parent=self) if accept == True: if len(curItem) == 0: messagebox.showwarning( title="Empty !!!", message="Xin hãy chọn loại hàng bạn muốn xóa", parent=self) return for choose in curItem: treeItem = frameChosen.treeType.item(choose) self.data.deleteType(treeItem["values"][0]) frameChosen.treeType.delete(treeItem["text"]) def onDeleteItem(self, event=None): idTab = self.parent.select() frameChosen = self.parent._nametowidget(idTab) accept = messagebox.askokcancel( "Xóa loại hàng này", "Bạn thật sự muốn xóa!!! Bạn không thể hoàn tác hành động này", parent=self) if accept == True: idTab = self.parent.select() frameChosen = self.parent._nametowidget(idTab) self.data.deleteItem(frameChosen.item.id) self.parent.forget(idTab) self.parent.update() def onDestroy(self, event): # ask = """ # Bạn thực sự muốn đóng ứng dụng # """ # messagebox.askokcancel("Closing!!!",) self.dialogParent.destroy()