class HelpOpening(tkinter.Toplevel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title("Что такое места перекрытия в конструкции дверей-купе?.") self.text = ScrolledText(self, wrap='word', height=40, width=120) self.text_p1 = """ Что такое места перекрытия в конструкции дверей-купе? Двери-купе перемещаются относительно друг друга по соседним полозьям, и чтобы внешне фасад шкафа-купе смотрелся нормально, край передней двери перекрывает край соседней двери на ширину профиля. Это и называется "местом перекрытия". Если в проём встраиваются две двери, между дверями создаётся одно место перекрытия. Если встраиваются три двери, получается два места перекрытия. Если встраиваются четыре двери, мест перекрытий может быть и три, а может быть и два. Пять дверей - четыре места перекрытия. На рисунке внизу всё показано наглядно. Чаще всего мест перекрытий бывает на один меньше, чем дверей, но бывают и исключения, как на примере четырёх дверей. Поэтому нужно быть внимательным при заполнении формы параметров дверей-купе """ self.text.insert(1.0, self.text_p1) self.text.tag_add('title', 2.0, '2.end') self.text.tag_config('title', font=('bold', )) self.image = Image.open( os.path.join(settings.help_img, 'opening_schem.png')) self.photo = ImageTk.PhotoImage(self.image) self.img = tkinter.Label(self, relief='flat', bd=0, image=self.photo) self.text.window_create(tkinter.INSERT, window=self.img) self.text.insert('end', ' ') self.text.pack(fill='x', side='left')
class TextEditor(): # see PyEdit for more def __init__(self, parent=None): # TODO: 1226 why This can generate independent window ? #frm=Toplevel(Frame.__init__(self, parent)) frm=Toplevel() # TODO : assign title based on cmdline tag frm.title('New Text') # TODO , how to make button and Text in a better Layout format ? # grid() param to learn Button(frm, text='Save', command=self.onSave).grid(row=0,column=0) Button(frm, text='Cut', command=self.onCut).grid(row=0,column=1) Button(frm, text='Paste', command=self.onPaste).grid(row=0,column=2) Button(frm, text='Find', command=self.onFind).grid(row=0,column=3) self.text = ScrolledText(frm) self.text.grid(row=1,columnspan=4) #Button(self, text='Save', command=self.onSave).grid() #Button(self, text='Cut', command=self.onCut).grid() #Button(self, text='Paste', command=self.onPaste).grid() #Button(self, text='Find', command=self.onFind).grid() #self.text = ScrolledText(self) def gettext(self): # returns a string return self.text.get('1.0', END+'-1c') # first through last def onSave(self): filename = asksaveasfilename() #print(filename) if filename: alltext = self.gettext() # first through last open(filename, 'w').write(alltext) # store text in file def onCut(self): text = self.text.get(SEL_FIRST, SEL_LAST) # error if no select self.text.delete(SEL_FIRST, SEL_LAST) # should wrap in try self.text.clipboard_clear() self.text.clipboard_append(text) def onPaste(self): # add clipboard text try: text = self.text.selection_get(selection='CLIPBOARD') self.text.insert(INSERT, text) except TclError: pass # not to be pasted def onFind(self): target = askstring('SimpleEditor', 'Search String?') if target: where = self.text.search(target, INSERT, END) # from insert cursor if where: # returns an index print(where) pastit = where + ('+%dc' % len(target)) # index past target #self.text.tag_remove(SEL, '1.0', END) # remove selection self.text.tag_add(SEL, where, pastit) # select found target self.text.mark_set(INSERT, pastit) # set insert mark self.text.see(INSERT) # scroll display self.text.focus() # select text widget
def descripText(destroy = False): 'Laat de puntentelling zien op het spelscherm' T.pack_forget() global hint, root, destxt destxt = ScrolledText(root, height=8, width=50, padx=170, pady=50) destxt.pack() destxt.insert(END, hint) destxt.config(state=DISABLED) destxt.tag_configure("center", justify='center') destxt.tag_add("center", 1.0, "end") destxt.place(relx=1, x=-2, y=2, anchor=NE)
class Application(tkinter.Tk): def __init__(self): """Initialize widgets, methods.""" tkinter.Tk.__init__(self) self.grid() fontoptions = families(self) font = Font(family="Verdana", size=10) menubar = tkinter.Menu(self) fileMenu = tkinter.Menu(menubar, tearoff=0) editMenu = tkinter.Menu(menubar, tearoff=0) fsubmenu = tkinter.Menu(editMenu, tearoff=0) ssubmenu = tkinter.Menu(editMenu, tearoff=0) # adds fonts to the font submenu and associates lambda functions for option in fontoptions: fsubmenu.add_command(label=option, command = lambda: font.configure(family=option)) # adds values to the size submenu and associates lambda functions for value in range(1,31): ssubmenu.add_command(label=str(value), command = lambda: font.configure(size=value)) # adds commands to the menus menubar.add_cascade(label="File",underline=0, menu=fileMenu) menubar.add_cascade(label="Edit",underline=0, menu=editMenu) fileMenu.add_command(label="New", underline=1, command=self.new, accelerator="Ctrl+N") fileMenu.add_command(label="Open", command=self.open, accelerator="Ctrl+O") fileMenu.add_command(label="Save", command=self.save, accelerator="Ctrl+S") fileMenu.add_command(label="Exit", underline=1, command=exit, accelerator="Ctrl+Q") editMenu.add_command(label="Copy", command=self.copy, accelerator="Ctrl+C") editMenu.add_command(label="Cut", command=self.cut, accelerator="Ctrl+X") editMenu.add_command(label="Paste", command=self.paste, accelerator="Ctrl+V") editMenu.add_cascade(label="Font", underline=0, menu=fsubmenu) editMenu.add_cascade(label="Size", underline=0, menu=ssubmenu) editMenu.add_command(label="Color", command=self.color) editMenu.add_command(label="Bold", command=self.bold, accelerator="Ctrl+B") editMenu.add_command(label="Italic", command=self.italic, accelerator="Ctrl+I") editMenu.add_command(label="Underline", command=self.underline, accelerator="Ctrl+U") editMenu.add_command(label="Overstrike", command=self.overstrike, accelerator="Ctrl+T") editMenu.add_command(label="Undo", command=self.undo, accelerator="Ctrl+Z") editMenu.add_command(label="Redo", command=self.redo, accelerator="Ctrl+Y") self.config(menu=menubar) """Accelerator bindings. The cut, copy, and paste functions are not bound to keyboard shortcuts because Windows already binds them, so if Tkinter bound them as well whenever you typed ctrl+v the text would be pasted twice.""" self.bind_all("<Control-n>", self.new) self.bind_all("<Control-o>", self.open) self.bind_all("<Control-s>", self.save) self.bind_all("<Control-q>", self.exit) self.bind_all("<Control-b>", self.bold) self.bind_all("<Control-i>", self.italic) self.bind_all("<Control-u>", self.underline) self.bind_all("<Control-T>", self.overstrike) self.bind_all("<Control-z>", self.undo) self.bind_all("<Control-y>", self.redo) self.text = ScrolledText(self, state='normal', height=30, wrap='word', font = font, pady=2, padx=3, undo=True) self.text.grid(column=0, row=0, sticky='NSEW') # Frame configuration self.grid_columnconfigure(0, weight=1) self.resizable(True, True) """Command functions. *args is included because the keyboard bindings pass two arguments to the functions, while clicking in the menu passes only 1.""" def new(self, *args): """Creates a new window.""" app = Application() app.title('Python Text Editor') app.option_add('*tearOff', False) app.mainloop() def color(self): """Changes selected text color.""" try: (rgb, hx) = tkinter.colorchooser.askcolor() self.text.tag_add('color', 'sel.first', 'sel.last') self.text.tag_configure('color', foreground=hx) except TclError: pass def bold(self, *args): """Toggles bold for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "bold" in current_tags: self.text.tag_remove("bold", "sel.first", "sel.last") else: self.text.tag_add("bold", "sel.first", "sel.last") bold_font = Font(self.text, self.text.cget("font")) bold_font.configure(weight="bold") self.text.tag_configure("bold", font=bold_font) except TclError: pass def italic(self, *args): """Toggles italic for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "italic" in current_tags: self.text.tag_remove("italic", "sel.first", "sel.last") else: self.text.tag_add("italic", "sel.first", "sel.last") italic_font = Font(self.text, self.text.cget("font")) italic_font.configure(slant="italic") self.text.tag_configure("italic", font=italic_font) except TclError: pass def underline(self, *args): """Toggles underline for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "underline" in current_tags: self.text.tag_remove("underline", "sel.first", "sel.last") else: self.text.tag_add("underline", "sel.first", "sel.last") underline_font = Font(self.text, self.text.cget("font")) underline_font.configure(underline=1) self.text.tag_configure("underline", font=underline_font) except TclError: pass def overstrike(self, *args): """Toggles overstrike for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "overstrike" in current_tags: self.text.tag_remove("overstrike", "sel.first", "sel.last") else: self.text.tag_add("overstrike", "sel.first", "sel.last") overstrike_font = Font(self.text, self.text.cget("font")) overstrike_font.configure(overstrike=1) self.text.tag_configure("overstrike", font=overstrike_font) except TclError: pass def undo(self, *args): """Undo function""" try: self.text.edit_undo() except TclError: pass def redo(self, *args): """Redo function""" try: self.text.edit_redo() except TclError: pass def copy(self, *args): """Copy text""" self.clipboard_clear() self.clipboard_append(self.text.selection_get()) def cut(self, *args): """Cut text""" self.copy self.text.delete("sel.first", "sel.last") def paste(self, *args): """Paste text""" insertion = self.selection_get(selection = "CLIPBOARD") self.text.insert(0.0, insertion) def open(self, *args): """Opens a file dialog to open a plain text file.""" filename = tkinter.filedialog.askopenfilename() with open(filename) as f: text = f.read() self.text.delete("1.0", "end") self.text.insert('insert', text) def save(self, *args): try: """Opens a file dialog to save the text in plain text format.""" text = self.text.get("1.0", "end") filename = tkinter.filedialog.asksaveasfilename() with open(filename, 'w') as f: f.write(text) except FileNotFoundError: pass def exit(self, *args): """Exits the program.""" self.quit()
class ChatGUI(Frame): def __init__(self, parent, conn, title): #Frame.__init__(self, parent, background="grey") self.parent = parent self.conn = conn self.title = title self.centerWindow() self.initUI() def initUI(self): self.lineCounter = 0 # create a custom font self.customFontHeader = font.Font(family="Calibri", slant = "italic") #family="Helvetica", weight="bold", slant="italic") self.customFontMessage = font.Font(family="Calibri") self.parent.title(self.title) frame = Frame(self.parent) frame.pack(fill=BOTH, expand=1, side=LEFT) self.box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) self.box.insert(END, 'Welcome to Python Chat!') self.box.config(state=DISABLED) self.box.pack(expand="yes", fill=BOTH, side=TOP) self.textarea = Text(frame, width=30, height=5) #self.textarea.insert(END, "") self.textarea.bind("<KeyRelease-Return>", self.gettext) #Se metto on press, rimane una newline in piu self.textarea.pack(expand="yes", fill=BOTH, side=TOP) okButton = Button(frame, text="Panic Button", activebackground="red", command=self.sendFile) okButton.pack(expand="no", fill=BOTH, side=TOP) self.usersFrame = Frame(self.parent) self.usersFrame.pack(fill=BOTH, expand=1, side=RIGHT) self.userListbox = Listbox(self.usersFrame, width=3) self.userListbox.bind("<Double-Button-1>", self.privateChat) self.userListbox.pack(fill=BOTH, expand=1) self.updateUsersFrame() def centerWindow(self): w = 600 h = 475 sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - w)/2 y = (sh - h)/2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) def gettext(self, e): #e sta per event, questo e' un listener text = self.textarea.get("1.0", END + " - 2c") # 1.0: row:columa - END-2c rimuove l'ultimo carattere, una newline \r\n self.textarea.delete("0.0", END) #NON VA: il problema e' che viene inviato il carattere di newline ma non incluso nell'area a causa della bind mi sa. Devo escluderlo io self.sendToServer(text) def printConversation(self, message): self.box.config(state=NORMAL) self.box.insert(END,"\n" + message) self.lineCounter = self.lineCounter + 2 #m = re.match("\[.*\] From .*\n", self.box.get("0.0", END)) m = re.search("\[.*\].*:", message, re.MULTILINE) if m is not None: #print("MATCH") #print(m.group(0)) #print(str(m.start(0)) + "_" + str(m.end(0))) #print("COUNTER") #print(str(self.lineCounter) + "." + str(m.start(0)+1) + "___" + str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_add("header", str(self.lineCounter) + "." + str(m.start(0)), str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_config("header", font=self.customFontHeader, foreground = "blue") self.box.config(state=DISABLED) #self.box.yview_scroll(10000,"units") self.box.see(END) def sendToServer(self, messageToSend): self.conn.send(messageToSend.encode(encoding='utf_8', errors='strict')) def sendFile(self): #aprire una dialog di quelle predefinite (Sfoglia...) #capire come fare la send di un file sul socket... pass def updateUsersFrame(self): global connectedClients self.userListbox.delete(0, END) self.userListbox.insert(END, "Connected users") for item in connectedClients: self.userListbox.insert(END, item) #self.userListbox.update() #self.usersFrame.update() def privateChat(self, e): global conversationBoxList userselected = self.userListbox.selection_get() if not userselected == "Connected users": print("EVVAI CHAT PRIVATA con "+userselected) newWindow = Toplevel(self.parent) newWindow.title("Python Chat with "+userselected) newWindow.minsize(400, 475) newWindow.focus() def disconnectPM(): del conversationBoxList[userselected] newWindow.destroy() newWindow.protocol('WM_DELETE_WINDOW', disconnectPM) #label = Label(newWindow, text="PROVA PROVA") #label.pack(side="top", fill="both", padx=10, pady=10) frame = Frame(newWindow) frame.pack(fill=BOTH, expand=1, side=LEFT) box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) box.config(state=DISABLED) box.pack(expand="yes", fill=BOTH, side=TOP) textarea = Text(frame, width=30, height=5) textarea.bind("<KeyRelease-Return>", lambda event : self.getprivatetext(event, textarea, userselected)) textarea.pack(expand="yes", fill=BOTH, side=TOP) #aggiungo alla mappa globale il box di conversazione conversationBoxList[userselected] = box def receivePrivateChat(self, connectingUser): global conversationBoxList print("CHAT PRIVATA in arrivo con "+connectingUser) newWindow = Toplevel(self.parent) newWindow.title("Python Chat requested by "+connectingUser) newWindow.minsize(400, 475) newWindow.focus() def disconnectPM(): del conversationBoxList[connectingUser] newWindow.destroy() newWindow.protocol('WM_DELETE_WINDOW', disconnectPM) #label = Label(newWindow, text="PROVA PROVA") #label.pack(side="top", fill="both", padx=10, pady=10) frame = Frame(newWindow) frame.pack(fill=BOTH, expand=1, side=LEFT) box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) box.config(state=DISABLED) box.pack(expand="yes", fill=BOTH, side=TOP) textarea = Text(frame, width=30, height=5) textarea.bind("<KeyRelease-Return>", lambda event : self.getprivatetext(event, textarea, connectingUser)) textarea.pack(expand="yes", fill=BOTH, side=TOP) #aggiungo alla mappa globale il box di conversazione conversationBoxList[connectingUser] = box def getprivatetext(self, e, textarea, nickname): text = textarea.get("1.0", END + " - 2c") textarea.delete("0.0", END) self.sendToServer("##" + nickname + "##" + text) def setprivatetext(self, nickname, message, isLocalMessage): #isLocalMessage identifica un messaggio che mando io e che devo ri-ricevere nella mia finestra if isLocalMessage: for i in conversationBoxList.keys(): box = conversationBoxList[i] box.config(state=NORMAL) box.insert(END,"\n" + message) box.config(state=DISABLED) box.see(END) else: conversationbox = conversationBoxList[nickname] conversationbox.config(state=NORMAL) conversationbox.insert(END,"\n" + message) #self.lineCounter = self.lineCounter + 2 #m = re.match("\[.*\] From .*\n", self.box.get("0.0", END)) #m = re.search("\[.*\].*:", message, re.MULTILINE) ''' if m is not None: #print("MATCH") #print(m.group(0)) #print(str(m.start(0)) + "_" + str(m.end(0))) #print("COUNTER") #print(str(self.lineCounter) + "." + str(m.start(0)+1) + "___" + str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_add("header", str(self.lineCounter) + "." + str(m.start(0)), str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_config("header", font=self.customFontHeader, foreground = "blue") ''' conversationbox.config(state=DISABLED) #self.box.yview_scroll(10000,"units") conversationbox.see(END)
#! python3 # noqa: E265 """ To test https://github.com/Guts/DicoGIS/issues/18 """ import tkinter as tk import tkinter.font as tkfont from tkinter.scrolledtext import ScrolledText root = tk.Tk() frame = tk.LabelFrame(root, text="Polices") frame.grid() ft = tkfont.families() txt = ScrolledText(frame, width=50, height=20) txt.grid() txt.insert("1.0", "Polices:\n") txt.tag_add("tagpolices", "1.0", "insert") for i, f in enumerate(ft): font = tkfont.Font(frame, size=20, family=f) tag = f"tag{i}" txt.tag_config(tag, font=font) txt.insert("end", f, tag, "\n") root.mainloop()
class App(Frame): """Гланое окно приложения""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # screen_width = self.winfo_screenwidth() # print(screen_width, self.winfo_screenheight()) self.master.title(f'Mem-translate {__version__}') self.master.minsize(300, 200) menu = Menu(self.master) self.master.configure(menu=menu) menu_file = Menu(menu) menu_file.add_command(label='Импорт', command=self.on_import) menu.add_cascade(label='Файл', menu=menu_file) width = 73 self.text = ScrolledText(self, bg='white', height=31, width=width, undo=True, wrap='word') self.text['font'] = DEFAULT_FONT self.text.tag_configure(TAG_BLUE, background='#aaf') self.text.focus_set() self.text.bind('<Key>', self.on_key_text) self.text.grid_configure(row=0, column=0, rowspan=2) self.text_fuzz = ScrolledText(self, bg='white', height=15, width=width, wrap='word') self.text_fuzz['font'] = DEFAULT_FONT self.text_fuzz.tag_configure(TAG_BLUE, background='#afa') self.text_fuzz.bind('<Key>', lambda event: 'break') self.text_fuzz.grid_configure(row=0, column=1, sticky='n') self.text_tran = ScrolledText(self, bg='white', height=15, width=width, wrap='word') self.text_tran['font'] = DEFAULT_FONT self.text_tran.bind('<Key>', lambda event: 'break') self.text_tran.grid_configure(row=1, column=1, sticky='s') self.grid_configure() def destroy(self): # todo log.info('destroy') super().destroy() def on_import(self): """Обработчик кнопки Импорт""" filename = Open(initialdir='../you-can/source/', filetypes=(('Текст', '*.txt'),)).show() text_ls = do_import(filename) self.do_open(text_ls) def do_open(self, text_ls: List[str]): """Отрисовать текст""" for line in text_ls: self.text.insert('end', line) # добавляем немного подсветки # if not line.startswith(PREFIX_TRANSLATE) and line != PREFIX_CUT: if not line.startswith('>>>'): i = self.text.index('insert').split('.', 1)[0] self.text.tag_add(TAG_BLUE, f'{i}.0', f'{i}.{len(line)}') self.text.insert('end', '\n') log.debug(self.text.tag_ranges(TAG_BLUE)) def on_key_text(self, event): """Обработчик нажатий любой клавиши в главном textArea""" if event.keycode == 36: # Return self.do_enter() return 'break' log.debug(event) def do_enter(self): tag_range = self.text.tag_nextrange(TAG_BLUE, self.text.index('insert')) if not tag_range: return index1, index2 = tag_range # двигаем курсор index = int(index2.split('.')[0]) + 1 self.text.mark_set('insert', f'{index}.{len(PREFIX_TRANSLATE)}') self.text.see('insert') text: str = self.text.get(index1, index2) # переводим текст self.text_tran.delete('1.0', 'end') start_new_thread(self.thread_translate, (text,)) # ... self.text_fuzz.delete('1.0', 'end') start_new_thread(self.thread_fuzz, (text,)) def thread_translate(self, text: str): """Асинхронно запускаем машинный перевод""" try: text2 = translate_yandex(text) except BaseException as ex: text2 = str(ex) self.text_tran.insert('1.0', text2) def thread_fuzz(self, text: str): """Асинхронно ищем нечёткие совпадения""" # todo закешировать + парсить перевод + перенести в text.py ls: list = self.text.get('1.0', 'end').split('\n') ls.remove(text) choices = [f'{i + 1}: {line}' for i, line in enumerate(ls) if not line.startswith('>>>')] # result = [f'{line} ({p})' for line, p in extractBests(text, choices, score_cutoff=1, limit=7)] # result = [(line, fuzz.token_set_ratio(line, text)) for line in choices] ww = set(re.findall(r'\w{4,}', text)) - {'that', 'That', 'only', 'Only'} result = [] for line in choices: p = len(set(re.findall(r'\w{4,}', line)) & ww) if p > 0: result.append((line, p)) result = heapq.nlargest(7, result, key=lambda x: x[1]) result = [line for line, p in result] # self.text_fuzz.insert('1.0', '\n'.join(result)) for line in result: self.text_fuzz.insert('end', line) i = self.text_fuzz.index('insert').split('.', 1)[0] # for m in SequenceMatcher(None, line.lower(), text.lower()).get_matching_blocks(): # self.text_fuzz.tag_add(TAG_BLUE, f'{i}.{m.a}', f'{i}.{m.a + m.size}') for w in ww: for m in re.finditer(w, line): self.text_fuzz.tag_add(TAG_BLUE, f'{i}.{m.start()}', f'{i}.{m.end()}') self.text_fuzz.insert('end', '\n')
class PiDiteur(Frame): def __init__(self, parent=None, nom_fichier=None): Frame.__init__(self, parent) self.pack(expand=YES, fill=BOTH) self.fichier_courant = nom_fichier self.nom_editeur = self.__class__.__name__ self.creer_composants() self.gerer_evenements() self.afficher_fichier(nom_fichier) def creer_composants(self): self.creer_zone_texte() self.creer_barre_menu() self.creer_barre_texte() def creer_zone_texte(self): self.zone_texte = ScrolledText( self, padx=5, pady=5, wrap=WORD, relief=SUNKEN, font=("courier", 14, "normal"), bg="white", fg="black", undo=True, autoseparators=True, ) self.zone_texte.pack(side=TOP, fill=BOTH, expand=YES) def creer_barre_texte(self): self.barre_texte = Label(self, relief=SUNKEN, bd=2) self.barre_texte.pack(side=BOTTOM, fill=X) def creer_barre_menu(self): self.barre_menu = Menu(self.master) self.master.config(menu=self.barre_menu) self.menu_fichier() self.menu_editer() def menu_fichier(self): menu = Menu(self.barre_menu, tearoff=False) menu.add_command(label="Ouvrir (Ctrl+o)", command=self.ouvrir) menu.add_command(label="Nouveau (Ctrl+n)", command=self.afficher_fichier) menu.add_command(label="Enregistrer (Ctrl+s)", command=self.enregistrer) menu.add_command(label="Enregistrer sous", command=self.enregistrer_sous) menu.add_command(label="Fermer (Alt+F4)", command=self.quitter) self.barre_menu.add_cascade(label="Fichier", menu=menu) def menu_editer(self): menu = Menu(self.barre_menu, tearoff=False) menu.add_command(label="Couper (Ctrl+x)", command=lambda: self.copier(True)) menu.add_command(label="Copier (Ctrl+c)", command=self.copier) menu.add_command(label="Coller (Ctrl+v)", command=self.coller) menu.add_command(label="Chercher (Ctrl+f)", command=self.chercher) self.barre_menu.add_cascade(label="Edition", menu=menu) def gerer_evenements(self): self.master.bind("<Control-Key-f>", lambda ev: self.chercher()) self.master.bind("<Control-Key-o>", lambda ev: self.ouvrir()) self.master.bind("<Control-Key-s>", lambda ev: self.enregistrer()) self.master.bind("<Control-Key-n>", lambda ev: self.afficher_fichier()) self.master.protocol("WM_DELETE_WINDOW", self.quitter) def afficher_fichier(self, nom_fichier=None): if nom_fichier: with open(nom_fichier, "r", encoding="utf-8") as f: texte = f.read() self.barre_texte.config(text=nom_fichier) self.master.title("%s - %s" % (self.nom_editeur, nom_fichier)) else: texte = "" nouveau = "Nouveau fichier" self.barre_texte.config(text=nouveau) self.master.title("%s - %s" % (self.nom_editeur, nouveau)) self.fichier_courant = nom_fichier self.zone_texte.delete("0.0", END) self.zone_texte.insert("0.0", texte) self.zone_texte.mark_set(INSERT, "0.0") self.zone_texte.focus() self.update() def ouvrir(self): fichier = askopenfilename() if fichier: self.afficher_fichier(nom_fichier=fichier) def enregistrer(self): if not self.fichier_courant: fichier = asksaveasfilename() if fichier: self.fichier_courant = fichier else: return fichier = self.fichier_courant texte = self.zone_texte.get("0.0", END) with open(fichier, "w", encoding="utf-8") as f: f.write(texte) self.barre_texte.config(text=fichier) self.master.title("{} - {}".format(self.nom_editeur, fichier)) def enregistrer_sous(self): fichier = asksaveasfilename() if fichier: self.fichier_courant = fichier self.enregistrer() def copier(self, couper=False): try: texte = self.zone_texte.get(SEL_FIRST, SEL_LAST) except TclError: showinfo(message="Selectionnez du texte à copier !") return if couper: self.zone_texte.delete(SEL_FIRST, SEL_LAST) self.clipboard_clear() self.clipboard_append(texte) def coller(self): try: texte = self.selection_get(selection="CLIPBOARD") self.zone_texte.insert(INSERT, texte) except TclError: pass def chercher(self): caractere = askstring("Recherche", "Tapez votre chaîne de caractères :") if caractere: trouve = self.zone_texte.search(caractere, INSERT, END) if trouve: aprestrouve = trouve + ("+%dc" % len(caractere)) self.zone_texte.tag_add(SEL, trouve, aprestrouve) self.zone_texte.mark_set(INSERT, aprestrouve) self.zone_texte.see(INSERT) self.zone_texte.focus() def quitter(self): if askyesno("Confirmation", f"Voulez-vous vraiment fermer {self.nom_editeur} ?"): Frame.quit(self)
class ChatForm(tk.Frame): font_color = "#000000" font_size = 10 user_list = [] tag_i = 0 def remove_listener_and_close(self): remove_message_listener(self.message_listener) client.util.socket_listener.remove_listener(self.socket_listener) self.master.destroy() if self.target['id'] in client.memory.window_instance[self.target['type']]: del client.memory.window_instance[self.target['type']][self.target['id']] def message_listener(self, data): self.digest_message(data) def socket_listener(self, data): if data['type'] == MessageType.query_room_users_result: if data['parameters'][1] != self.target['id']: return # [id, nickname, online, username] self.user_list = data['parameters'][0] self.refresh_user_listbox() if data['type'] == MessageType.room_user_on_off_line: # [room_id, user_id, online] if data['parameters'][0] != self.target['id']: return for i in range(0, len(self.user_list)): if self.user_list[i][0] == data['parameters'][1]: self.user_list[i][2] = data['parameters'][2] self.refresh_user_listbox() def refresh_user_listbox(self): # [id, nickname, online, username] self.user_listbox.delete(0, END) self.user_list.sort(key=lambda x: x[2]) for user in self.user_list: self.user_listbox.insert(0, user[1] + ("(在线)" if user[2] else "(离线)")) self.user_listbox.itemconfig(0, {'fg': ("green" if user[2] else "#999")}) def digest_message(self, data): time = datetime.datetime.fromtimestamp( int(data['time']) / 1000 ).strftime('%Y-%m-%d %H:%M:%S') self.append_to_chat_box(data['sender_name'] + " " + time + '\n', ('me' if client.memory.current_user['id'] == data[ 'sender_id'] else 'them')) # type 0 - 文字消息 1 - 图片消息 if data['message']['type'] == 0: self.tag_i += 1 self.chat_box.tag_config('new' + str(self.tag_i), lmargin1=16, lmargin2=16, foreground=data['message']['fontcolor'], font=(None, data['message']['fontsize'])) self.append_to_chat_box(data['message']['data'] + '\n', 'new' + str(self.tag_i)) if data['message']['type'] == 1: client.memory.tk_img_ref.append(ImageTk.PhotoImage(data=data['message']['data'])) self.chat_box.image_create(END, image=client.memory.tk_img_ref[-1], padx=16, pady=5) self.append_to_chat_box('\n', '') def user_listbox_double_click(self, _): if len(self.user_listbox.curselection()) == 0: return None index = self.user_listbox.curselection()[0] selected_user_id = self.user_list[len(self.user_list) - 1 - index][0] selected_user_nickname = self.user_list[len(self.user_list) - 1 - index][1] selected_user_username = self.user_list[len(self.user_list) - 1 - index][3] if selected_user_id == client.memory.current_user['id']: return client.memory.contact_window[0].try_open_user_id(selected_user_id, selected_user_nickname, selected_user_username) # pprint(selected_user_id) return def __init__(self, target, master=None): super().__init__(master) self.master = master self.target = target self.user_listbox = tk.Listbox(self, bg='#EEE') client.util.socket_listener.add_listener(self.socket_listener) client.memory.unread_message_count[self.target['type']][self.target['id']] = 0 client.memory.contact_window[0].refresh_contacts() master.resizable(width=True, height=True) master.geometry('660x500') master.minsize(520, 370) self.sc = client.memory.sc if self.target['type'] == 0: self.master.title(self.target['nickname']) if self.target['type'] == 1: self.master.title("群:" + str(self.target['id']) + " " + self.target['room_name']) self.sc.send(MessageType.query_room_users, self.target['id']) self.right_frame = tk.Frame(self, bg='white') self.user_listbox.bind('<Double-Button-1>', self.user_listbox_double_click) if self.target['type'] == 1: self.user_listbox.pack(side=LEFT, expand=False, fill=BOTH) self.right_frame.pack(side=LEFT, expand=True, fill=BOTH) self.input_frame = tk.Frame(self.right_frame, bg='white') self.input_textbox = ScrolledText(self.right_frame, height=10) self.input_textbox.bind("<Control-Return>", self.send_message) self.input_textbox.bind_all('<Key>', self.apply_font_change) self.send_btn = tk.Button(self.input_frame, text='发送消息(Ctrl+Enter)', command=self.send_message) self.send_btn.pack(side=RIGHT, expand=False) self.font_btn = tk.Button(self.input_frame, text='字体颜色', command=self.choose_color) self.font_btn.pack(side=LEFT, expand=False) self.font_btn = tk.Button(self.input_frame, text='字体大小', command=self.choose_font_size) self.font_btn.pack(side=LEFT, expand=False) self.image_btn = tk.Button(self.input_frame, text='发送图片', command=self.send_image) self.image_btn.pack(side=LEFT, expand=False) self.chat_box = ScrolledText(self.right_frame, bg='white') self.input_frame.pack(side=BOTTOM, fill=X, expand=False) self.input_textbox.pack(side=BOTTOM, fill=X, expand=False, padx=(0, 0), pady=(0, 0)) self.chat_box.pack(side=BOTTOM, fill=BOTH, expand=True) self.chat_box.bind("<Key>", lambda e: "break") self.chat_box.tag_config("default", lmargin1=10, lmargin2=10, rmargin=10) self.chat_box.tag_config("me", foreground="green", spacing1='5') self.chat_box.tag_config("them", foreground="blue", spacing1='5') self.chat_box.tag_config("message", foreground="black", spacing1='0') self.chat_box.tag_config("system", foreground="grey", spacing1='0', justify='center', font=(None, 8)) self.pack(expand=True, fill=BOTH) add_message_listener(self.target['type'], self.target['id'], self.message_listener) master.protocol("WM_DELETE_WINDOW", self.remove_listener_and_close) # 历史消息显示 if target['id'] in client.memory.chat_history[self.target['type']]: for msg in client.memory.chat_history[self.target['type']][target['id']]: self.digest_message(msg) self.append_to_chat_box('- 以上是历史消息 -\n', 'system') def append_to_chat_box(self, message, tags): self.chat_box.insert(tk.END, message, [tags, 'default']) self.chat_box.update() self.chat_box.see(tk.END) def send_message(self, _=None): message = self.input_textbox.get("1.0", END) if not message or message.replace(" ", "").replace("\r", "").replace("\n", "") == '': return self.sc.send(MessageType.send_message, {'target_type': self.target['type'], 'target_id': self.target['id'], 'message': { 'type': 0, 'data': message.strip().strip('\n'), 'fontsize': self.font_size, 'fontcolor': self.font_color } }) self.input_textbox.delete("1.0", END) return 'break' def choose_color(self): _, self.font_color = colorchooser.askcolor(initialcolor=self.font_color) self.apply_font_change(None) def choose_font_size(self): result = simpledialog.askinteger("设置", "请输入字体大小", initialvalue=self.font_size) if result is None: return self.font_size = result self.apply_font_change(None) def apply_font_change(self, _): try: self.input_textbox.tag_config('new', foreground=self.font_color, font=(None, self.font_size)) self.input_textbox.tag_add('new', '1.0', END) except: pass def send_image(self): filename = filedialog.askopenfilename(filetypes=[("Image Files", ["*.jpg", "*.jpeg", "*.png", "*.gif", "*.JPG", "*.JPEG", "*.PNG", "*.GIF"]), ("All Files", ["*.*"])]) if filename is None or filename == '': return with open(filename, "rb") as imageFile: f = imageFile.read() b = bytearray(f) self.sc.send(MessageType.send_message, {'target_type': self.target['type'], 'target_id': self.target['id'], 'message': {'type': 1, 'data': b}})
text='Top K:', font=('Microsoft YaHei', 12), width=15, height=1, ).grid(row=3, column=0) entry_top_k = tk.Entry(main_window, width=100) entry_top_k.insert(0, '20') entry_top_k.grid(row=3, column=1) button_execute = tk.Button(main_window, text="Execute", width=15, height=1, command=execute).grid(row=3, column=2) button_file = tk.Button(main_window, text="Browse", width=15, height=1, command=open_filedialog).grid(row=0, column=2) text_output = ScrolledText(main_window, width=135, height=25, undo=True, font=('Microsoft YaHei', 12)) text_output.grid(row=4, column=0, columnspan=4) text_output.tag_add("start", "1.8", "1.13") text_output.tag_config("start", background="black", foreground="white") main_window.mainloop()
def makewidgets(self): frm = ttk.Frame(self.parent) frm.grid(row=1, column=0, sticky=ALL) tex = ScrolledText(frm, width=70, height=20, bg='black', fg='green') tex.grid(row=1, column=2, rowspan=2, sticky=ALL) msg = _('Backup Application') tex.insert(END, msg.center(70, '*')) tex.tag_add('protigrammi', '1.0', '1.end') tex.tag_config('protigrammi', background='green', foreground='black') # tex.tag_add('ln', '2.0') tex.tag_bind('protigrammi', '<Double-1>', self.creditbind) tex.config(state=DISABLED) self.tex = tex lblfrm1 = ttk.LabelFrame(frm, text=_('Files')) lblfrm1.grid(row=1, column=0, sticky=ALL) lblfrm1.columnconfigure(0, weight=1) lboxfiles = Listbox(lblfrm1, width=40, height=10, selectmode=EXTENDED) lboxfiles.grid(row=0, column=0, sticky=ALL) self.lboxfiles = lboxfiles self.lboxfiles.bind('<Double-1>', self.OnDouble) #Να το παιδέψω. self.lboxfiles.bind('<Button-3>', self.OnDouble) vsb01 = ttk.Scrollbar(lblfrm1, orient="vertical", command=self.lboxfiles.yview) self.lboxfiles.configure(yscrollcommand=vsb01.set) vsb01.grid(row=0, column=1, sticky=N + S) # btndel1 = ttk.Button(lblfrm1, text='Διαγραφή Επιλεγμένου', command=lambda: self.del_frm_list(None, self.lboxfiles)) # btndel1.grid(sticky=S) lblfrm2 = ttk.LabelFrame(frm, text=_('Directories')) lblfrm2.grid(row=2, column=0, sticky=ALL) lblfrm2.columnconfigure(0, weight=1) lboxdirs = Listbox(lblfrm2, width=40, height=10, selectmode=EXTENDED) lboxdirs.grid(row=0, column=0, stick=ALL) self.lboxdirs = lboxdirs self.lboxdirs.bind('<Double-1>', self.OnDouble) self.lboxdirs.bind('<Button-3>', self.OnDouble) vsb = ttk.Scrollbar(lblfrm2, orient='vertical', command=self.lboxdirs.yview) self.lboxdirs.configure(yscrollcommand=vsb.set) vsb.grid(row=0, column=1, sticky=N + S) lblfrmradio = ttk.LabelFrame(frm, text=_('Select File Type')) lblfrmradio.grid(row=1, column=3, sticky=N) rdiozip = ttk.Radiobutton( lblfrmradio, width=20, text=_('Zip File'), command=lambda: self.change_filename(self.ent.get()), variable=self.typefile, value='typezip') rdiozip.grid(row=0, column=0) rdiotar = ttk.Radiobutton( lblfrmradio, width=20, text=_('Tar File'), command=lambda: self.change_filename(self.ent.get()), variable=self.typefile, value='typetar') rdiotar.grid(row=1, column=0) self.typefile.set('typezip') lblfrmmode = ttk.Labelframe(frm, text=_('Open File')) lblfrmmode.grid(row=1, column=3, sticky=S) rdioappend = ttk.Radiobutton(lblfrmmode, text=_('add files and comments'), variable=self.filemode, value='a') rdioappend.grid(row=0, column=0, sticky=W) rdiowrite = ttk.Radiobutton(lblfrmmode, text=_('new for add files'), variable=self.filemode, value='w') rdiowrite.grid(row=1, column=0, sticky=W) self.filemode.set('w') ent = ttk.Entry(frm) ent.grid(row=4, column=0, columnspan=2, sticky=W + E) ent.insert( 0, os.path.normpath(os.path.join(os.path.expanduser('~'), 'zip.zip'))) self.ent = ent # defaultchk = ttk.Checkbutton(frm, text=_('Most recent file'), state=DISABLED, command='') # defaultchk.grid(row=1, column=3, sticky=W+E) sp1 = ttk.Separator(frm) sp1.grid(row=3, column=0, columnspan=4, sticky=W + E) lbl = ttk.Label(frm, textvariable=self.msg) lbl.grid(row=4, column=2, sticky=N + S + W + E) sp2 = ttk.Separator(frm) sp2.grid(row=5, column=0, columnspan=4, sticky=W + E) # lblcomment = ttk.Label(frm, text = _('Write your comment:')) # lblcomment.grid(row=2, column=3, sticky=N+W+E) lblfrmaddcomment = ttk.LabelFrame(frm, text=_('Write your comment:')) lblfrmaddcomment.grid(row=2, column=3, sticky=W) entcomment = ttk.Entry(lblfrmaddcomment, width=30) entcomment.grid(row=2, column=3, sticky=W) self.entcomment = entcomment for child in frm.winfo_children(): child.grid_configure(pady=4, padx=4) self.parent.columnconfigure(0, weight=1) self.parent.rowconfigure(1, weight=1) for x in range(frm.grid_size()[0] - 1): frm.columnconfigure(x, weight=1) for x in range(frm.grid_size()[1] - 1): frm.rowconfigure(x, weight=1) self.parent.update_idletasks()
class ChatForm(tk.Frame): font_color = "#000000" font_size = 16 user_list = [] tag_i = 0 """将监听事件移除并关闭该窗口""" def remove_listener_and_close(self): remove_message_listener(self.message_listener) client.util.socket_listener.remove_listener(self.socket_listener) self.master.destroy() if self.target['id'] in client.memory.window_instance[self.target['type']]: del client.memory.window_instance[self.target['type']][self.target['id']] """定义监听事件""" def message_listener(self, data): self.digest_message(data) """监听socket传来的数据""" def socket_listener(self, data): init_time = int(time.time()) dirname = "send_msg_log" filename = str(init_time) dir_flag = os.path.exists(dirname) if dir_flag == False: os.mkdir(dirname) if data['parameters']['message']['type'] == 1: with open(dirname + '/' + filename, 'wb') as f: contents = data['parameters']['message']['data'] f.write(contents) f.close() with open(dirname + '/' + filename, 'rb') as f: file_format = filetype.guess(dirname + '/' + filename) file_format = file_format.extension if file_format == None: file_format = "txt" f.close() os.rename(dirname + '/' + filename, (str(dirname + '/' + filename) + '_.' + file_format)) if data['type'] == MessageType.query_room_users_result: if data['parameters'][1] != self.target['id']: return self.user_list = data['parameters'][0] self.refresh_user_listbox() if data['type'] == MessageType.room_user_on_off_line: if data['parameters'][0] != self.target['id']: return for i in range(0, len(self.user_list)): if self.user_list[i][0] == data['parameters'][1]: self.user_list[i][2] = data['parameters'][2] self.refresh_user_listbox() """更新好友列表""" def refresh_user_listbox(self): self.user_listbox.delete(0, END) self.user_list.sort(key=lambda x: x[2]) for user in self.user_list: self.user_listbox.insert(0, user[1] + ("(在线)" if user[2] else "(离线)")) self.user_listbox.itemconfig(0, {'fg': ("blue" if user[2] else "#505050")}) """处理消息并将其展示出来""" def digest_message(self, data): time = datetime.datetime.fromtimestamp( int(data['time']) / 1000 ).strftime('%Y-%m-%d %H:%M:%S') self.append_to_chat_box(data['sender_name'] + " " + time + '\n', ('me' if client.memory.current_user['id'] == data[ 'sender_id'] else 'them')) # type 0 - 文字消息 1 - 图片消息 if data['message']['type'] == 0: self.tag_i += 1 self.chat_box.tag_config('new' + str(self.tag_i), lmargin1=16, lmargin2=16, foreground=data['message']['fontcolor'], font=(None, data['message']['fontsize'])) self.append_to_chat_box(data['message']['data'] + '\n', 'new' + str(self.tag_i)) if data['message']['type'] == 1: client.memory.tk_img_ref.append(ImageTk.PhotoImage(data=data['message']['data'])) self.chat_box.image_create(END, image=client.memory.tk_img_ref[-1], padx=16, pady=5) self.append_to_chat_box('\n', '') """ 双击聊天框 """ def user_listbox_double_click(self, _): if len(self.user_listbox.curselection()) == 0: return None index = self.user_listbox.curselection()[0] selected_user_id = self.user_list[len(self.user_list) - 1 - index][0] selected_user_username = self.user_list[len(self.user_list) - 1 - index][3] if selected_user_id == client.memory.current_user['id']: return client.memory.contact_window[0].try_open_user_id(selected_user_id, selected_user_username) return def __init__(self, target, master=None): super().__init__(master) self.master = master self.target = target self.user_listbox = tk.Listbox(self, bg='#63d5eb', width=0, bd=0) client.util.socket_listener.add_listener(self.socket_listener) client.memory.unread_message_count[self.target['type']][self.target['id']] = 0 client.memory.contact_window[0].refresh_contacts() master.resizable(width=False, height=False) master.geometry('580x500') self.sc = client.memory.sc # 私人聊天 if self.target['type'] == 0: self.master.title(self.target['username']) # 群组聊天 if self.target['type'] == 1: self.master.title("[群:" + str(self.target['id']) + "] " + self.target['room_name']) self.sc.send(MessageType.query_room_users, self.target['id']) self.right_frame = tk.Frame(self) self.user_listbox.bind('<Double-Button-1>', self.user_listbox_double_click) if self.target['type'] == 1: self.user_listbox.pack(side=LEFT, expand=False, fill=BOTH) self.right_frame.pack(side=LEFT, expand=True, fill=BOTH) self.input_frame = tk.Frame(self.right_frame, bg='#63d5eb') self.input_textbox = ScrolledText(self.right_frame, bg='#63d5eb', font=("楷书", 16), height=5) self.input_textbox.bind("<Control-Return>", self.send_message) self.input_textbox.bind_all('<Key>', self.apply_font_change) self.send_btn = tk.Button(self.input_frame, text='发送消息(Ctrl+Enter)', font=("仿宋", 16, 'bold'), fg="black", bg="#35d1e9",activebackground="#6cdcf0", relief=GROOVE, command=self.send_message) self.send_btn.pack(side=RIGHT, expand=False) self.font_btn = tk.Button(self.input_frame, text='字体颜色', font=("仿宋", 16, 'bold'), fg="black", bg="#35d1e9", activebackground="#6cdcf0", relief=GROOVE, command=self.choose_color) self.font_btn.pack(side=LEFT, expand=False) self.font_btn = tk.Button(self.input_frame, text='字体大小', font=("仿宋", 16, 'bold'), fg="black", bg="#35d1e9", activebackground="#6cdcf0", relief=GROOVE, command=self.choose_font_size) self.font_btn.pack(side=LEFT, expand=False) self.image_btn = tk.Button(self.input_frame, text='发送文件', font=("仿宋", 16, 'bold'), fg="black", bg="#35d1e9", activebackground="#6cdcf0", relief=GROOVE, command=self.send_image) self.image_btn.pack(side=LEFT, expand=False) self.chat_box = ScrolledText(self.right_frame, bg='#70d5eb') self.input_frame.pack(side=BOTTOM, fill=X, expand=False) self.input_textbox.pack(side=BOTTOM, fill=X, expand=False, padx=(0, 0), pady=(0, 0)) self.chat_box.pack(side=BOTTOM, fill=BOTH, expand=True) self.chat_box.bind("<Key>", lambda e: "break") self.chat_box.tag_config("default", lmargin1=10, lmargin2=10, rmargin=10, font=("仿宋", 15)) self.chat_box.tag_config("me", foreground="green", spacing1='0', font=("仿宋", 15)) self.chat_box.tag_config("them", foreground="blue", spacing1='0', font=("仿宋", 15)) self.chat_box.tag_config("message", foreground="black", spacing1='0', font=("楷体", 15)) self.chat_box.tag_config("system", foreground="#505050", spacing1='0', justify='center', font=("新宋体", 10)) self.pack(expand=True, fill=BOTH) add_message_listener(self.target['type'], self.target['id'], self.message_listener) master.protocol("WM_DELETE_WINDOW", self.remove_listener_and_close) # 历史消息显示 if target['id'] in client.memory.chat_history[self.target['type']]: for msg in client.memory.chat_history[self.target['type']][target['id']]: self.digest_message(msg) self.append_to_chat_box('- 以上是历史消息 -\n', 'system') """ 附加聊天框 """ def append_to_chat_box(self, message, tags): self.chat_box.insert(tk.END, message, [tags, 'default']) self.chat_box.update() self.chat_box.see(tk.END) """ 发送消息 """ def send_message(self, _=None): message = self.input_textbox.get("1.0", END) if not message or message.replace(" ", "").replace("\r", "").replace("\n", "") == '': return self.sc.send(MessageType.send_message, {'target_type': self.target['type'], 'target_id': self.target['id'], 'message': { 'type': 0, 'data': message.strip().strip('\n'), 'fontsize': self.font_size, 'fontcolor': self.font_color } }) self.input_textbox.delete("1.0", END) return 'break' """ 选择字体颜色 """ def choose_color(self): _, self.font_color = colorchooser.askcolor(initialcolor=self.font_color) self.apply_font_change(None) """ 选择字体大小 """ def choose_font_size(self): result = simpledialog.askinteger("设置", "请输入字体大小", initialvalue=self.font_size) if result is None: return self.font_size = result self.apply_font_change(None) """" 更新字体 """ def apply_font_change(self, _): try: self.input_textbox.tag_config('new', foreground=self.font_color, font=(None, self.font_size)) self.input_textbox.tag_add('new', '1.0', END) except: pass """" 发送图片 """ def send_image(self): filename = filedialog.askopenfilename(filetypes=[("Image Files", ["*.jpg", "*.jpeg", "*.png", "*.gif", "*.JPG", "*.JPEG", "*.PNG", "*.GIF"]), ("All Files", ["*.*"])]) if filename is None or filename == '': return with open(filename, "rb") as imageFile: f = imageFile.read() b = bytearray(f) self.sc.send(MessageType.send_message, {'target_type': self.target['type'], 'target_id': self.target['id'], 'message': {'type': 1, 'data': b}})
class MY_GUI(): def __init__(self, init_window_name): self.init_window_name = init_window_name self.max1 = "" self.filename = "" #设置窗口 def set_init_window(self): # 设置输入输出框字体 ft = tkFont.Font(family='宋体', size=15) self.init_window_name.title("电子病历标注工具_v1.3 ") #窗口名 #self.init_window_name.geometry('320x160+10+10') #290 160为窗口大小,+10 +10 定义窗口弹出时的默认展示位置 self.init_window_name.geometry('1500x1000+10+10') #self.init_window_name["bg"] = "pink" #窗口背景色,其他背景色见:blog.csdn.net/chl0000/article/details/7657887 #self.init_window_name.attributes("-alpha",0.9) #虚化,值越小虚化程度越高 #标签 self.init_data_label = ttk.Label(self.init_window_name, text="待处理数据") self.init_data_label.grid(row=0, column=0) self.result_data_label = ttk.Label(self.init_window_name, text="输出结果") self.result_data_label.grid(row=0, column=12) self.log_label = ttk.Label(self.init_window_name, text="日志") self.log_label.grid(row=12, column=0) self.cursorIndex = Label(self.init_window_name, text=("row: %s\ncol: %s" % (0, 0))) self.cursorIndex.grid(row=10, column=15, pady=4) #文本框 self.init_data_Text = ScrolledText(self.init_window_name, width=67, height=35, font=ft) #原始数据录入框 self.init_data_Text.grid(row=1, column=0, rowspan=10, columnspan=10) self.result_data_Text = ScrolledText(self.init_window_name, width=70, height=49, font=ft) #处理结果展示 self.result_data_Text.grid(row=1, column=12, rowspan=15, columnspan=10) self.log_data_Text = ScrolledText(self.init_window_name, width=66, height=9) # 日志框 self.log_data_Text.grid(row=13, column=0, columnspan=10) self.init_data_Text.bind("<Button-1>", self.button_start) self.init_data_Text.bind("<ButtonRelease-1>", self.button_end) #按钮 # self.str_trans_to_md5_button = Button(self.init_window_name, text="字符串转MD5", bg="lightblue", width=10,command=self.str_trans_to_md5) # 调用内部方法 加()为直接调用 # self.str_trans_to_md5_button.grid(row=1, column=11) #导入文件按钮 self.input_button = ttk.Button(self.init_window_name, text="导入文件", width=8, command=self.openfile) self.input_button.grid(row=0, column=2) # 输入窗口清空按钮 self.delet_input_button = ttk.Button(self.init_window_name, text="一键清空", width=8, command=self.delet_ofInput) self.delet_input_button.grid(row=0, column=3) #展示窗口清空按钮 self.delet_result_button = ttk.Button(self.init_window_name, text="一键清空", width=8, command=self.delet_ofResult) self.delet_result_button.grid(row=0, column=13) #导出文件按钮 self.output_button = ttk.Button(self.init_window_name, text="导出文件", width=8, command=self.outputfile) self.output_button.grid(row=0, column=14) #标记解剖部位按钮 self.show_button = ttk.Button(self.init_window_name, text="解剖部位", width='8', command=self.show_jpbw) self.show_button.grid(row=2, column=11) # 标记症状描述按钮 self.show_button = ttk.Button(self.init_window_name, text="症状描述", width='8', command=self.show_zzms) self.show_button.grid(row=3, column=11) # 标记独立症状按钮 self.show_button = ttk.Button(self.init_window_name, text="独立症状", width='8', command=self.show_dlzz) self.show_button.grid(row=4, column=11) # 标记药物按钮 self.show_button = ttk.Button(self.init_window_name, text="药物", width='8', command=self.show_yw) self.show_button.grid(row=5, column=11) # 标记手术按钮 self.show_button = ttk.Button(self.init_window_name, text="手术", width='8', command=self.show_ss) self.show_button.grid(row=6, column=11) # 恢复操作按钮 self.recover_button = ttk.Button(self.init_window_name, text="恢复", width='8', command=self.recover) self.recover_button.grid(row=0, column=15) # 标注撤销功能ctrl+z实现 self.back_button = ttk.Button(self.init_window_name, text="撤销", width='8', command=self.backToHistory) self.back_button.grid(row=0, column=16) self.result_data_Text.bind('<Control-Key-z>', self.backToHistory) self.result_data_Text.edit_separator() #功能函数 # 获取鼠标选中文本 def button_start(self, event): global s s = self.init_data_Text.index('@%s,%s' % (event.x, event.y)) print(event.x, event.y) def button_end(self, event): global e e = self.init_data_Text.index('@%s,%s' % (event.x, event.y)) print(str(e)) def str_trans_to_md5(self): src = self.init_data_Text.get(1.0, END).strip().replace("\n", "").encode() #print("src =",src) if src: try: myMd5 = hashlib.md5() myMd5.update(src) myMd5_Digest = myMd5.hexdigest() #print(myMd5_Digest) #输出到界面 self.result_data_Text.delete(1.0, END) self.result_data_Text.insert(1.0, myMd5_Digest) self.write_log_to_Text("INFO:str_trans_to_md5 success") except: self.result_data_Text.delete(1.0, END) self.result_data_Text.insert(1.0, "字符串转MD5失败") else: self.write_log_to_Text("ERROR:str_trans_to_md5 failed") #标记解剖部位 def show_jpbw(self): self.result_data_Text.edit_separator() print(self.init_data_Text.selection_get() + "\t" + "解剖部位" + "\n") start = self.init_data_Text.selection_get()[0] end = self.init_data_Text.selection_get()[-1] print(start, end) start_index = self.init_data_Text.get('1.0', END).index( self.init_data_Text.selection_get()[0]) end_index = len(self.init_data_Text.selection_get()) + start_index - 1 self.init_data_Text.tag_config('jpbw', background='red') self.init_data_Text.tag_add('jpbw', s, e) self.result_data_Text.insert( END, self.init_data_Text.selection_get() + "\t" + str(start_index) + "\t" + str(end_index) + "\t" + "解剖部位" + "\n") print(self.result_data_Text.get(END)) self.max1 = self.result_data_Text.get('1.0', END) self.result_data_Text.edit_separator() # 标记症状描述 def show_zzms(self, ): start = self.init_data_Text.selection_get()[0] end = self.init_data_Text.selection_get()[-1] print(start, end) start_index = self.init_data_Text.get('1.0', END).index( self.init_data_Text.selection_get()[0]) end_index = len(self.init_data_Text.selection_get()) + start_index - 1 self.init_data_Text.tag_config('zzms', background='yellow') self.init_data_Text.tag_add('zzms', s, e) print(self.init_data_Text.selection_get() + "\t" + str(start_index) + "\t" + str(end_index) + "症状描述" + "\n") self.result_data_Text.insert( END, self.init_data_Text.selection_get() + "\t" + str(start_index) + "\t" + str(end_index) + "\t" + "症状描述" + "\n") self.max1 = self.result_data_Text.get('1.0', END) self.result_data_Text.edit_separator() # 标记独立症状 def show_dlzz(self): start = self.init_data_Text.selection_get()[0] end = self.init_data_Text.selection_get()[-1] print(start, end) start_index = self.init_data_Text.get('1.0', END).index( self.init_data_Text.selection_get()[0]) end_index = len(self.init_data_Text.selection_get()) + start_index - 1 self.init_data_Text.tag_config('dlzz', background='green') self.init_data_Text.tag_add('dlzz', s, e) print(self.init_data_Text.selection_get() + "\t" + str(start_index) + "\t" + str(end_index) + "独立症状" + "\n") self.result_data_Text.insert( END, self.init_data_Text.selection_get() + "\t" + str(start_index) + "\t" + str(end_index) + "\t" + "独立症状" + "\n") self.max1 = self.result_data_Text.get('1.0', END) self.result_data_Text.edit_separator() # 标记药物 def show_yw(self): start = self.init_data_Text.selection_get()[0] end = self.init_data_Text.selection_get()[-1] print(start, end) start_index = self.init_data_Text.get('1.0', END).index( self.init_data_Text.selection_get()[0]) end_index = len(self.init_data_Text.selection_get()) + start_index - 1 self.init_data_Text.tag_config('yw', background='blue') self.init_data_Text.tag_add('yw', s, e) print(self.init_data_Text.selection_get() + "\t" + "药物" + "\n") self.result_data_Text.insert( END, self.init_data_Text.selection_get() + "\t" + str(start_index) + "\t" + str(end_index) + "\t" + "药物" + "\n") self.max1 = self.result_data_Text.get('1.0', END) self.result_data_Text.edit_separator() # 标记手术 def show_ss(self): start = self.init_data_Text.selection_get()[0] end = self.init_data_Text.selection_get()[-1] print(start, end) start_index = self.init_data_Text.get('1.0', END).index( self.init_data_Text.selection_get()[0]) end_index = len(self.init_data_Text.selection_get()) + start_index - 1 self.init_data_Text.tag_config('ss', background='orange') self.init_data_Text.tag_add('ss', s, e) print(self.init_data_Text.selection_get() + "\t" + "手术" + "\n") self.result_data_Text.insert( END, self.init_data_Text.selection_get() + "\t" + str(start_index) + "\t" + str(end_index) + "\t" + "手术" + "\n") self.max1 = self.result_data_Text.get('1.0', END) self.result_data_Text.edit_separator() #标注操作撤销功能 def callback(self): # 每当有字符插入的时候,就自动插入一个分割符,主要是防止每次撤销的时候会全部撤销 self.result_data_Text.edit_separator() def backToHistory(self): #撤销操作 if len(self.result_data_Text.get('1.0', 'end')) != 0: self.result_data_Text.edit_undo() else: #无字符时不能撤销 return def recover(self): #恢复操作 if len(self.max1) == len(self.result_data_Text.get('1.0', END)): return self.result_data_Text.edit_redo() #输入窗口一键清空功能 def delet_ofInput(self): self.init_data_Text.delete('1.0', 'end') #结果窗口一键清空功能 def delet_ofResult(self): self.result_data_Text.delete('1.0', 'end') #打开文件功能 def openfile(self): #打开新文件前清空历史 self.init_data_Text.delete('1.0', END) self.result_data_Text.delete('1.0', END) fname = filedialog.askopenfilename(title='打开文件', filetypes=[('All Files', '*')]) self.filename = os.path.basename(fname) print(self.filename) f = open(fname, 'r', encoding='utf-8', errors='ignore') # 对文本数据存储进数组,方便后续操作 line = f.readline() data_list = [] while line: num = list(map(str, line.split())) data_list.append(num) line = f.readline() f.close() data_array = np.array(data_list) f_contet = data_array self.init_data_Text.insert(END, f_contet) self.write_log_to_Text() # 导出文件功能 def outputfile(self): if self.filename != "": os.chdir(r'E:\GitTest\untitled\文本标注1.1\Annoation') f = open("ann" + self.filename, 'w', encoding='utf-8', errors='ignore') f.write(self.result_data_Text.get("1.0", "end")) json1 = json.dumps(self.result_data_Text.get("1.0", END)) print(json1) showinfo(title="成功", message="标注文件已导出至Annoation文件夹") else: showinfo(title="错误", message="未找到指定文件") #获取当前时间 def get_current_time(self): current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) return current_time #日志动态打印 def write_log_to_Text(self): global LOG_LINE_NUM current_time = self.get_current_time() logmsg_in = str(current_time) + " " + str(self.filename) + "\n" #换行 self.log_data_Text.insert(END, logmsg_in)
class SpinDelight(Frame): def __init__(self): Frame.__init__(self) self.master.geometry("1020x600+150+50") self.master.title("Spin Delight 1.0 - Copyright (c) Robin Thomas") self.master.resizable(0,0) self.grid() self.brwe = Button(self, text = "Browse", command = self.open_file, width = 10, relief = "groove") self.rtxt = Label(self, text="Input Text:") self.txt1 = ScrolledText(self, width = 50, height = 25) self.txt1.bind("<Control-Key-a>", self.select_all_txt1) self.txt1.bind("<Control-Key-A>", self.select_all_txt1) self.spin = Button(self, text = "Spin", command = self.spin_file, width = 10, relief = "groove") self.stxt = Label(self, text="Spun Text:") self.txt2 = ScrolledText(self, width = 50, height = 25) self.txt2.bind("<Control-Key-a>", self.select_all_txt2) self.txt2.bind("<Control-Key-A>", self.select_all_txt2) self.brwe.grid(row = 2, column = 2, pady = 15) self.rtxt.grid(row = 2, column = 0, padx = 25) self.txt1.grid(row = 3, column = 0, columnspan = 10, padx = 25) self.spin.grid(row = 3, column = 12) self.stxt.grid(row = 2, column = 13, padx = 25, pady = 5) self.txt2.grid(row = 3, column = 13, columnspan = 10, padx = 25) def select_all_txt1(self,event): self.txt1.tag_add(SEL, "1.0", END) self.txt1.mark_set(INSERT, "1.0") self.txt1.see(INSERT) return 'break' def select_all_txt2(self,event): self.txt2.tag_add(SEL, "1.0", END) self.txt2.mark_set(INSERT, "1.0") self.txt2.see(INSERT) return 'break' def open_file(self): fname = askopenfilename(filetypes=(("Text files", "*.txt"), ("All files", "*.*") )) if fname: try: self.txt1.delete(0.0, END) f = open(fname,'r') self.txt1.insert(INSERT,f.read()) except: showerror("Open Source File", "Failed to read file\n'%s'" % fname) def spin_file(self): txt = self.txt1.get("1.0", END) self.txt2.delete(0.0, END) if len(txt): try: words = sub(r'([.,?])+', r' \1 ', sub(r'[^a-zA-Z0-9 .,?]+', ' ', txt)).split() w1 = words[0] z = [(words[j - 1], words[j]) for j in range(1, len(words))] values = self.generate_dict(z, w1) string = self.generate_sent(values) if len(string): self.txt2.insert(INSERT, string) else: showerror("Error", "Insufficient data to spin !!") except: showerror("Error", "Nothing to spin !!") def generate_dict(self, x, w1): values = {'.': [w1]} for (wa, wb) in x: if wa in values: values[wa].append(wb) else: values[wa] = [wb] return values def generate_sent(self, values): w1 = '.' w2 = choice(values[w1]) string = w2 values[w1].remove(w2) while values: w1 = w2 if len(values[w1]): w2 = choice(values[w1]) else: del values[w1] w1 = '.' break if w2 in ('.', ',', '?'): string += w2 else: string += " " + w2 values[w1].remove(w2) return string
class Window: def __init__(self, width, height, title="MyWindow", resizable=(False, False), icon=r"resources/feather.ico"): self.root = Tk() self.root.title(title) # self.root.geometry(f"{width}x{height}+200+200") self.root.geometry("+600+300") # self.root.resizable(resizable[0], resizable[1]) if icon: self.root.iconbitmap(icon) self.st = ScrolledText(self.root, width=50, height=5, bg="yellow", fg="green", relief=SUNKEN, bd=8, selectbackground="red", selectforeground="blue", font=("Arial", 11, "bold"), padx=5, pady=8, wrap=WORD, spacing1=10, spacing2=20, spacing3=30, tabs=300, state=DISABLED) def run(self): self.draw_widgets() self.root.mainloop() def draw_widgets(self): self.draw_menu() self.st.configure(state=NORMAL) self.st.tag_config("ref", background="blue", foreground="white", underline=1, font=("Consolas", 14), justify=CENTER, offset=-8, relief=RAISED, borderwidth=2) # self.st.insert("1.0", "My\ntext\n1234") # self.st.insert("2.1", "Hello") self.st.insert("1.0", "SomeText " * 7) self.st.insert("1.8", "\n") self.st.tag_add("ref", "1.2", "1.10") self.st.insert(END, "REFERENCE", "ref") self.st.delete("1.3", "1.6") print(self.st.get("2.2", "2.5")) self.st.see("1.0") # self.st.search() # Indices # "1.2" # "2.end" # INSERT # CURRENT # END # "tag.first", "tag.end" ("ref.start") # "+ n chars" "- 1 chars" # "+ n lines" "- 2 lines" # "linestart", "lineend" # "wordstart", "wordend" # "+ 3 chars" => "+3c", "- 2 lines" => "-2l" index = "1.0" index += "+1c" self.st.configure(state=DISABLED) self.st.pack() def draw_menu(self): menu_bar = Menu(self.root) file_menu = Menu(menu_bar, tearoff=0) file_menu.add_separator() file_menu.add_command(label="Выйти", command=self.exit) info_menu = Menu(menu_bar, tearoff=0) info_menu.add_command(label="О приложении", command=self.show_info) menu_bar.add_cascade(label="Файл", menu=file_menu) menu_bar.add_cascade(label="Справка", menu=info_menu) self.root.configure(menu=menu_bar) def show_info(self): mb.showinfo("Информация", "Лучшее графическое приложение на свете") def exit(self): choice = mb.askyesno("Quit", "Do you want to quit?") if choice: self.root.destroy() def create_child(self, width, height, title="Child", resizable=(False, False), icon=None): ChildWindow(self.root, width, height, title, resizable, icon)
class LoggingWindow(): def __init__(self): window = Toplevel(bg='white') window.title("Logger") # get screen width and height screen_width = window.winfo_screenwidth() screen_height = window.winfo_screenheight() window.geometry("600x400+%d+%d" % (screen_width - 600, 0)) self.lineNum = 1 self.text = ScrolledText(window, background='black') self.text.pack(fill=BOTH, expand=1) def putLog(self, plotables=None, data_info=None, status=None): # writing current time current_time = datetime.now().strftime("%H:%M:%S") if status is not None: if status.get_state(): message = status.get_info() self.text.insert(INSERT, \ ">> " + current_time + "\t SUCCESS " + message + "\n" ) self.text.tag_add("success", str(self.lineNum) + ".12", str(self.lineNum) + ".20") self.text.tag_config("success", foreground="green") self.text.tag_add( "success message", str(self.lineNum) + ".20", str(self.lineNum) + "." + str(21 + len(message))) self.text.tag_config("success message", foreground="LightBlue1") else: message = status.get_error() self.text.insert(INSERT, \ ">> " + current_time + "\t ERROR " + message + "\n" ) self.text.tag_add("error", str(self.lineNum) + ".12", str(self.lineNum) + ".18") self.text.tag_config("error", foreground="red") self.text.tag_add( "error message", str(self.lineNum) + ".18", str(self.lineNum) + "." + str(19 + len(message))) self.text.tag_config("error message", foreground="yellow") self.text.tag_add("time", str(self.lineNum) + ".03", str(self.lineNum) + ".11") self.text.tag_config("time", foreground="PeachPuff2") self.lineNum += 1 dic = status.get_dic() for each in dic.keys(): self.text.insert(INSERT, \ ">> " + current_time + "\t" + each + str(dic[each]) + "\n" ) self.text.tag_add("time", str(self.lineNum) + ".03", str(self.lineNum) + ".11") self.text.tag_config("time", foreground="PeachPuff2") self.text.tag_add( "dic_label", str(self.lineNum) + ".12", str(self.lineNum) + "." + str(12 + len(each))) self.text.tag_config("dic_label", foreground="azure") self.lineNum += 1 self.text.insert(INSERT, "\n") self.lineNum += 1 return elif plotables is not None: self.text.insert(INSERT, \ ">> " + current_time + "\t Time Series' Information \n\n" + \ "TYPE" + "\t\t\t\t\t\t LENGTH" + "\t\t NUMBER OF VOXELS \n\n" ) self.text.tag_add("labels", str(self.lineNum) + ".12", str(self.lineNum) + "." + str(37)) self.text.tag_config("labels", foreground="PaleTurquoise1") self.text.tag_add("titles", str(self.lineNum + 2) + ".00", str(self.lineNum + 2) + "." + str(37)) self.text.tag_config("titles", foreground="azure") self.text.tag_add("time", str(self.lineNum) + ".03", str(self.lineNum) + ".11") self.text.tag_config("time", foreground="PeachPuff2") for each in plotables: self.text.insert(INSERT, \ each[0] + "\t\t\t\t\t\t " + str(each[1].shape[0]) + "\t\t " + str(each[1].shape[1]) + "\n" ) self.lineNum += 1 self.text.insert(INSERT, "\n") self.lineNum += 5 return elif data_info is not None: self.text.insert(INSERT, \ ">> " + current_time + "\t Information \n\n") self.text.tag_add("labels", str(self.lineNum) + ".12", str(self.lineNum) + "." + str(37)) self.text.tag_config("labels", foreground="PaleTurquoise1") self.text.tag_add("time", str(self.lineNum) + ".03", str(self.lineNum) + ".11") self.text.tag_config("time", foreground="PeachPuff2") self.lineNum += 2 if data_info["Type"] == "BOLD": self.text.insert(INSERT, \ " :- " + "Type of Data: BOLD Time Series\n" + " :- " + "Subject: " + data_info["Subject"] + "\n" " :- " + "Input File: " + data_info["Input File"] + "\n" ) self.lineNum += 1 elif data_info["Type"] == "Preprocessed-BOLD": self.text.insert(INSERT, \ " :- " + "Type of Data: Preprocessed-BOLD Time Series\n" + " :- " + "Subject: " + data_info["Subject"] + "\n" + " :- " + "Mask File: " + data_info["Mask File"] + "\n" + " :- " + "Associated Raw BOLD: " + data_info["Associated Raw BOLD"] + "\n" ) self.lineNum += 2 elif data_info["Type"] == "HRF": self.text.insert(INSERT, \ " :- " + "Type of Data: Hemodynamic Response Function Time Series\n" + " :- " + "Associated BOLD: " + data_info["Associated BOLD"] + "\n" ) elif data_info["Type"] == "Deconvolved-BOLD": self.text.insert(INSERT, \ " :- " + "Type of Data: Deconvolved BOLD Time Series\n" + " :- " + "Associated HRF: " + data_info["Associated HRF"] + "\n" ) self.text.tag_config("type", foreground="azure") self.text.tag_config("line2", foreground="azure") self.lineNum += 2 self.text.insert(INSERT, \ " :- " + "\t\t\tAssociated Parameters\n" ) self.text.tag_add("ap", str(self.lineNum) + ".03", str(self.lineNum) + ".30") self.text.tag_config("ap", foreground="Khaki1") self.lineNum += 1 for each in data_info["Parameters"].keys(): self.text.insert(INSERT, \ "\t\t" + each + "\t\t\t=\t\t" + str(data_info["Parameters"][each]) + "\n") self.text.tag_add("pv", str(self.lineNum) + ".00", str(self.lineNum) + "." + str(6 + len(each))) self.text.tag_config("pv", foreground="LemonChiffon2") self.lineNum += 1 self.text.insert(INSERT, "\n") self.lineNum += 1 return
class AnnotationGUI(BasicGUI, FileAnnotator): def __init__(self, master=None): BasicGUI.__init__(self, master=master) FileAnnotator.__init__(self) self.vert_panes = PanedWindow(master, bg='#BF98A0') self.vert_panes.pack(fill=BOTH, expand=1) # Left style = ttk.Style() style.configure('TButton', foreground='black', background='#B0D7FF') self.onto_viewer = Treeview(self.vert_panes, selectmode='browse', style='TButton') self.vert_panes.add(self.onto_viewer) self.onto_viewer_scroll_bar = Scrollbar(self.vert_panes, orient='vertical', command=self.onto_viewer.yview) self.vert_panes.add(self.onto_viewer_scroll_bar) self.onto_viewer.configure(yscrollcommand=self.onto_viewer_scroll_bar.set) self.onto_viewer.bind("<Double-1>", self.expand_onto_viewer) # Right self.horz_panes = PanedWindow(self.vert_panes, orient=VERTICAL, bg='#BF98A0') self.vert_panes.add(self.horz_panes) # Top self.text_pad = ScrolledText(self.horz_panes, bg='#EAE8FF') self.horz_panes.add(self.text_pad) # Bottom self.term_viewer = ScrolledText(self.horz_panes, bg='#B0D7FF') self.horz_panes.add(self.term_viewer) ontology_menu_commands = [('Load ontology from file', self.load_ontology_command)] self.add_menu_to_main_menu('Ontology', ontology_menu_commands) self.v = StringVar() def load_ontology_command(self, file=None, onto_name=None, roots=None): if file is None: file = filedialog.askopenfile(parent=self.master, mode='rb', title='Select a file') if file is not None: if onto_name is None: onto_name = simpledialog.askstring('Name', 'Enter a name for this ontology') if roots is None: roots = simpledialog.askstring('Roots', 'Enter the names of the roots for this ontology').split(',') print('Loading {}'.format(file)) self.ontos[onto_name] = {'onto': obonet.read_obo(file), 'roots': roots} self.display_onto(onto_name) self.ontos[onto_name]['id_to_name'] = {id_: data['name'] for id_, data in self.ontos[onto_name]['onto'].nodes(data=True)} self.ontos[onto_name]['name_to_id'] = {data['name']: id_ for id_, data in self.ontos[onto_name]['onto'].nodes(data=True)} def display_term(self, term, onto_name): term_data = self.ontos[onto_name]['onto'].node[self.ontos[onto_name]['name_to_id'][term]] self.term_viewer.configure(state='normal') self.term_viewer.delete('1.0', END) for label, value in term_data.items(): self.term_viewer.insert(END, '{}:\n\t{}\n'.format(label, value)) self.term_viewer.configure(state='disabled') def display_onto(self, onto_name): name_id = self.onto_viewer.insert('', END, text=onto_name, value=onto_name) for root in self.ontos[onto_name]['roots']: self.onto_viewer.insert(name_id, END, text=root, value=onto_name) def expand_onto_viewer(self, _): iid = self.onto_viewer.selection()[0] term = self.onto_viewer.item(iid, 'text') onto_name = self.onto_viewer.item(iid, 'value')[0] self.display_term(term, onto_name) if self.onto_viewer.parent(iid) != '': subterms = get_subterms(term, self.ontos[onto_name]['onto'], self.ontos[onto_name]['id_to_name'], self.ontos[onto_name]['name_to_id']) for s in subterms: self.onto_viewer.insert(iid, END, text=s, value=onto_name) def annotate_text(self, _): self.text_pad.tag_add() def run(self, preload_annotation_file=None, preload_ontology=None): self.vert_panes.pack() self.master.state('zoomed') self.master.configure(bg='black') if len(preload_ontology) == 3: self.load_ontology_command(file=preload_ontology['File'], onto_name=preload_ontology['Name'], roots=preload_ontology['Roots']) if len(preload_annotation_file) == 1: self.open_command(file_name=preload_annotation_file['File']) self.master.mainloop()
class textEditor(): alltabs = None def __init__(self, window, labelFrame, tabs, vocab, startWithSameLetter, tabsOpen, file_path=""): self.window = window # record the directory path of the file self.file_path = file_path if file_path: self.file_name = self.file_path else: # if the file path doesn't exist, name it accordingly self.file_name = 'Untitled' # record the necessary passed-in parameters self.labelFrame = labelFrame self.tabsOpen = tabsOpen self.tabs = tabs self.vocab = vocab self.startWithSameLetter = startWithSameLetter # create the main gui elements in the respective tab frame self.notepad = ScrolledText(self.labelFrame, font=("Calibri", 15)) editorbox = self.notepad self.var = tk.IntVar() self.autoCorrectOption = tk.Checkbutton(self.labelFrame, \ text="Enable Auto-Correct", variable=self.var, command=self.switchSpellChecker) self.autoComplete_suggestions = tk.Listbox(self.labelFrame) self.autoCorrect_suggestions = tk.Listbox(self.labelFrame) myFont = Font(family="Calibri", size=15) self.autoComplete_suggestions.configure(font=myFont) self.autoCorrect_suggestions.configure(font=myFont) # create funtionality bars inside tab frame self.createMenuBar() self.createToolBar(self.labelFrame) self.autoCorrectOption.grid(row=1, column=9) self.notepad.config(undo=True) self.notepad.config(height=900) self.notepad.grid(row=2, column=0, columnspan=11, sticky="WE") self.window.protocol("WM_DELETE_WINDOW", lambda: newFileTab.closeCheck(self.tabsOpen)) # add pre-set markup on the entire text widget in the tab frame self.notepad.tag_configure("misspelling", foreground="red", underline=True) # bind all navigation to checking the spelling of the word self.nav_click = self.notepad.bind("<ButtonRelease-1>", self.spellChecker) self.nav_up = self.notepad.bind("<Up>", self.spellChecker) self.nav_down = self.notepad.bind("<Down>", self.spellChecker) self.nav_left = self.notepad.bind("<Left>", self.spellChecker) self.nav_right = self.notepad.bind("<Right>", self.spellChecker) # check each word's spelling after typed and mark it up self.notepad.bind("<space>", self.markUp) self.notepad.bind(".", self.markUp) # keep calling autocomplete while user is writing for letter in "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM": self.notepad.bind("<KeyRelease-" + letter + ">", self.autoComplete) self.notepad.bind("<KeyRelease-BackSpace>", self.autoComplete) # bind file shortcuts self.notepad.bind('<Control-s>', newFileTab.saveToFile) self.notepad.bind('<Control-o>', newFileTab.openFile) self.notepad.bind('<Control-n>', newFileTab.createFile) self.notepad.bind('<Control-c>', newFileTab.copySelected) self.notepad.bind('<Control-x>', newFileTab.cutSelected) self.notepad.bind('<Control-v>', newFileTab.pasteClipboard) # this function creates the top menu bar including all functionalities def createMenuBar(self): menuBar = Menu(self.window) # create drop-down options for the file menu fileMenu = tk.Menu(menuBar, tearoff=0) fileMenu.add_command( label="New Document", command=lambda: newFileTab.createFile(self.tabsOpen)) fileMenu.add_command( label="Open Local File", command=lambda: newFileTab.openFile(self.tabsOpen)) fileMenu.add_command( label="Save file", command=lambda: newFileTab.saveToFile(self.tabsOpen)) fileMenu.add_separator() fileMenu.add_command( label="Close File", command=lambda: newFileTab.closeFile(self.tabsOpen)) fileMenu.add_command(label="Exit", command=lambda: newFileTab.quit(self.tabsOpen)) menuBar.add_cascade(label="File", menu=fileMenu) # create drop-down options for the edit menu editMenu = tk.Menu(menuBar, tearoff=0) editMenu.add_command( label="Undo", command=lambda: newFileTab.undoEdit(self.tabsOpen)) editMenu.add_command( label="Redo", command=lambda: newFileTab.redoEdit(self.tabsOpen)) editMenu.add_command( label="Copy", command=lambda: newFileTab.copySelected(self.tabsOpen)) editMenu.add_command( label="Cut", command=lambda: newFileTab.cutSelected(self.tabsOpen)) editMenu.add_command( label="Paste", command=lambda: newFileTab.pasteClipboard(self.tabsOpen)) menuBar.add_cascade(label="Edit", menu=editMenu) self.window.config(menu=menuBar) '''icon pics retrieved from: https://icons-for-free.com/folder+open+icon-1320161390409087972/''' # this function creates the tool bar with clickable icon shortcuts for the functionalities def createToolBar(self, labelFrame): # add icon for handling creating new files new_img = tk.PhotoImage(file="newicon.png") new_img = new_img.zoom(1) new_img = new_img.subsample(15) # add icon for handling opening local files open_img = tk.PhotoImage(file="openicon.png") open_img = open_img.zoom(1) open_img = open_img.subsample(15) # add icon for handling saving files save_img = tk.PhotoImage(file="saveicon.png") save_img = save_img.zoom(1) save_img = save_img.subsample(4) # add icon for handling copying from files copy_img = tk.PhotoImage(file="copyicon.png") copy_img = copy_img.zoom(1) copy_img = copy_img.subsample(4) # add icon for handling cutting from files cut_img = tk.PhotoImage(file="cuticon.png") cut_img = cut_img.zoom(1) cut_img = cut_img.subsample(4) # add icon for handling cutting from clipboard paste_img = tk.PhotoImage(file="pasteicon.png") paste_img = paste_img.zoom(1) paste_img = paste_img.subsample(4) # add icon for handling undo edits undo_img = tk.PhotoImage(file="undoicon.png") undo_img = undo_img.zoom(1) undo_img = undo_img.subsample(4) # add icon for handling redo edits redo_img = tk.PhotoImage(file="redoicon.png") redo_img = redo_img.zoom(1) redo_img = redo_img.subsample(4) # add icon for handling closing current file tab close_img = tk.PhotoImage(file="closeicon.png") close_img = close_img.zoom(1) close_img = close_img.subsample(4) # create all respective buttons and configure them to their appropriate icons and function calls new_button = tk.Button( labelFrame, image=new_img, command=lambda: newFileTab.createFile(self.tabsOpen)) open_button = tk.Button( labelFrame, image=open_img, command=lambda: newFileTab.openFile(self.tabsOpen)) save_button = tk.Button( labelFrame, image=save_img, command=lambda: newFileTab.saveToFile(self.tabsOpen)) copy_button = tk.Button( labelFrame, image=copy_img, command=lambda: newFileTab.copySelected(self.tabsOpen)) cut_button = tk.Button( labelFrame, image=cut_img, command=lambda: newFileTab.cutSelected(self.tabsOpen)) paste_button = tk.Button( labelFrame, image=paste_img, command=lambda: newFileTab.pasteClipboard(self.tabsOpen)) undo_button = tk.Button( labelFrame, image=undo_img, command=lambda: newFileTab.undoEdit(self.tabsOpen)) redo_button = tk.Button( labelFrame, image=redo_img, command=lambda: newFileTab.redoEdit(self.tabsOpen)) close_button = tk.Button( labelFrame, image=close_img, command=lambda: newFileTab.closeFile(self.tabsOpen)) new_button.image = new_img open_button.image = open_img save_button.image = save_img copy_button.image = copy_img cut_button.image = cut_img paste_button.image = paste_img undo_button.image = undo_img redo_button.image = redo_img close_button.image = close_img # grid the buttons appropriately onto the tab frame new_button.grid(row=1, column=1) open_button.grid(row=1, column=2) save_button.grid(row=1, column=3) copy_button.grid(row=1, column=4) cut_button.grid(row=1, column=5) paste_button.grid(row=1, column=6) undo_button.grid(row=1, column=7) redo_button.grid(row=1, column=8) close_button.grid(row=1, column=10) # this function takes automatically the first choice from the suggestion # box and replaces it with the word that is underlined as misspelt def autoCorrect(self, event): lastWord = self.getLastWord() if self.spellCheckerList(lastWord): # get first suggestiosn from listbox contents bestSuggestion = self.spellCheckerList(lastWord)[0] # configure and find first and last index of word to be replaced start = self.notepad.get('1.0', tk.END).index(lastWord) end = start + len(lastWord) line_num = int(float(self.notepad.index(tk.CURRENT))) start_i = str(line_num) + '.' + str(start) end_i = str(line_num) + '.' + str(end) # delete the misspelled word by the best suggestion in text widget self.notepad.delete(start_i, end_i) self.notepad.insert(start_i, bestSuggestion) # this function unbinds the arrows with the list from the dictionary # so that the list dosen't appear when pressing the auto-correct option def switchSpellChecker(self): self.notepad.unbind('<ButtonRelease-1>') self.notepad.unbind('<Up>') self.notepad.unbind('<Down>') self.notepad.unbind('<Left>') self.notepad.unbind('<Right>') self.notepad.unbind("<space>") # if the autocorrect option is pressed if self.var.get(): # replace the spellchecker bindings to autocorrect self.notepad.bind("<space>", self.autoCorrect) self.notepad.bind(".", self.autoCorrect) # if it is not pressed else: # rebind the orginal keys for the spellchecker listbox functionality self.notepad.bind("<ButtonRelease-1>", self.spellChecker) self.notepad.bind("<Up>", self.spellChecker) self.notepad.bind("<Down>", self.spellChecker) self.notepad.bind("<Left>", self.spellChecker) self.notepad.bind("<Right>", self.spellChecker) # check each word's spelling after typed and mark it up self.notepad.bind("<space>", self.isSpeltCorrect) self.notepad.bind(".", self.isSpeltCorrect) # this function gets the last word that was typed by the user def getLastWord(self): # split all input text at all white space characters (e.g. space, tab, enter) wordsList = re.split("\s+", self.notepad.get("1.0", tk.END)) # remove last empty string wordsList.remove('') # last word is at the last index of the words list lastWord = wordsList[len(wordsList) - 1] # remove unnecessary punctuations next to the last word lastWord_stripped = lastWord.translate( str.maketrans('', '', string.punctuation)) return lastWord_stripped.lower() # here we edit the words that are misspelt after # getting the words from the screen and correct their form def spellCheckerList(self, word_to_check): edits = {} # if there's no word selected or a space is selected if word_to_check == "" or word_to_check == " ": return # if the word is misspelt, record its respective edit distances and frequencies elif not self.isSpeltCorrect(word_to_check): # compute for min edit distance from each word in dictionary for word in self.vocab: edits_num = self.minEditDistance(word_to_check, word) # record all words corresponding to edits numbers 1 and 2 in a dictionary if edits_num <= 2: # if there is a key in the dictionary corresponding to the same edit distance if edits_num in edits: # add it to its list of values edits[edits_num].append(word) else: # if not, create a new key for the number of edits and add it edits[edits_num] = [word] # record and sort frequencies of words corresponding for 1 edit and 2 edits freqs1 = [] freqs2 = [] # sorting words with edit distance 1 one based on frequency if 1 in edits: for similar_word in edits.get(1): # record frequency of each word with the same edit distance freq = self.vocab.get(similar_word) freqs1.append(freq) # sorting words with edit distance 1 one based on frequency if 2 in edits: for similar_word in edits.get(2): # record frequency of each word with the same edit distance freq = self.vocab.get(similar_word) freqs2.append(freq) # rearrange frequencies individually freqs1.sort() freqs2.sort() # combine the two frequency lists in order of 1 then 2 to get appropriate suggestions list # the smallest edit distance if the first priority, then its frequency freqs = freqs1 + freqs2 suggestions = [] for f in freqs: for word in self.vocab: # get words based on their corresponding frequencies in order if self.vocab.get(word) == f: # add each corresponding word to the suggestions list suggestions.append(word) return suggestions '''STILL TO DO, CONSIDER CAPITALIZATION IN SPELLCHECKER and replacement word/pop-up lists''' # this function checks if the word is spelt correctly or not # it returns a boolean value based on this condition def isSpeltCorrect(self, word): if word in self.vocab: return True return False # this functions recognizes the word and finds similar words # depending on their frequency, this will be then added to the # suggestion list. this function updates after typing each charachter def autoCompleteList(self, e): typed_word = self.getCurrWord(e).lower() if typed_word == "": return freqs = [] suggestions = [] inp_length = len(typed_word) for word in self.vocab: # check for english words that start with the same characters if word[:inp_length].lower() == typed_word: print('hi') # record the frequency ranks of such words freq = self.vocab.get(word) freqs.append(freq) # order frequencies freqs.sort() for f in freqs: for word in self.vocab: # get words based on their corresponding frequencies in order if self.vocab.get(word) == f: suggestions.append(word) return suggestions # this function takes the list of words suggested if any and # inserts them on the screen in the autocomplete suggestions listbox def autoComplete(self, event): self.autoComplete_suggestions.destroy() self.autoComplete_suggestions = tk.Listbox(window) myFont = Font(family="Calibri", size=15) self.autoComplete_suggestions.configure(font=myFont) word = self.getCurrWord(event).lower() # ignore autocomplete call if the word is empty if not word: return # if there is one character typed if len(word) == 1: # use pre-loaded dictionary to get suggestiosn into listbox suggestions = self.startWithSameLetter.get(word) i = 0 # add the first 10 word suggestions, as long as they exist while i < 11 and i < len(suggestions): for l in suggestions: # add them to the suggestions listbox in order self.autoComplete_suggestions.insert(i, l + " ") i += 1 else: # if typed portion is a part of a valid word if self.autoCompleteList(event): # get autocomplete list and append its first 10 values into the listbox suggestions = self.autoCompleteList(event)[:10] for i in range(len(suggestions)): self.autoComplete_suggestions.insert( i, suggestions[i] + " ") # if not, indicate lack of matches on listbox else: self.autoComplete_suggestions.insert(0, "No matches found.") # remove duplicate words in the suggestions listbox and the typed word if word in self.autoComplete_suggestions.get(0, tk.END): index = self.autoComplete_suggestions.get(0, tk.END).index(word) # delete duplicate word from suggestions listbox self.autoComplete_suggestions.delete(index) # if there are more suggestions available after 10, add the next one if len(self.autoCompleteList(event)) >= 11: self.autoComplete_suggestions.insert( 10, self.autoCompleteList(event)[10] + " ") # place the listbox where the typing cursor is (x, y, w, h) = self.notepad.bbox('insert') self.autoComplete_suggestions.place(x=x + 140, y=y + 200, anchor="center") self.autoComplete_suggestions.bind('<<ListboxSelect>>', self.autoCompleteClickSelect) # this function also draws a list box with all the suggested words that # could replace the misspelt word. def spellChecker(self, event): self.autoComplete_suggestions.destroy() self.autoCorrect_suggestions.destroy() self.autoCorrect_suggestions = tk.Listbox(self.labelFrame) myFont = Font(family="Calibri", size=15) self.autoCorrect_suggestions.configure(font=myFont) # if the selected word is the one being currently typed # autocomplete it and don't spellcheck it (word not fully typed yet) '''if self.getCurrWord(event) and self.getNavigWord(event): self.autoComplete(event) return''' word = self.getNavigWord(event) # if the suggestions listbox is not empty, clear it if len(self.autoCorrect_suggestions.get(0, tk.END)) != 0: self.autoCorrect_suggestions.delete(0, tk.END) # exit spell checker if the word is spelt correctly if self.isSpeltCorrect(word): return # if current word is not empty and is spelled incorrectly elif len(self.notepad.get('1.0', 'end-1c')) != 0: if self.spellCheckerList(word): # append first 10 suggestions into listbox suggestions = self.spellCheckerList(word)[:10] for i in range(len(suggestions)): self.autoCorrect_suggestions.insert(i, suggestions[i]) else: # if not close matches from min edit function, display appropriate message self.autoCorrect_suggestions.insert(0, "No matches found.") self.autoCorrect_suggestions.insert(1, "Add word to dictionary") if len(word) != 1: # place the listbox where the cursor is (x, y, w, h) = self.notepad.bbox('insert') self.autoCorrect_suggestions.place(x=x + 115, y=y + 160, anchor="center") self.autoComplete_suggestions = tk.Listbox(self.labelFrame) myFont = Font(family="Calibri", size=15) self.autoComplete_suggestions.configure(font=myFont) self.autoCorrect_suggestions.bind('<<ListboxSelect>>', self.autoCorrectClickSelect) # this function takes the selection that the user made from the suggestion box # and overwrites the word in he screen def autoCorrectClickSelect(self, event): selected_word = self.autoCorrect_suggestions.get( self.autoCorrect_suggestions.curselection()) # get the entire word the cursor is on navigWord = self.getNavigWord(event) if selected_word == "No matches found.": self.autoCorrect_suggestions.destroy() return elif selected_word == "Add word to dictionary": self.vocab[navigWord] = len(self.vocab) + 1 else: start = self.notepad.get('1.0', tk.END).index(navigWord) end = start + len(navigWord) line_num = int(float(self.notepad.index(tk.CURRENT))) # configure start and end indices of the word to be corrected syntax correctly start_i = str(line_num) + '.' + str(start) end_i = str(line_num) + '.' + str(end) # delete the misspelled word and replace it by the correct one selected from the listbox self.notepad.delete(start_i, end_i) self.notepad.insert(start_i, selected_word) if self.autoCorrect_suggestions.winfo_exists: self.autoCorrect_suggestions.destroy() # this function takes the selection that the user made from the suggestion box # and overwrites the word in the screen for the autocomplete option def autoCompleteClickSelect(self, event): if self.autoComplete_suggestions.curselection(): selected_word = self.autoComplete_suggestions.get( self.autoComplete_suggestions.curselection()) if selected_word == "No matches found.": self.autoComplete_suggestions.destroy() return # get the partial word currently being typed currWord = self.getCurrWord(event).lower() # configure start and end indices of the word to be corrected syntax correctly start = self.notepad.get('1.0', tk.END).index(currWord) end = start + len(currWord) line_num = int(float(self.notepad.index(tk.CURRENT))) start_i = str(line_num) + '.' + str(start) end_i = str(line_num) + '.' + str(end) # delete the misspelled word and replace it by the correct one selected from the listbox self.notepad.delete(start_i, end_i) self.notepad.insert(start_i, selected_word) self.autoComplete_suggestions.destroy() # this function underlines the word that is misspelt and # colors it with red def markUp(self, misspelt_word): lastWord = self.getLastWord() # if word contains numbers of special characters, don't mark it up if not lastWord.isalpha(): return self.autoComplete_suggestions.destroy() # search for starting index of the misspelt word index = self.notepad.search(r'\s', "insert", backwards=True, regexp=True) if index == "": index = "1.0" else: index = self.notepad.index("%s+1c" % index) word = self.notepad.get(index, "insert").translate( str.maketrans('', '', string.punctuation)) # if word spelled correctly, remove pre-set misspelling tag if word.lower() in self.vocab: self.notepad.tag_remove("misspelling", index, "%s+%dc" % (index, len(word))) else: self.notepad.tag_add("misspelling", index, "%s+%dc" % (index, len(word))) '''modfiied code from: https://stackoverflow.com/questions/3732605/add-advanced-features-to-a-tkinter-text-widget''' # This function finds the minimum edit distance using a modified version of the Levistein algorithm # This is my own implementation of the algorithm def minEditDistance(self, misspelt_word, vocab_word): rows = len(misspelt_word) + 1 columns = len(vocab_word) + 1 matrix = [] # split list of lists based on rows # initialize values for column contents for each row for i in range(rows): matrix.append([]) for j in range(columns): matrix[i].append(-1) # empty string row first_row = [] for n in range(columns): first_row.append(n) matrix = [first_row] + matrix[1:] # add first column values in matrix n = 0 for i in range(rows): matrix[i][0] = n n += 1 # for each letter of the misspelt word for r in range(rows - 1): # go through each letter in the vocab word for c in range(columns - 1): # if the letters are the same if vocab_word[c] == misspelt_word[r]: # copy down the value at the relative left diagonal position in the matrix # into the corresponding matrix position of the current string comparison matrix[r + 1][c + 1] = matrix[r][c] # if letters are different else: # take the minimum value of the three upper left diagonals to the current position adj_min = min(matrix[r][c], matrix[r][c + 1], matrix[r + 1][c]) # add 1 to get the minimum additional edit to transform the two strings parts so far # add resulting value into corresponding matrix position matrix[r + 1][c + 1] = adj_min + 1 # minimum number of edits is the last computed value of the matrix minEdits = matrix[rows - 1][columns - 1] return minEdits # this function gets the word that the cursor is hovering over in the text widget # and returns it. def getNavigWord(self, event): start = self.notepad.index("insert wordstart") end = self.notepad.index("insert wordend") nav_word = self.notepad.get(start, end) # remove unnecessary punctuations next to the typed word nav_word_stripped = nav_word.translate( str.maketrans('', '', string.punctuation)) return nav_word_stripped.lower() # this function gets the word that is being modified currently from the user # and returns it. def getCurrWord(self, event): all_typed = self.notepad.get("1.0", "end") i = all_typed.rfind(" ") curr_word = all_typed[i + 1:].strip() # remove unnecessary punctuations next to the typed word curr_word_stripped = curr_word.translate( str.maketrans('', '', string.punctuation)) return curr_word_stripped.lower()
class Main(Tk): def __init__(self): super().__init__() self.title("Untitled - Vulgar") self.geometry('800x600') self.menuBar = Menu(self) self.FileMenu = Menu(self.menuBar, tearoff = 0) self.EditMenu = Menu(self.menuBar, tearoff = 0) self.RunMenu = Menu(self.menuBar, tearoff = 0) self.HelpMenu = Menu(self.menuBar, tearoff = 0) self.ConfigMenu = Menu(self.menuBar, tearoff = 0) self.window_title = "Code " self.tabControl = ttk.Notebook(self) self.tab1 = Frame(self.tabControl) self.tab2 = Frame(self.tabControl) self.tabControl.add(self.tab1, text = self.window_title) self.tabControl.add(self.tab2, text = "Console") self.tabControl.pack(expand = 1, fill = BOTH) self.line_num = Canvas(self.tab1, width = 50, bg = "black") self.textArea = ScrolledText(self.tab1,background = "black", foreground = "white", insertbackground = "white", wrap = WORD, width = 93, height = 90) self.View = ScrolledText(self.tab2, background = "black", foreground = "white", insertbackground = "white", wrap = WORD, width = 93, height = 90) self.scroll = Scrollbar(self.textArea) self.file = None self.grid_rowconfigure(0, weight = 1) self.grid_columnconfigure(0, weight = 1) self.FileMenu.add_command(label = "New File Ctrl+N", command = self.newFile) self.FileMenu.add_command(label = "Open... Ctrl+O", command = self.openFile) self.FileMenu.add_command(label = "Save Ctrl+S", command = self.saveFile) self.FileMenu.add_command(label = "Save As... Ctrl+Shift+S", command = self.SaveAs) self.FileMenu.add_command(label = "Exit Ctrl+Q", command = self._quit_) self.HelpMenu.add_command(label = "About ", command = self.ShowAbout) self.HelpMenu.add_command(label = "How to use", command = None) self.EditMenu.add_command(label = "undo Ctrl+Z", command = self.undo) self.EditMenu.add_command(label = "redo Ctrl+Y", command = self.redo) self.EditMenu.add_command(label = "Copy Ctrl+C", command = self.copy) self.EditMenu.add_command(label = "Cut Ctrl+X", command = self.cut) self.EditMenu.add_command(label = "Paste Ctrl+V", command = self.paste) self.EditMenu.add_command(label = "Select All Ctrl+A", command = None) self.ConfigMenu.add_command(label = "Set background color", command = self.Setbg) self.ConfigMenu.add_command(label = "Set text color", command = self.Setfg) self.ConfigMenu.add_command(label = "Set cursor color", command = self.SetCurs) self.RunMenu.add_command(label = "Run code F5", command = self.Run) self.menuBar.add_cascade(label = "File", menu = self.FileMenu) self.menuBar.add_cascade(label = "Edit", menu = self.EditMenu) self.menuBar.add_cascade(label = "Run", menu = self.RunMenu) self.menuBar.add_cascade(label = "Configure IDE", menu = self.ConfigMenu) self.menuBar.add_cascade(label = "Help", menu = self.HelpMenu) self.config(menu = self.menuBar) self.line_num.pack(side=LEFT, fill = Y) #self.textArea.pack(side = RIGHT, fill = "both") self.textArea.place(x = 35) self.bind("<F5>", lambda x:self.Run()) self.textArea.bind('<Return>', lambda x:self.update_line_nums(x)) #bind update_line_nums to textArea here self.View.pack() self.text = "Vulgar - console >>>" self.View.insert(0.0, self.text) self.View.config(state = DISABLED) self.update_line_nums() def _quit_(self): if askokcancel("Exit", "Are you sure you want to quit?"): self.self.destroy() def update_line_nums(self, *args): i = str(float(self.textArea.index('end'))-1) dline = self.textArea.dlineinfo(i) y = dline[1] linenum= int(i.split('.')[0]) text = self.line_num.create_text(25, y+18 if args else y, anchor = "nw", text = linenum+1 if args else linenum, fill = "#fff", font = ('Helvetica', 12)) bbox = self.line_num.bbox(text) coord = self.line_num.coords(text) self.line_num.coords(text, 35-(bbox[2]-bbox[0]), coord[1]) i = self.textArea.index('{0}+1line'.format(i)) def delete_line_nums(self, *args): ... def get_end_linenumber(text): """Utility to get the last line's number in a Tk text widget.""" return int(float(text.index('end-1c'))) def ShowAbout(self):showinfo ("Vulgar", "made for sake of coding practice") def openFile(self): self.file = askopenfilename(defaultextension = " .txt", filetypes = [("All Files", "*.*"), ("Text Documents" , "*.txt"), ("Brainfuck files", "*.bf")]) if self.file == " ": self.file = None else: self.self.title (os.path.basename(self.file) + " - Vulgar") self.textArea.delete(1.0, END) try: file = open(self.file, "r") self.textArea.insert(1.0, file.read()) file.close() except Exception as e: showerror("An Error Occured", e) self.update_line_nums() def newFile(self): self.self.title("Untitled - Vulgar") self.file = None self.textArea.delete(1.0, END) def saveFile(self): if self.file == None: self.file = asksaveasfilename (initialfile = 'Untitled.bf', defaultextension = " .bf", filetypes = [("All Files", "*.*"), ("Text Documents", "* .txt"), ("Brainfuck files", "*.bf")]) if self.file == " ": self.file == None else: file = open(self.file, "w+") file.write(self.textArea.get(1.0, END)) file.close() self.self.title(os.path.basename(self.file) + " - Vulgar") else: file = open(self.file, "w+") file.write(self.textArea.get(1.0, END)) file.close() self.update_line_nums() def SaveAs(self): self.file = asksaveasfilename (initialfile = 'Untitled.bf', defaultextension = " .bf", filetypes = [("All Files", "*.*"), ("Text Documents", "* .txt"), ("Brainfuck files", "*.bf", "*.b")]) if self.file == " ": pass else: file = open(self.file, "w+") file.write(self.textArea.get(1.0, END)) file.close() self.self.title(os.path.basename(self.file) + " - Vulgar") def undo(self): try: self.textArea.event_generate("<<Undo>>") self.update_line_nums() return "break" except Exception as e: showinfo("An Error Occured",e) def redo(self, event=None): try: self.textArea.event_generate("<<Redo>>") self.update_line_nums() return "break" except Exception as e: showinfo("An Error Occured", e) def cut(self): try: self.textArea.event.generate("<<Cut>>") except Exception as e: showerror("An Error Occured", e) self.update_line_nums() def copy(self): try: self.textArea.event.generate("<<Copy>>") except Exception as e:showerror("An Error Occured", e) def paste(self): try: self.textArea.event.generate("<<Paste>>") except Exception as e:showerror("An Error Occured", e) self.update_line_nums() def Setbg(self): useless, color = askcolor(title = "choose a background color") self.textArea.config(background = color) self.update_line_nums() def Setfg(self): useless, color = askcolor(title= "choose your text color") self.textArea.config(foreground = color) self.update_line_nums() def SetCurs(self): useless, color = askcolor(title = "choose your cursor's color") self.textArea.config(insertbackground = color) self.update_line_nums() def Run(self): code = self.textArea.get(0.0, END) symbols = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '"', "'", '{', "}", '|', "/", "\ "] for i in code: if i.isdigit() or i.isalpha() is True or i in symbols: self.s = i if self.s: self.idx = '1.0' while 1: self.idx = self.textArea.search(self.s, self.idx, nocase = 1, stopindex = END) if not self.idx:break self.lastidx = '%s+%dc' % (self.idx, len(self.s)) self.textArea.tag_add('found', self.idx, self.lastidx) self.idx = self.lastidx self.textArea.tag_config('found', background = 'red') showerror("Error", "invalid syntax") self.textArea.tag_config('found', background = None) self.tabControl.select(self.tab2) output = brainfuck.evaluate(code) self.View.config(state = NORMAL) self.View.insert(END, str(output))#don't know why but it prints the output to your python shell instead self.View.delete(0.0, END) self.View.insert(0.0, self.text) self.View.config(state = DISABLED)
class ScrolledTextInfoFrame(Frame): def __init__(self, master, *args, **kwargs): self.master = master super(ScrolledTextInfoFrame, self).__init__(self.master, *args, **kwargs) self.saved_time = StringVar() self.highlighter = Highlighter() self._create_widgets() # the associated file self._file = None # TODO: rename the textentry def _create_widgets(self): # create a Text widget and read in the file self.textentry = ScrolledText(self, wrap=WORD) self.textentry.grid(column=0, row=0, columnspan=2, sticky='nsew') for key, value in self.highlighter.style: self.textentry.tag_configure(key, foreground=value) self.save_label = Label(self, textvar=self.saved_time) self.save_label.grid(column=0, row=1, sticky='es') self.save_btn = Button(self, text="Save", command=self.save_file) self.save_btn.grid(column=1, row=1, sticky='es') self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(1, weight=0) self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(1, weight=0) def update(self): self._update_savetime() self.textentry.delete(1.0, END) with open(self.file.file, 'r') as file: self.textentry.insert(END, file.read()) if HAS_PYGMENTS: if self.highlighter.change_type(self.file.dtype): # remove current tags for tag in self.textentry.tag_names(): self.textentry.tag_configure(tag, foreground="#000000") for key, value in self.highlighter.style.items(): self.textentry.tag_configure(key, foreground=value) self.syn() def _update_savetime(self): self.saved_time.set("Last saved:\t{0}\t".format(self.file.saved_time)) @threaded def syn(self, event=None): """ Allow for syntax highlighting. Source: https://stackoverflow.com/a/30199105 This will highlight the entire document once. Dynamic highlighting not yet supported. #TODO: (maybe?): https://stackoverflow.com/questions/32058760/improve-pygments-syntax-highlighting-speed-for-tkinter-text/32064481 # noqa This is threaded to hopefully stop it blocking the view from displaying and causing a race condition. """ self.textentry.mark_set("range_start", "1.0") data = self.textentry.get("1.0", "end-1c") lexer = self.highlighter.lexer if lexer is not None: for token, content in lex(data, lexer()): self.textentry.mark_set("range_end", "range_start + %dc" % len(content)) self.textentry.tag_add(str(token), "range_start", "range_end") self.textentry.mark_set("range_start", "range_end") def save_file(self): """ Write the current data in the text widget back to the file """ file_contents = self.textentry.get("1.0", "end-1c") with open(self.file.file, 'w') as file: file.write(file_contents) savetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.file.saved_time = savetime self._update_savetime() # also re-apply the syntax highlighting self.syn() @property def file(self): return self._file @file.setter def file(self, other): """ Set the file property to whatever the new file is. When this happens the update command will be called which will redraw the channel info list """ # if the file is being set as a con_file continue if other != self._file: self._file = other self.update()
class SummaryFrame(Observer, FrameBase): def _init_frame(self): # ROW 0 self.title = tk.Label(self, text='Summary', font=self.root_frame.font_title) self.title.grid(column=0, row=0, columnspan=2, sticky='w', padx=4, pady=4) # ROW 1 self.receipt = ScrolledText(self) self.receipt.grid(column=0, row=1, columnspan=6, sticky='nsew', padx=2, pady=2) self.receipt.bind("<FocusIn>", self._select_all) self.receipt.bind("<Control-a>", self._select_all) self.assign_subject(OrderController().last_order) # ROW 2 self.clipboard_button = tk.Button(self, text='Copy to clipboard', command=self._copy_to_clipboard) self.clipboard_button.grid(column=0, row=2, sticky='e', padx=2, pady=2) self.save_button = tk.Button(self, text='Save receipt', command=self._save_receipt) self.save_button.grid(column=1, row=2, sticky='e', padx=2, pady=2) self.next_button = tk.Button(self, text='Finish', command=self.goto_home) self.next_button.grid(column=5, row=2, sticky='e', padx=2, pady=2) self.columnconfigure(2, weight=1) # self.columnconfigure(4, minsize=30) self.rowconfigure(1, weight=1) self.configure(padx=2, pady=2) def _select_all(self, event): self.receipt.tag_add('sel', '1.0', 'end') self.receipt.mark_set('insert', '1.0') self.receipt.see('insert') return 'break' def _copy_to_clipboard(self): self.root_win.clipboard_clear() self.root_win.clipboard_append(self.subject.get_receipt()) return 'break' def _save_receipt(self): filename = filedialog.asksaveasfilename( parent=self, title='Select where to save the receipt', filetypes=[('Plaintext file', '*.txt')], ) if filename: self.subject.save_receipt(filename) def update_content(self): receipt = self.subject.get_receipt() # self.receipt.insert('1.0', 'LMAO\nhehehehheeheh\nbruuuuuuuuuuuuuu\nkek') self.receipt['state'] = 'normal' self.receipt.delete('1.0', 'end') self.receipt.insert('1.0', receipt) self.receipt['state'] = 'disabled' # self.receipt.insert('1.1', 'WUTBRUH') def goto_home(self): pass def _on_frame_destroy(self): pass
class ChatForm(tk.Frame): font_color = "#000000" font_size = 12 def on_list_click(self, e): name = self.chatroom_user_list.get( self.chatroom_user_list.curselection()) for tmp in memory.chatroom_user_list[self.username]: if tmp[1] == name: uname = tmp[0] for fn in memory.friend_list: if uname == fn[1]: # It's friend... uname = memory.friend_list[fn] + " (" + uname + ")" run(uname) return # Not friend... result = messagebox.askokcancel("还不是好友?", "你和" + name + "还不是好友,是否立即添加?") if result: friend_name = uname.encode() serializeMessage = common_handler.pack_message( common_handler.MessageType.add_friend, friend_name) client_socket.send_msg(serializeMessage) messagebox.showinfo('添加好友', '好友请求已发送') def __init__(self, master=None, username=None, nickname="Unkown"): super().__init__(master) self.master = master self.username = username self.nickname = nickname self.master.resizable(width=True, height=True) self.master.geometry('660x500') self.master.minsize(420, 370) self.master.title("与 {} 聊天中...".format(self.nickname)) memory.Chat_window[self.username] = self print(memory.Chat_window) # Chatroom window for v in memory.friend_list: if v[1] == self.username: if v[0] == 2: self.left_frame = tk.Frame(self) self.scroll = Scrollbar(self.left_frame) self.scroll.pack(side=RIGHT, fill=Y) self.chatroom_user_list = Listbox( self.left_frame, yscrollcommand=self.scroll.set) self.chatroom_user_list.bind("<Double-Button-1>", self.on_list_click) self.scroll.config(command=self.chatroom_user_list.yview) self.chatroom_user_list.pack(expand=True, fill=BOTH) self.update_chatroom_user_list(v[1]) self.left_frame.pack(side=RIGHT, expand=True, fill=BOTH) # self.friend_name = tk.Label( # self.left_frame, text=nickname, bg='#EEE', width=15) # self.friend_name.pack(expand=True, fill=BOTH, ipadx=5, ipady=5) self.right_frame = tk.Frame(self, bg='white') self.right_frame.pack(side=LEFT, expand=True, fill=BOTH) self.input_frame = tk.Frame(self.right_frame) self.input_textbox = ScrolledText(self.right_frame, height=7) self.input_textbox.bind("<Control-Return>", self.send_message) self.input_textbox.bind_all('<Key>', self.apply_font_change) self.send_btn = tk.Button(self.input_frame, text='发送消息(Ctrl+Enter)', command=self.send_message) self.send_btn.pack(side=RIGHT, expand=False) self.font_btn = tk.Button(self.input_frame, text='字体颜色', command=self.choose_color) self.font_btn.pack(side=LEFT, expand=False) self.font_btn = tk.Button(self.input_frame, text='字体大小', command=self.choose_font_size) self.font_btn.pack(side=LEFT, expand=False) # self.image_btn = tk.Button( # self.input_frame, text='发送图片', command=self.send_image) # self.image_btn.pack(side=LEFT, expand=False) self.chat_box = ScrolledText(self.right_frame, bg='white') self.input_frame.pack(side=BOTTOM, fill=X, expand=False) self.input_textbox.pack(side=BOTTOM, fill=X, expand=False, padx=(0, 0), pady=(0, 0)) self.chat_box.pack(side=BOTTOM, fill=BOTH, expand=True) self.chat_box.bind("<Key>", lambda e: "break") self.chat_box.tag_config("default", lmargin1=10, lmargin2=10, rmargin=10) self.chat_box.tag_config("me", foreground="green", spacing1='5') self.chat_box.tag_config("them", foreground="blue", spacing1='5') self.chat_box.tag_config("message", foreground="black", spacing1='0') self.chat_box.tag_config("system", foreground="grey", spacing1='0', justify='center', font=(None, 8)) self.pack(expand=True, fill=BOTH, padx=5, pady=5, ipadx=5, ipady=5) def append_to_chat_box(self, time, user, message, tags): if user == memory.username: user = "******" time_info = "%s %s 说:\n" % (time, user) self.chat_box.insert(tk.END, time_info, [tags, 'message']) self.chat_box.insert(tk.END, message, [tags, 'default']) self.chat_box.insert(tk.END, "\n", [tags, 'message']) self.chat_box.update() self.chat_box.see(tk.END) def send_message(self, _=None): stime = dtime.datetime.now() time_info = "%s年%s月%s日 %s时%s分%s秒" % (stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second) message = self.input_textbox.get("1.0", END) if not message or message.replace(" ", "").\ replace("\r", "").replace("\n", "") == '': return for k1 in memory.friend_list: if k1 == (1, self.username): self.append_to_chat_box(time_info, "我", message, 'me') self.input_textbox.delete("1.0", END) # format datetime send_message_handler(time_info, message, self.username) return 'break' def choose_color(self): _, self.font_color = colorchooser.askcolor( initialcolor=self.font_color) self.apply_font_change(None) def choose_font_size(self): result = simpledialog.askinteger("设置", "请输入字体大小", initialvalue=self.font_size) if result is None: return self.font_size = result self.apply_font_change(None) def apply_font_change(self, _): try: self.input_textbox.tag_config('new', foreground=self.font_color, font=(None, self.font_size)) self.input_textbox.tag_add('new', '1.0', END) except Exception: pass def close_window(self): del memory.Chat_window[self.username] self.master.destroy() def update_chatroom_user_list(self, chatroom_name): cn = chatroom_name.encode() serializeMessage = common_handler.pack_message( common_handler.MessageType.query_room_users, cn) client_socket.send_msg(serializeMessage)
class StrFindGUI: def __init__(self): '类的构造函数 主要用于绘制应用程序的界面' self.root = Tk() self.root.title(u"敏感信息查找") self.root.geometry('800x600') self.root.resizable(FALSE,FALSE) #top self.top_frame = Frame(self.root) self.top_frame.grid(row=0,column=0,columnspan=200) #top_label_logPath self.path_label = Label(self.top_frame,text=u"日志路径:", padx=1, pady=1) self.path_label.grid(row=0,column=0) #top_entry_logPath self.path = StringVar() self.path_entry = Entry(self.top_frame, textvariable=self.path, highlightthickness=2, width=94) self.getini = GetINI() #实例化一个GetINI对象,用来读取ini文件 self.getini.Read(global_variable.path_Keywordini) self.path_name = self.getini.Get('path','PathName') self.path.set(self.path_name) #设置默认搜索路径 self.path_entry.grid(row=0,column=1,columnspan=4) #top_button self.path_button = Button(self.top_frame, text=u"打开", padx=1, pady=1,width=6, cursor='hand2', command=self.SelectPath) self.path_button.grid(row=0,column=5) #top_label_configurepath self.configure_path_label = Label(self.top_frame, text=u"配置路径:",padx=1,pady=1) self.configure_path_label.grid(row=1,column=0) #top_entry_configurepath self.configure_path_name = StringVar() self.configure_path_entry = Entry(self.top_frame, textvariable=self.configure_path_name,highlightthickness=2,width=94) self.configure_path_entry.grid(row=1,column=1,columnspan=4) #top_button_configurepath self.configurepath_button = Button(self.top_frame, text=u"打开", padx=1, pady=1, width=6, cursor="hand2", command=self.SelectConfigurePath) self.configurepath_button.grid(row=1,column=5) #top_label self.configure_path_label = Label(self.top_frame, text=u"搜索结果:",padx=1,pady=1) self.configure_path_label.grid(row=2,column=0) #top_entry self.related_file_name = StringVar() self.search_display =Entry(self.top_frame, textvariable=self.related_file_name,highlightthickness=2, width=94, state=DISABLED) self.search_display.grid(row=2,column=1,columnspan=4) #top_button self.search_button = Button(self.top_frame, text=u"搜索",padx=1, pady=1,width=6,cursor='hand2',command=self.SearchSensitiveInfo) self.search_button.grid(row=2,column=5) #top_button self.search_button = Button(self.top_frame, text=u"选择", padx=3, pady=6,width=7,cursor='hand2',command=self.SelectKeyword) self.search_button.grid(row=3,column=0,padx=10,rowspan=2) #top_checkbutton #标记com.txt或者ecat.txt日志是否加密 self.tk_var_com = IntVar() self.isEncriptComtxt_checkbutton = Checkbutton(self.top_frame,text="com日志是否加密", variable=self.tk_var_com, command=self.isEncryptLog) self.isEncriptComtxt_checkbutton.grid(row=3,column=1) self.tk_var_log = IntVar() self.isEncriptComtxt_checkbutton = Checkbutton(self.top_frame,text="ecat日志是否加密", variable=self.tk_var_log, command=self.isEncryptLog) self.isEncriptComtxt_checkbutton.grid(row=4,column=1) #top_button self.search_button = Button(self.top_frame, text=u"检查Resources", padx=3, pady=6,width=13,cursor='hand2',command=self.SearchInHtml) self.search_button.grid(row=3,column=2,padx=10,rowspan=2) #top_button self.search_button = Button(self.top_frame, text=u"检查账密配置", padx=3, pady=6,width=13,cursor='hand2',command=self.SearchPassword) self.search_button.grid(row=3,column=3,padx=10,rowspan=2) #mid #list keyword self.keyword_list_01 = ScrolledText(self.root,width=15,height=20) self.keyword_list_01.grid(row=1,column=0,rowspan=2,sticky=W) self.keyword_list_01.insert(END,"报文域\n支持自定义输入 \n") self.keyword_list_01.tag_add('tag_01','1.0','2.100') self.keyword_list_01.tag_config('tag_01', background='yellow', foreground='red') self.keyword_list_01.tag_bind('tag_01',"<Enter>",self.ShowDetails) self.keyword_list_01.tag_bind('tag_01',"<Leave>",self.HideDetails) self.keyword_list_02 = ScrolledText(self.root,width=15,height=10) self.keyword_list_02.grid(row=1,column=1) self.keyword_list_02.insert(END,"敏感文件路径\n支持自定义输入 \n") self.keyword_list_02.tag_add('tag_01','1.0','2.100') self.keyword_list_02.tag_config('tag_01', background='yellow', foreground='red') self.keyword_list_02.tag_bind('tag_01',"<Enter>",self.ShowDetails) self.keyword_list_02.tag_bind('tag_01',"<Leave>",self.HideDetails) self.keyword_list_03 = ScrolledText(self.root,width=15,height=9) self.keyword_list_03.grid(row=2,column=1) self.keyword_list_03.insert(END,"以身份证信息命名的文件\n支持自定义输入 \n") self.keyword_list_03.tag_add('tag_01','1.0','2.100') self.keyword_list_03.tag_config('tag_01', background='yellow', foreground='red') self.keyword_list_03.tag_bind('tag_01',"<Enter>",self.ShowDetails) self.keyword_list_03.tag_bind('tag_01',"<Leave>",self.HideDetails) self.keyword_list_04 = ScrolledText(self.root,width=15,height=15) self.keyword_list_04.grid(row=3,column=0,sticky=W) self.keyword_list_04.insert(END,"个人隐私信息\n支持自定义输入 \n") self.keyword_list_04.tag_add('tag_01','1.0','2.100') self.keyword_list_04.tag_config('tag_01', background='yellow', foreground='red') self.keyword_list_04.tag_bind('tag_01',"<Enter>",self.ShowDetails) self.keyword_list_04.tag_bind('tag_01',"<Leave>",self.HideDetails) self.keyword_list_05 = ScrolledText(self.root,width=15,height=15) self.keyword_list_05.grid(row=3,column=1,sticky=W) self.keyword_list_05.insert(END,"密钥信息、其他安全信息\n支持自定义输入 \n") self.keyword_list_05.tag_add('tag_01','1.0','2.100') self.keyword_list_05.tag_config('tag_01', background='yellow', foreground='red') self.keyword_list_05.tag_bind('tag_01',"<Enter>",self.ShowDetails) self.keyword_list_05.tag_bind('tag_01',"<Leave>",self.HideDetails) self.sensitive_info_listbox = ScrolledText(self.root,width=74,height=29,spacing1=3) self.sensitive_info_listbox.grid(row=1,column=6,rowspan=10,columnspan=100) ''' #test&debug for item in range(1, 300): self.sensitive_info_listbox.insert(END, item) ''' self.ModifyKeywordini() self.CreateChildWindow() #读取keyword.ini中的sensitive_documents,并将其值插入到界面上的self.keyword_list_02文本框中 sensitive_documents = self.getini.GetItems('sensitive_documents') line = 2 for a_sensitve_document in sensitive_documents: self.keyword_list_02.insert(END, a_sensitve_document[1]+'\n') #为插入的关键字增加Tag tag_name = 'position_tag_' + str(line) #self.keyword_list_02.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.keyword_list_02.tag_add(tag_name,'{line}.0'.format(line=line),'{line}.end'.format(line=line)) self.keyword_list_02.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.Locate_Keyword_In_Result, tag_name=tag_name, keyword_listbox=self.keyword_list_02)) line = line + 1 #读取keyword.ini中的idcardfiles_path,并将其值插入到界面上的self.keyword_list_03文本框中 idcardfiles_paths = self.getini.GetItems('idcardfiles_path') line = 2 for a_idcardfiles_path in idcardfiles_paths: self.keyword_list_03.insert(END, a_idcardfiles_path[1]+'\n') #为插入的关键字增加Tag tag_name = 'position_tag_' + str(line) #self.keyword_list_04.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.keyword_list_03.tag_add(tag_name,'{line}.0'.format(line=line),'{line}.end'.format(line=line)) self.keyword_list_03.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.Locate_Keyword_In_Result, tag_name=tag_name, keyword_listbox=self.keyword_list_03)) line = line + 1 #读取keyword.ini中的personal_privacy,并将其值插入到界面上的self.keyword_list_04文本框中 personal_privacy = self.getini.GetItems('personal_privacy') line = 2 for a_personal_privacy in personal_privacy: self.keyword_list_04.insert(END, a_personal_privacy[1]+'\n') #为插入的关键字增加Tag tag_name = 'position_tag_' + str(line) #self.keyword_list_04.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.keyword_list_04.tag_add(tag_name,'{line}.0'.format(line=line),'{line}.end'.format(line=line)) self.keyword_list_04.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.Locate_Keyword_In_Result, tag_name=tag_name, keyword_listbox=self.keyword_list_04)) line = line + 1 #读取keyword.ini中的keyinfo,并将其值插入到界面上的self.keyword_list_04文本框中 keyinfo = self.getini.GetItems('keyinfo') line = 2 for a_keyinfo in keyinfo: self.keyword_list_05.insert(END, a_keyinfo[1]+'\n') #为插入的关键字增加Tag tag_name = 'position_tag_' + str(line) #self.keyword_list_05.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.keyword_list_05.tag_add(tag_name,'{line}.0'.format(line=line),'{line}.end'.format(line=line)) self.keyword_list_05.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.Locate_Keyword_In_Result, tag_name=tag_name, keyword_listbox=self.keyword_list_05)) line = line + 1 #读取keyword.ini中的special_paths并保存在全局变量self.special_paths里,将在这些路径里搜索不包含子文件夹的文件 #self.special_paths变量中保存的路径,意味着不会查找该路径中子文件夹中的文件 self.special_paths = [] paths = self.getini.GetItems('special_paths') for a_paths in paths: self.special_paths.append(a_paths[1]) #self.menubar = Menu(self.child_window, tearoff=False) self.root.mainloop() def CreateChildWindow(self): self.child_window=Toplevel() self.child_window.title('请选择') self.child_window.geometry('800x600') self.child_window.resizable(TRUE,TRUE) #self.child_window.attributes('-topmost',True) #self.child_window.overrideredirect(boolean=True) self.child_window.protocol("WM_DELETE_WINDOW", self.callback) #top_button self.button_01 = Button(self.child_window, text=u"选择所有",padx=10, pady=6,width=7,cursor='hand2',command=self.SelectAllKeyword) self.button_01.grid(row=0,column=0,padx=50) self.button_02 = Button(self.child_window, text=u"全不选择",padx=10, pady=6,width=7,cursor='hand2',command=self.DelAllSelect) self.button_02.grid(row=0,column=1,padx=50) self.button_03 = Button(self.child_window, text=u"不选择屏蔽域",padx=10, pady=6,width=7,cursor='hand2',command=self.DelMaskField) self.button_03.grid(row=0,column=2,padx=50) self.button_04 = Button(self.child_window, text=u"选择敏感域",padx=10, pady=6,width=7,cursor='hand2',command=self.SelectSensitiveField) self.button_04.grid(row=0,column=3,padx=50) self.button_05 = Button(self.child_window, text=u"确认",padx=10, pady=6,width=7,cursor='hand2',command=self.Confirm_button) self.button_05.grid(row=1,column=0,padx=50) self.child_window.withdraw() def callback(self): tkinter.messagebox.showinfo("提醒","该操作将不会使用本次选中的报文域参与搜索") self.child_window.withdraw() def SelectPath(self): '与第一个“打开”按钮绑定,将选中文件路径设置为搜索路径' path_name = filedialog.askdirectory(initialdir="D:/") self.path.set(path_name) def SelectConfigurePath(self): '与第二个“打开”按钮绑定,将选中文件路径置为通讯报文配置文件所在路径' path_name = filedialog.askopenfilename(initialdir="D:/",title=u"选择8583配置文件",filetypes=[('xml','*.xml'),('All Files','*')]) self.configure_path_name.set(path_name) #重新指定报文配置文件后,需要重新抓取报文域并更新到Keyword.ini self.ModifyKeywordini() def SelectKeyword(self): '与"选择"按钮绑定' self.child_window.deiconify() i=2 j=0 z=0 try: for a_Keyword_FieldName in self.Keyword_FieldNames: keyword_checkbutton = Checkbutton(self.child_window, text=a_Keyword_FieldName, variable=self.tk_int_var[z],cursor='hand2') keyword_checkbutton.bind("<Button-3>",self.HandlerAdaptor(self.pop_menu,a_Keyword_FieldName=a_Keyword_FieldName)) keyword_checkbutton.grid(row=i, column=j, sticky=W) i = i + 1 z = z + 1 if i == 20: j = j + 1 i = 2 self.SelectSensitiveField() except AttributeError: self.child_window.attributes('-topmost',False) tkinter.messagebox.showinfo('提示','没有找到报文配置文件,请手动指定') self.child_window.withdraw() self.child_window.attributes('-topmost',True) return def pop_menu(self,event,a_Keyword_FieldName): self.menubar = Menu(self.child_window, tearoff=False) ID = a_Keyword_FieldName.partition(":")[0] self.menubar.add_command(label = self.Field_Description[ID]) self.menubar.post(event.x_root, event.y_root) def ShowDetails(self,event): self.details = Menu(self.root, tearoff=False,font = "黑体") self.details.add_command(label = "支持自定义输入,每个关键字以回车键分隔") self.details.post(event.x_root, event.y_root) def HideDetails(self,event): self.details.unpost() self.details.delete(0) def isEncryptLog(self): path_name = self.path.get() try: self.all_files='' #初始化一个保存所有文件的变量 self.all_files = self.TraversalFiles(path_name) #遍历指定路径下的所有文件 except FileNotFoundError: tkinter.messagebox.showinfo('提示','搜索路径为空或者该路径不存在') else: self.all_files = self.all_files.strip('\n') #字符串首尾去换行符处理 files = self.all_files.split('\n') #以\n为分割符,返回分割后的列表 #若勾选com\eCat日志是否加密复选框,则将com\eCat日志后缀修改为.Encrypted #若取消勾选com\eCat日志是否加密复选框,则将com\eCat日志后缀修改为.txt if self.tk_var_com.get() == 1: for a_file in files: a_file_name = a_file.rpartition("\\") if a_file_name[2][0:3] == "COM" and a_file_name[2][3:11].isdigit(): portion = os.path.splitext(a_file) newname = portion[0] + '.Encrypted' os.rename(a_file,newname) else: for a_file in files: a_file_name = a_file.rpartition("\\") if a_file_name[2][0:3] == "COM" and a_file_name[2][3:11].isdigit(): portion = os.path.splitext(a_file) newname = portion[0] + '.txt' os.rename(a_file,newname) if self.tk_var_log.get() == 1: for a_file in files: a_file_name = a_file.rpartition("\\") if a_file_name[2][0:4] == "eCAT" and a_file_name[2][4:12].isdigit(): portion = os.path.splitext(a_file) newname = portion[0] + '.Encrypted' os.rename(a_file,newname) else: for a_file in files: a_file_name = a_file.rpartition("\\") if a_file_name[2][0:4] == "eCAT" and a_file_name[2][4:12].isdigit(): portion = os.path.splitext(a_file) newname = portion[0] + '.txt' os.rename(a_file,newname) def SelectAllKeyword(self): '与“选择所有”按钮绑定,选择所有关键字' i = 0 for var in self.tk_int_var: self.tk_int_var[i].set(1) i = i + 1 def DelAllSelect(self): '与“全不选择”按钮绑定,所有关键字都不选择' i = 0 for var in self.tk_int_var: self.tk_int_var[i].set(0) i = i + 1 def DelMaskField(self): '与“不选择屏蔽域”按钮绑定,打解包配置文件中已经配置屏蔽的报文域取消选择' #获取打解包配置文件的路径,并读取其中的MaskFieldName atmp_conf_path = self.configure_path_name.get() getxml = GetXML() root = getxml.Read(atmp_conf_path) try: MaskFieldName = root.find('TransactionFieldConfig').attrib['MaskFieldName'] except: tkinter.messagebox.showinfo('提示','没有在打解包配置文件中找到MaskFieldName') return MaskFieldName = MaskFieldName.strip().split('|') #轮询self.Keyword_FieldNames,判断报文域是否在MaskFieldName列表里,如果在,则将这个报文域的复选框取消打勾 i = 0 for a_Keyword_FieldName in self.Keyword_FieldNames: a_Keyword_FieldName = a_Keyword_FieldName.partition(":")[2] if a_Keyword_FieldName in MaskFieldName: self.tk_int_var[i].set(0) i = i + 1 def SelectSensitiveField(self): '与“选择敏感域”按钮绑定,将安全技术规范中指定的敏感域默认勾选' #根据《软件安全技术规范》,下列序号报文域属于敏感报文域 sensitiveFieldBitID = [2,14,22,25,26,35,36,45,48,52,53,55,57,58,60,61,64,96,102,103,128] #轮询self.Keyword_FieldNames,判断域序号是否在sensitiveFieldBitID列表里,如果在,则将这个报文域的复选框打勾 i = 0 for a_Keyword_FieldName in self.Keyword_FieldNames: a_Keyword_FieldName = int(a_Keyword_FieldName.partition(":")[0]) if a_Keyword_FieldName in sensitiveFieldBitID: self.tk_int_var[i].set(1) i = i + 1 def Confirm_button(self): '与“确认”按钮绑定,隐藏子窗口,将选中的关键字保存在一个列表,并插入到应用界面上,用来参与搜索' self.child_window.withdraw() i = 0 tkIntVar_value_list = [] for var in self.tk_int_var: tkIntVar_value_list.append(self.tk_int_var[i].get()) i = i + 1 selected_result_dict = dict(zip(self.Keyword_FieldNames,tkIntVar_value_list)) selected_keywords = [] #初始化一个列表用来保存被选中的报文域关键字 for var in selected_result_dict.items(): if var[1] == 1: selected_keywords.append(var[0]) #向keyword_list_01中插入关键字前,需要清空该文本框 self.keyword_list_01.delete(3.0,END) line = 2 for var in selected_keywords: self.keyword_list_01.insert(END,'\n'+var) #为插入的关键字增加Tag tag_name = 'position_tag_' + str(line) #self.keyword_list_05.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.keyword_list_01.tag_add(tag_name,'{line}.0'.format(line=line),'{line}.end'.format(line=line)) self.keyword_list_01.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.Locate_Keyword_In_Result, tag_name=tag_name, keyword_listbox=self.keyword_list_01)) line = line + 1 #debug&test temporarily #Get Keyword real time def GetKeyword_realtime(self): self.T=self.keyword_list.get(0.0,END) messagebox.showinfo('提示',self.T) def TraversalFiles(self,path): '递归遍历指定文件夹下所有的文件(包含子文件夹中的文件)' #将该文件夹(包含子文件夹)中的所有文件,以字符串形式保存到self.all_files变量中,各文件之间以'\n'作分隔符 list = os.listdir(path) for i in range(0,len(list)): temp_file = os.path.join(path, list[i]) #messagebox.showinfo('提示',temp_file) if not os.path.isdir(temp_file): self.all_files = self.all_files + temp_file+'\n' else: self.TraversalFiles(temp_file) return self.all_files def ScanATMP8583(self): '查找程序使用的是什么报文配置文件,并返回其绝对路径' getxml = GetXML() #获取MessageConfig.xml的根节点 try: root = getxml.Read("D:\GrgBanking\eCAT\Config\MessageConfig.xml") except FileNotFoundError: tmp = '-----------------------------------------------------------------' self.sensitive_info_listbox.insert(END, tmp) tmp = '没有找到报文配置文件,请手动指定' self.sensitive_info_listbox.insert(END, tmp) tmp = '-----------------------------------------------------------------' self.sensitive_info_listbox.insert(END, tmp) tkinter.messagebox.showinfo('提示','没有找到报文配置文件,请手动指定') return for DataFormatterService in root.iter(tag='DataFormatterService'): #先判断DataFormatterService alias="Default"才继续判断是否包含ATMP if (DataFormatterService.attrib['alias'] == 'Default') and (DataFormatterService.attrib['cfg'].find('ATMP') != -1): atmp_conf_path = "D:\GrgBanking\eCAT" + DataFormatterService.attrib['cfg'][2:] self.configure_path_name.set(atmp_conf_path) #获取ATMP_8583.xml或者ATMP_FixedLen.xml的根节点 if atmp_conf_path.find('8583') == -1: tmp = '-----------------------------------------------------------------' self.sensitive_info_listbox.insert(END, tmp) tmp = '该版本的报文格式非8583,可能是定长报文格式' self.sensitive_info_listbox.insert(END, tmp) tmp = '-----------------------------------------------------------------' self.sensitive_info_listbox.insert(END, tmp) return atmp_conf_path def ModifyKeywordini(self): '将FieldName遍历抓取出来,保存在Keyword.ini中' atmp_conf_path = self.configure_path_name.get() print(atmp_conf_path) if len(atmp_conf_path) == 0: atmp_conf_path = self.ScanATMP8583() getxml = GetXML() root = getxml.Read(atmp_conf_path) getini = GetINI() getini.Read(global_variable.path_Keywordini) getini.DelSection('FieldName') getini.Write(global_variable.path_Keywordini) getini.AddSection('FieldName') try: Fields = root.find("TransactionFieldConfig").find("BitmapFields").findall("Field") except AttributeError: tkinter.messagebox.showinfo('提示','从报文配置文件里抓取关键字发生异常') return n = 1 #初始化一个字典,BitID:Description形式。用来通过BitID找到该域的域描述 self.Field_Description = dict() for a_Field in Fields: key = 'FieldName' + '_' + str(n) FieldName = a_Field.find("Data").attrib['FieldName'] BitID = a_Field.attrib['BitID'] Description = a_Field.attrib['Description'] self.Field_Description[BitID] = Description #FieldName = FieldName + ":" + BitID FieldName = BitID + ":" + FieldName getini.AddOption('FieldName', key, FieldName) n = n + 1 getini.Write(global_variable.path_Keywordini) self.Keyword_FieldNames = [] #初始化一个全局列表用来保存从报文配置文件中获取的报文域 try: self.getini = GetINI() #实例化一个GetINI对象,用来读取ini文件 self.getini.Read(global_variable.path_Keywordini) FieldNames = self.getini.GetItems('FieldName') #从keyword.ini中获取FieldName节点下的键值对,返回元祖列表 for a_FieldName in FieldNames: self.Keyword_FieldNames.append(a_FieldName[1]) self.tk_int_var = [] #初始化一个列表,用来保存tk整形变量。 for a_Keyword_FieldName in self.Keyword_FieldNames: self.tk_int_var.append(IntVar()) except configparser.NoSectionError: pass #依次对每个文件中的每一行,进行遍历关键字搜索 def Process(self,a_file_name,line): '处理字符串文本行,如果有敏感信息,分别打印到日志和应用界面的列表里,如果没有,不做任何处理' line = line.strip() #将报文域关键字、个人隐私关键字、密钥等安全信息关键字统一保存在all_keywords列表里 fieldnamesandID_keywords = self.keyword_list_01.get(3.0,END) #初始化一个变量用来保存当前被选中的报文域关键字 #目前Field_names_keyword为BitID:FieldName格式,需要去除BitID field_names_keywords = [] fieldnamesndID_keywords = fieldnamesandID_keywords.strip().split('\n') try: for a_fieldnamesndID_keyword in fieldnamesndID_keywords: field_names_keywords.append((a_fieldnamesndID_keyword.split(":"))[1]) except: pass #初始化一个变量用来保存个人隐私信息关键字 personal_privacy_keywords = [] personal_privacy_keywords = (self.keyword_list_04.get(3.0,END)).strip().split('\n') #初始化一个变量用来保存密钥等信息关键字 keyinfo_keywords = [] keyinfo_keywords = (self.keyword_list_05.get(3.0,END)).strip().split('\n') self.all_keywords = field_names_keywords + personal_privacy_keywords + keyinfo_keywords for a_keyword in self.all_keywords: self.root.update() if re.search(a_keyword, line, re.I): print(line,file=open("Sensitive_log_01.txt", 'a', encoding='utf-8')) ''' if line.count('*') <= 2: #no_repeat为重复标志,对于当前字符串文本,将和缓存列表sensitive_lines里的文本行比较,若相同,则将重复标志位置0 no_repeat = 1 if line[0:2].isdigit(): for a_sensitive_line in self.sensitive_lines: if line[12:] == a_sensitive_line[12:]: #日志中时间为12个字符 no_repeat = 0 else: for a_sensitive_line in self.sensitive_lines: if line == a_sensitive_line: no_repeat = 0 #判断重复标志位,仅当重复标志位为1时,才将该行插入到应用界面的列表框里 if no_repeat: self.sensitive_info_listbox.insert(END, line) #插入文本行到应用界面列表框里 self.sensitive_line_source[line] = a_file_name #以字典形式保存该行所在的文件信息,即{line:源文件路径} self.keyword_in_sensitive_line[line] = a_keyword #以字典形式保存改行包含的关键字,即{line:a_keyword} self.root.update() #实时更新界面信息 self.sensitive_lines.append(line) #将文本行插入缓存列表里 ''' def SearchKeywordInfo(self): tmp = '-----------------------------------------------------------------\n' self.sensitive_info_listbox.insert(END, tmp) tmp = '操作正在进行中,请稍后……\n' self.sensitive_info_listbox.insert(END, tmp) tmp = '-----------------------------------------------------------------\n' self.sensitive_info_listbox.insert(END, tmp) path_name = self.path.get() #初始化一个保存当前搜索路径的变量 try: self.all_files='' #初始化一个保存所有文件的变量 self.all_files = self.TraversalFiles(path_name) #遍历指定路径下的所有文件 except FileNotFoundError: tkinter.messagebox.showinfo('提示','搜索路径为空或者该路径不存在') else: self.all_files = self.all_files.strip('\n') #字符串首尾去换行符处理 files = self.all_files.split('\n') #以\n为分割符,返回分割后的列表 self.sensitive_lines = [] #该列表是一个临时缓存,对敏感信息行进一步处理时需要用到 self.sensitive_line_source = dict() #创建一个字典,{line:filename}形式,用来定位该行敏感信息所在文件路径 self.keyword_in_sensitive_line = dict() #创建一个字典,{line:keyword}形式,用来定位该行包含哪个关键字 #初始化一个列表,用来保存(filepath,index,line)元组 self.all_line_details = [] #初始化一个元素,用来保存行信息,包含文件路径,行索引,行内容 a_line_detail = () #先创建一个Sensitive_log_01.txt,防止第一次搜索结果为空时,导致第二次搜索报错 print('Hello~~\n',file=open("Sensitive_log_01.txt", 'a', encoding='utf-8')) #处理txt和log文件,检查是否包含敏感信息 for a_file in files: #判断文件是否是txt或者log类型的,如果是就搜索敏感信息,如果不是就进入下一次循环判断下一个文件的类型 #下面逻辑语句代替: #if a_file.endswith('txt') or a_file.endswith('log'): if a_file.rfind('.') != -1 and (a_file[a_file.rfind('.')+1:] == 'txt' or a_file[a_file.rfind('.')+1:] == 'log'): ''' #打印文件路径信息到日志里,方便定位敏感信息 print('\n\n---------------------------',file=open("Sensitive_log.txt", 'a', encoding='utf-8'),end='') print(a_file,file=open("Sensitive_log.txt", 'a', encoding='utf-8'),end='') print('---------------------------\n\n',file=open("Sensitive_log.txt", 'a', encoding='utf-8'),end='') ''' #打印查找状态到界面上 tmp = '正在查找:'+a_file self.related_file_name.set(tmp) #处理文件内容 with open(a_file,'rb') as f: #每打开一个文件,索引从1开始计数 index = 1 for line in f.readlines(): a_line_detail = (a_file, index, str(line,'utf-8','ignore')) index = index + 1 self.all_line_details.append(a_line_detail) try: self.Process(a_file,str(line,'utf-8','ignore')) except re.error: tkinter.messagebox.showinfo('提示','关键字不符合正则表达式规则,如[,需要转义才符合规则,转义后为\[') tmp = '注意关键字格式,请更新关键字!!!' self.related_file_name.set(tmp) return def SearchSensitiveFile(self): '处理敏感路径,打印路径里所有文件' #因为插入了下面三行字符串,所以行索引需要+3 self.line_index = self.line_index + 3 #打印提示信息到界面 tmp = '-----------------------------------------------------\n' self.sensitive_info_listbox.insert(END, tmp) tmp = '请注意,下面的文件可能为敏感文件,双击可查看\n' self.sensitive_info_listbox.insert(END, tmp) tmp = '-----------------------------------------------------\n' self.sensitive_info_listbox.insert(END, tmp) #打印信息到日志 tmp = '请注意,下面的文件可能为敏感文件\n' print('\n\n-----------------------------\n',file=open("Sensitive_log_02.txt", 'a', encoding='utf-8'),end='') print(tmp,file=open("Sensitive_log_02.txt", 'a', encoding='utf-8'),end='') print('-------------------------------\n\n',file=open("Sensitive_log_02.txt", 'a', encoding='utf-8'),end='') #获取keyword_list_02中所有敏感文件可能存在的路径 all_sensitive_paths = self.keyword_list_02.get(2.0,END) all_sensitive_paths = all_sensitive_paths.strip() all_sensitive_paths = all_sensitive_paths.split() for a_sensitive_path in all_sensitive_paths: if os.path.exists(a_sensitive_path): #判断该路径是否存在 self.all_files='' #判断该路径是否只需要寻找根路径下的文件,而不需要寻找子文件夹中的文件 #如果该路径在self.special_paths里能找到,则self.all_files不保存该路径下的子文件夹中的文件 #反之,则需要保存该路径下包含所有子文件夹中所有文件 if a_sensitive_path in self.special_paths: fileandfolder = os.listdir(a_sensitive_path) for onlyfile in fileandfolder: onlyfile = os.path.join(a_sensitive_path,onlyfile) if not os.path.isdir(onlyfile): self.all_files = self.all_files + onlyfile +'\n' else: #判断该路径下是否有文件,即遍历该路径(包含子路径)下所有文件,保存在self.all_files中 self.TraversalFiles(a_sensitive_path) #如果有文件就处理 if self.all_files.strip(): files = self.all_files.split('\n') for a_file in files: self.sensitive_info_listbox.insert(END, '{a_file}\n'.format(a_file=a_file)) #将疑似敏感文件打印至应用程序界面 #为记录增加Tag tag_name = 'position_tag_' + str(self.line_index) #self.keyword_list_04.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.sensitive_info_listbox.tag_add(tag_name,'{line_index}.0'.format(line_index=self.line_index),'{line_index}.end'.format(line_index=self.line_index)) self.sensitive_info_listbox.tag_bind(tag_name,'<Double-Button-1>',self.HandlerAdaptor(self.OpenThisFile, tag_name=tag_name, keyword_listbox=self.sensitive_info_listbox)) self.line_index = self.line_index + 1 self.sensitive_line_source[a_file] = a_file #以字典形式保存该文件,用来定位源文件 print(a_file,file=open("Sensitive_log_02.txt", 'a', encoding='utf-8')) #将疑似敏感文件打印至日志 def SearchIdcardFile(self): '搜索配置文件中配置的路径中以身份证号和姓名命名的文件,并打印出来' #因为插入了下面三行字符串,所以行索引需要+3 self.line_index = self.line_index + 3 #打印提示信息到界面 tmp = '------------------------------------------------------\n' self.sensitive_info_listbox.insert(END, tmp) tmp = '请注意,下面的文件可能为身份证文件,双击可查看\n' self.sensitive_info_listbox.insert(END, tmp) tmp = '------------------------------------------------------\n' self.sensitive_info_listbox.insert(END, tmp) #打印信息到日志 tmp = '请注意,下面的文件可能为身份证文件' print('\n\n---------------------------',file=open("Sensitive_log_02.txt", 'a', encoding='utf-8'),end='') print(tmp,file=open("Sensitive_log_02.txt", 'a', encoding='utf-8'),end='') print('---------------------------\n\n',file=open("Sensitive_log_02.txt", 'a', encoding='utf-8'),end='') #获取 all_idcardfiles_paths = self.keyword_list_03.get(2.0,END) all_idcardfiles_paths = all_idcardfiles_paths.strip() all_idcardfiles_paths = all_idcardfiles_paths.split() #实例化一个getxml对象,读取IdcardInfo.xml配置文件 getxml = GetXML() #实例化一个GetXML对象,用来处理XML文件 root = getxml.Read(global_variable.path_IdcardInfoxml) for a_idcardfiles_path in all_idcardfiles_paths: if os.path.exists(a_idcardfiles_path): #判断该路径是否存在 self.all_files='' self.TraversalFiles(a_idcardfiles_path) #判断该路径下是否有文件,即遍历该路径(包含子路径)下所有文件,保存在self.all_files中 if self.all_files.strip(): #如果有文件就处理 files = self.all_files.split('\n') for a_file in files: for idcard in root.iter('idcard'): if re.search(idcard.find('id').text, a_file, re.I): self.sensitive_info_listbox.insert(END, a_file) #将身份证文件打印至应用程序界面 #为记录增加Tag tag_name = 'position_tag_' + str(self.line_index) #self.keyword_list_04.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.sensitive_info_listbox.tag_add(tag_name,'{line_index}.0'.format(line_index=self.line_index),'{line_index}.end'.format(line_index=self.line_index)) self.sensitive_info_listbox.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.OpenThisFile, tag_name=tag_name, keyword_listbox=self.sensitive_info_listbox)) self.line_index = self.line_index + 1 self.sensitive_line_source[a_file] = a_file #以字典形式保存该文件,用来定位源文件 print(a_file,file=open("Sensitive_log_02.txt", 'a', encoding='utf-8')) #将疑似身份证文件打印至日志 if re.search(idcard.find('name').text, a_file, re.I): self.sensitive_info_listbox.insert(END, a_file) #将身份证文件打印至应用程序界面 #为记录增加Tag tag_name = 'position_tag_' + str(self.line_index) #self.keyword_list_04.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.sensitive_info_listbox.tag_add(tag_name,'{line_index}.0'.format(line_index=self.line_index),'{line_index}.end'.format(line_index=self.line_index)) self.sensitive_info_listbox.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.OpenThisFile, tag_name=tag_name, keyword_listbox=self.sensitive_info_listbox)) self.line_index = self.line_index + 1 self.sensitive_line_source[a_file] = a_file #以字典形式保存该文件,用来定位源文件 print(a_file,file=open("Sensitive_log_02.txt", 'a', encoding='utf-8')) #将疑似身份证文件打印至日志 def SearchSensitiveInfo(self): '在.txt或者.log文件里查找敏感信息,在可配置的指定路径下搜索敏感文件' self.sensitive_info_listbox.delete(0.0,END) #已取消该功能,按照波哥的建议,增加功能:将敏感域期望值与MaskFieldName的值比较,如果一个报文域名字在期望值里有,而在MaskFieldName里没有,就将该值打印出来,提醒检查 #在界面指定路径中的txt和log文件搜索查找界面上的关键字 self.SearchKeywordInfo() #self.SearchInLog() self.SearchInSennsitiveLog() #将配置文件中的配置的敏感路径里所有文件打印出来 self.SearchSensitiveFile() #按照均林建议,增加功能:检查配置文件中配置的路径中以身份证号和姓名命名的文件 self.SearchIdcardFile() def SearchInSennsitiveLog(self): #刷新界面,插入结果之前先清空界面 self.sensitive_info_listbox.delete(0.0,END) #初始化一个字典,用来保存关键字-首个包含关键字行索引的键值对,用来在结果中定位关键字所在记录的首行 self.keyword_line_dict = {} #num用来记录首个包含关键字的行索引 num = 1 #line_index用来记录插入的日志行的在Text中索引 self.line_index = 1 #进行第二次搜索,并对搜索结果排序后再显示到界面上 for a_keyword in self.all_keywords: self.lines = [] #初始化一个列表保存符合搜索结果的行内容,用来排序。 with open('Sensitive_log_01.txt', 'rb') as f: for line in f.readlines(): try: self.SearchFieldNameInLine(a_keyword,str(line,'utf-8','ignore')) except re.error: tkinter.messagebox.showinfo('提示','关键字不符合正则表达式规则,如[,需要转义才符合规则,转义后为\[') tmp = '注意关键字格式,请更新关键字!!!' self.related_file_name.set(tmp) return #修改字典,记录关键字-首个包含关键字行索引的键值对 if not len(self.lines): self.keyword_line_dict[a_keyword] = None else: self.keyword_line_dict[a_keyword] = num #行索引根据一个关键字含有的行记录数量联动 num = len(self.lines) + num + 1 #对符合含有a_keyword关键字记录的行进行排序,然后将排序后的结果插入到界面上 self.lines.sort() for var in self.lines: self.sensitive_info_listbox.insert(END,var) print(var,file=open("Sensitive_log_02.txt", 'a', encoding='utf-8')) #为界面上的行记录增加Tag tag_name = 'position_tag_' + str(self.line_index) #self.keyword_list_04.tag_add(tag_name,"%d.%d" % (line, column),"%d.end" % (line)) self.sensitive_info_listbox.tag_add(tag_name,'{line_index}.0'.format(line_index=self.line_index),'{line_index}.end'.format(line_index=self.line_index)) self.sensitive_info_listbox.tag_bind(tag_name,' <Double-Button-1>',self.HandlerAdaptor(self.Locate_Line_In_log, tag_name=tag_name, keyword_listbox=self.sensitive_info_listbox)) self.line_index = self.line_index + 1 self.sensitive_info_listbox.insert(END,'\n') self.line_index = self.line_index + 1 tmp = '查找完毕!!!' self.related_file_name.set(tmp) def SearchPassword(self): self.sensitive_line_source = dict() self.sensitive_info_listbox.delete(0.0,END) #获取配置文件中的[xml_path]搜索路径 getini = GetINI() getini.Read(global_variable.path_Keywordini) path_name = getini.Get('xml_path','pathname') #遍历搜索路径中所有文件,最终保存在一个叫做files的列表里 try: self.all_files = "" self.all_files = self.TraversalFiles(path_name) except: tkinter.messagebox.showinfo("提示","搜索路径为空或者该路径不存在") else: self.all_files = self.all_files.strip() files = self.all_files.split('\n') index = 1 #创建索引 #筛选非./TransactionFlow/路径下xml文件,并在其中寻找账号密码配置 getxml = GetXML() for a_file in files: #排除掉./TransactionFlow/路径和./TwinScreen/中的文件 if a_file.find('TransactionFlow') == -1 and a_file.find('TwinScreen') == -1: #如果是xml文件就进行帐号密码查找 if a_file.endswith('xml'): try: root = getxml.Read(a_file) except: tkinter.messagebox.showinfo("警告","解析某个xml时出问题了") for a_node in getxml.Iter(): #声明一个新字典,用来保存将原字典key值转为小写后的字典 new_dict = {} for key,value in a_node.attrib.items(): new_dict[key.lower()] = value flag = 0 for usename in getini.GetItems('username'): if new_dict.get(usename[1]): flag = 1 self.sensitive_info_listbox.insert(END,a_file+'\n') self.sensitive_line_source[a_file] = a_file tag_name = 'position_tag_' + str(index) self.sensitive_info_listbox.tag_add(tag_name, '{line_index}.0'.format(line_index=index),'{line_index}.end'.format(line_index=index)) self.sensitive_info_listbox.tag_bind(tag_name, '<Double-Button-1>', self.HandlerAdaptor(self.OpenThisFile,tag_name=tag_name,keyword_listbox=self.sensitive_info_listbox)) index = index + 1 var = "username="******"Sensitive_log_02.txt",'a',encoding='utf-8')) print("username={}".format(new_dict.get(usename[1])),file=open("Sensitive_log_02.txt",'a',encoding='utf-8')) for password in getini.GetItems('password'): if new_dict.get(password[1]): if flag == 0: print(a_file, file=open("Sensitive_log_02.txt",'a',encoding='utf-8')) self.sensitive_info_listbox.insert(END,a_file+'\n') self.sensitive_line_source[a_file] = a_file tag_name = 'position_tag_' + str(index) self.sensitive_info_listbox.tag_add(tag_name, '{line_index}.0'.format(line_index=index),'{line_index}.end'.format(line_index=index)) self.sensitive_info_listbox.tag_bind(tag_name, '<Double-Button-1>', self.HandlerAdaptor(self.OpenThisFile,tag_name=tag_name,keyword_listbox=self.sensitive_info_listbox)) index = index + 1 var = "password="******"password={}".format(new_dict.get(password[1])),file=open("Sensitive_log_02.txt",'a',encoding='utf-8')) self.sensitive_info_listbox.insert(END,'\n') index = index + 1 def SearchInHtml(self): self.sensitive_line_source = dict() self.sensitive_info_listbox.delete(0.0,END) #获取配置文件中的[html_path]搜索路径 getini = GetINI() getini.Read(global_variable.path_Keywordini) path_name = getini.Get('html_path','pathname') all_html_attribute = getini.GetItems('html_attribute') html_attribute = [] for a_html_attribute in all_html_attribute: html_attribute.append(a_html_attribute[1]) #创建索引 index = 1 #遍历搜索路径中所有文件,最终保存在一个叫做files的列表里 try: self.all_files = "" self.all_files = self.TraversalFiles(path_name) except: tkinter.messagebox.showinfo("提示","搜索路径为空或者该路径不存在") else: self.all_files = self.all_files.strip() files = self.all_files.split('\n') getxml = GetXML() for a_file in files: if a_file.endswith('html'): html = getxml.ReadHtml(a_file) hrefs_01 = html.xpath("//*[@id = 'txtIDCard']") hrefs_02 = html.xpath("//*[@id = 'txtMobilePhone']") hrefs_03 = html.xpath("//*[@id = 'txtName']") if hrefs_01 or hrefs_02 or hrefs_03: self.sensitive_info_listbox.insert(END, a_file + '\n') self.sensitive_line_source[a_file] = a_file tag_name = 'position_tag_' + str(index) self.sensitive_info_listbox.tag_add(tag_name, '{line_index}.0'.format(line_index=index),'{line_index}.end'.format(line_index=index)) self.sensitive_info_listbox.tag_bind(tag_name, '<Double-Button-1>', self.HandlerAdaptor(self.OpenThisFile, tag_name=tag_name, keyword_listbox=self.sensitive_info_listbox)) index = index + 1 if hrefs_03: if hrefs_03[0].text and (len(hrefs_03[0].text.strip()) != 0) : var = hrefs_03[0].text.strip() self.sensitive_info_listbox.insert(END, 'Name = ' + var + '\n') index = index + 1 if hrefs_01: if hrefs_01[0].text and (len(hrefs_01[0].text.strip()) != 0) : var = hrefs_01[0].text.strip() self.sensitive_info_listbox.insert(END, 'IDCard = ' + var + '\n') index = index + 1 if hrefs_02: if hrefs_02[0].text and (len(hrefs_02[0].text.strip()) != 0) : var = hrefs_02[0].text.strip() self.sensitive_info_listbox.insert(END, 'MobilePhon = ' + var + '\n') index = index + 1 def MeaningForKeyword(self,event): 'listbox控件绑定的回调函数,以消息框的形式展示该行中的关键字具体信息' #按照均林建议,增加该功能。 matching_flag = False #获取选中行中的关键字 #初始化一个标志位,用来标志该关键字是否是敏感报文域,默认不是。 try: keyword = self.keyword_in_sensitive_line[self.sensitive_info_listbox.get(self.sensitive_info_listbox.curselection())] except (KeyError,AttributeError,UnboundLocalError): tkinter.messagebox.showinfo(r'提示','该行没有敏感域关键字。') return getxml = GetXML() #实例化一个GetXML对象,用来处理XML文件 root = getxml.Read(global_variable.ath_MeaningForKeywordxml) for field in root.iter('Field'): if keyword == field.attrib['name']: tkinter.messagebox.showinfo(r'说明','域命名:' +field.attrib['name'] + '\n' + '域序号:' +field.find('id').text + '\n' + '域描述:' +field.find('description').text) matching_flag = True if not matching_flag: tkinter.messagebox.showinfo(r'提示','该行的关键字是:['+ keyword + '],不属于敏感报文域') def SearchInLog(self): all_FieldNames = self.keyword_list.get(0.0,END) #初始化一个变量用来保存当前所有待检查的域命 all_FieldNames = all_FieldNames.split() path_name = self.path.get() #初始化一个保存当前搜索路径的变量 try: self.all_files='' #初始化一个保存所有文件的变量 self.all_files = self.TraversalFiles(path_name) #遍历指定路径下的所有文件 except FileNotFoundError: tkinter.messagebox.showinfo('提示','搜索路径为空或者该路径不存在') else: self.all_files = self.all_files.strip('\n') #字符串首尾去换行符处理 files = self.all_files.split('\n') #以\n为分割符,返回分割后的列表 for a_FieldName in all_FieldNames: for a_file in files: self.SearchFieldName(a_FieldName,a_file) #打印查找状态到界面上 tmp = '查找完毕!!!' self.related_file_name.set(tmp) def SearchFieldName(self, a_FieldName, a_file): #判断文件是否是txt或者log类型的,如果是就搜索敏感信息,如果不是就进入下一次循环判断下一个文件的类型 #下面逻辑语句代替: #if a_file.endswith('txt') or a_file.endswith('log'): if a_file.rfind('.') != -1 and (a_file[a_file.rfind('.')+1:] == 'txt' or a_file[a_file.rfind('.')+1:] == 'log'): ''' #打印文件路径信息到日志里,方便定位敏感信息 print('\n\n---------------------------',file=open("Sensitive_log.txt", 'a', encoding='utf-8'),end='') print(a_file,file=open("Sensitive_log.txt", 'a', encoding='utf-8'),end='') print('---------------------------\n\n',file=open("Sensitive_log.txt", 'a', encoding='utf-8'),end='') ''' #打印查找状态到界面上 tmp = '正在查找:'+a_file self.related_file_name.set(tmp) #处理文件内容 with open(a_file,'rb') as f: for line in f.readlines(): try: self.SearchFieldNameInLine(a_FieldName,str(line,'utf-8','ignore')) except re.error: tkinter.messagebox.showinfo('提示','关键字不符合正则表达式规则,如[,需要转义才符合规则,转义后为\[') tmp = '注意关键字格式,请更新关键字!!!' self.related_file_name.set(tmp) return def SearchFieldNameInLine(self,a_FieldName,line): if re.search(a_FieldName, line, re.I): #print(line,file=open("Sensitive_log_02.txt", 'a', encoding='utf-8')) #self.sensitive_info_listbox.insert(END, line) #插入文本行到应用界面列表框里 self.lines.append(line) self.root.update() #实时更新界面信息 def HandlerAdaptor(self,fun, **kwds): '用于给事件绑定函数传参的中间适配函数' return lambda event,fun=fun,kwds=kwds: fun(event, **kwds) def Locate_Keyword_In_Result(self, event, tag_name, keyword_listbox): #将选中的关键字在Text里Index保存在coordinate中 coordinate = keyword_listbox.tag_ranges(tag_name) #获取选定的关键字值 keyword_value = keyword_listbox.get(coordinate[0],coordinate[1]) if keyword_value.find(':') != -1: keyword_value = keyword_value.partition(':')[2] line_index = self.keyword_line_dict[keyword_value] if line_index == None: tkinter.messagebox.showinfo('提示','没有包含该关键字的日志记录') else: self.sensitive_info_listbox.see('{line_index}.0'.format(line_index = line_index)) def Locate_Line_In_log(self, event, tag_name, keyword_listbox): #将选中的关键字在Text里Index保存在coordinate中 coordinate = keyword_listbox.tag_ranges(tag_name) #获取选定的关键字值 line_value = keyword_listbox.get(coordinate[0],coordinate[1]) for a_line_detail in self.all_line_details: if line_value.strip() == a_line_detail[2].strip(): try: win32api.ShellExecute(0,'open','notepad++.exe','{file} -n{index}'.format(file=a_line_detail[0],index=a_line_detail[1]),'',1) except: tkinter.messagebox.showinfo('提示','请先安装notepad++') return def OpenThisFile(self, event, tag_name, keyword_listbox): 'listbox控件绑定的回调函数,默认参数event不可少,功能是打开改行信息所在的源文件' #将选中的关键字在Text里Index保存在coordinate中 coordinate = keyword_listbox.tag_ranges(tag_name) #获取选定的关键字值 line_value = keyword_listbox.get(coordinate[0],coordinate[1]) try: file = self.sensitive_line_source[line_value] os.startfile(file) except (KeyError,UnboundLocalError): tkinter.messagebox.showinfo('提示','该行无源文件')
class Application(tkinter.Tk): def __init__(self): """Initialize widgets, methods.""" tkinter.Tk.__init__(self) self.grid() fontoptions = families(self) font = Font(family="Verdana", size=10) menubar = tkinter.Menu(self) fileMenu = tkinter.Menu(menubar, tearoff=0) editMenu = tkinter.Menu(menubar, tearoff=0) fsubmenu = tkinter.Menu(editMenu, tearoff=0) ssubmenu = tkinter.Menu(editMenu, tearoff=0) # adds fonts to the font submenu and associates lambda functions for option in fontoptions: fsubmenu.add_command(label=option, command = lambda: font.configure(family=option)) # adds values to the size submenu and associates lambda functions for value in range(1,31): ssubmenu.add_command(label=str(value), command = lambda: font.configure(size=value)) # adds commands to the menus menubar.add_cascade(label="File",underline=0, menu=fileMenu) menubar.add_cascade(label="Edit",underline=0, menu=editMenu) fileMenu.add_command(label="New", underline=1,command=self.new, accelerator="Ctrl+N") fileMenu.add_command(label="Open", command=self.open, accelerator="Ctrl+O") fileMenu.add_command(label="Save", command=self.save, accelerator="Ctrl+S") fileMenu.add_command(label="Exit", underline=1,command=exit, accelerator="Ctrl+Q") editMenu.add_command(label="Copy", command=self.copy, accelerator="Ctrl+C") editMenu.add_command(label="Cut", command=self.cut, accelerator="Ctrl+X") editMenu.add_command(label="Paste", command=self.paste, accelerator="Ctrl+V") editMenu.add_cascade(label="Font", underline=0, menu=fsubmenu) editMenu.add_cascade(label="Size", underline=0, menu=ssubmenu) editMenu.add_command(label="Color", command=self.color) editMenu.add_command(label="Bold", command=self.bold, accelerator="Ctrl+B") editMenu.add_command(label="Italic", command=self.italic, accelerator="Ctrl+I") editMenu.add_command(label="Underline", command=self.underline, accelerator="Ctrl+U") editMenu.add_command(label="Overstrike", command=self.overstrike, accelerator="Ctrl+T") editMenu.add_command(label="Undo", command=self.undo, accelerator="Ctrl+Z") editMenu.add_command(label="Redo", command=self.redo, accelerator="Ctrl+Y") self.config(menu=menubar) self.bind_all("<Control-n>", self.new) self.bind_all("<Control-o>", self.open) self.bind_all("<Control-s>", self.save) self.bind_all("<Control-q>", self.exit) self.bind_all("<Control-b>", self.bold) self.bind_all("<Control-i>", self.italic) self.bind_all("<Control-u>", self.underline) self.bind_all("<Control-T>", self.overstrike) self.bind_all("<Control-z>", self.undo) self.bind_all("<Control-y>", self.redo) self.text = ScrolledText(self, state='normal', height=80, wrap='word', font = font, pady=2, padx=3, undo=True) self.text.grid(column=0, row=0, sticky='NSEW') # Frame configuration self.grid_columnconfigure(0, weight=1) self.resizable(True, True) def new(self, *args): """Creates a new window.""" app = Application() app.title('Python Text Editor') app.option_add('*tearOff', False) app.mainloop() def color(self): """Changes selected text color.""" try: (rgb, hx) = tkinter.colorchooser.askcolor() self.text.tag_add('color', 'sel.first', 'sel.last') self.text.tag_configure('color', foreground=hx) except TclError: pass def bold(self, *args): """Toggles bold for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "bold" in current_tags: self.text.tag_remove("bold", "sel.first", "sel.last") else: self.text.tag_add("bold", "sel.first", "sel.last") bold_font = Font(self.text, self.text.cget("font")) bold_font.configure(weight="bold") self.text.tag_configure("bold", font=bold_font) except TclError: pass def italic(self, *args): """Toggles italic for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "italic" in current_tags: self.text.tag_remove("italic", "sel.first", "sel.last") else: self.text.tag_add("italic", "sel.first", "sel.last") italic_font = Font(self.text, self.text.cget("font")) italic_font.configure(slant="italic") self.text.tag_configure("italic", font=italic_font) except TclError: pass def underline(self, *args): """Toggles underline for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "underline" in current_tags: self.text.tag_remove("underline", "sel.first", "sel.last") else: self.text.tag_add("underline", "sel.first", "sel.last") underline_font = Font(self.text, self.text.cget("font")) underline_font.configure(underline=1) self.text.tag_configure("underline", font=underline_font) except TclError: pass def overstrike(self, *args): """Toggles overstrike for selected text.""" try: current_tags = self.text.tag_names("sel.first") if "overstrike" in current_tags: self.text.tag_remove("overstrike", "sel.first", "sel.last") else: self.text.tag_add("overstrike", "sel.first", "sel.last") overstrike_font = Font(self.text, self.text.cget("font")) overstrike_font.configure(overstrike=1) self.text.tag_configure("overstrike", font=overstrike_font) except TclError: pass def undo(self, *args): """Undo function""" try: self.text.edit_undo() except TclError: pass def redo(self, *args): """Redo function""" try: self.text.edit_redo() except TclError: pass def copy(self, *args): """Copy text""" self.clipboard_clear() self.clipboard_append(self.text.selection_get()) def cut(self, *args): """Cut text""" self.copy self.text.delete("sel.first", "sel.last") def paste(self, *args): """Paste text""" insertion = self.selection_get(selection = "CLIPBOARD") self.text.insert(0.0, insertion) def open(self, *args): """Opens a file dialog to open a plain text file.""" filename = tkinter.filedialog.askopenfilename() with open(filename) as f: text = f.read() self.text.delete("1.0", "end") self.text.insert('insert', text) def save(self, *args): try: """Opens a file dialog to save the text in plain text format.""" text = self.text.get("1.0", "end") filename = tkinter.filedialog.asksaveasfilename() with open(filename, 'w') as f: f.write(text) except FileNotFoundError: pass def exit(self, *args): """Exits the program.""" self.quit()
class Window(Listbox): # Initializes the variables and settings for the project. Finally # executes the create_menu for the menu bar, and the create_notepad # for the text window def __init__(self, master, **kw): # Sets master, or root super().__init__(master, **kw) self.master = master # Set some variables self.current_file_path = '' self.current_file_text = '' self.is_saved = True # Set up the context menu and the text box self.context_popup_menu = Menu(self.master, tearoff=0) self.text_window = ScrolledText(self.master, undo=True) self.text_window.focus() self.user_data = self.text_window.get('1.0', END + '-1c') # Name the window, icon, and start the create functions self.master.title(NAME) # self.master.iconbitmap('./tk/images/icon.ico') self.initiate_shortcuts() self.create_menu() self.create_notepad() self.create_context_menu() # Creates the context menu def create_context_menu(self): # Adds a command for button, separator for separator self.context_popup_menu.add_command(label="Undo", command=lambda: self.undo()) self.context_popup_menu.add_command(label="Redo", command=lambda: self.redo()) self.context_popup_menu.add_separator() self.context_popup_menu.add_command( label="Cut", command=lambda: self.text_window.event_generate("<<Cut>>")) self.context_popup_menu.add_command( label="Copy", command=lambda: self.text_window.event_generate("<<Copy>>")) self.context_popup_menu.add_command( label="Paste", command=lambda: self.text_window.event_generate("<<Paste>>")) self.context_popup_menu.add_separator() self.context_popup_menu.add_command(label="Delete", command=lambda: self.clear()) self.context_popup_menu.add_separator() self.context_popup_menu.add_command(label="Select All", command=lambda: self.select_all()) # Creates the top bar menu def create_menu(self): # Creating menu bar and adding it to master menu_bar = Menu(self.master) text = self.text_window # Telling root that menu_bar is the Window's menu self.master.config(menu=menu_bar) # Creating the File menu dropdown file_menu = Menu(menu_bar, tearoff=False) file_menu.add_command(label="New Document...", command=self.new_file, accelerator="Ctrl+N") file_menu.add_command(label="Open Document...", command=self.open_file, accelerator="Ctrl+O") file_menu.add_command(label="Save...", command=self.save_file, accelerator="Ctrl+S") file_menu.add_command(label="Save as...", command=self.save_as_file, accelerator="Ctrl+Shift+S") file_menu.add_separator() file_menu.add_command(label="Quit", command=self.exit, accelerator="Ctrl+Q") # Adding it to the menu_bar menu_bar.add_cascade(label="File", menu=file_menu, underline=0) # Creating the Edit menu dropdown edit_menu = Menu(menu_bar, tearoff=False) edit_menu.add_command(label="Undo", command=self.undo, accelerator="Ctrl+Z") edit_menu.add_command(label="Redo", command=self.redo, accelerator="Ctrl+Y") edit_menu.add_separator() edit_menu.add_command(label="Cut", command=lambda: text.event_generate("<<Cut>>"), accelerator="Ctrl+X") edit_menu.add_command(label="Copy", command=lambda: text.event_generate("<<Copy>>"), accelerator="Ctrl+C") edit_menu.add_command(label="Paste", command=lambda: text.event_generate("<<Paste>>"), accelerator="Ctrl+V") edit_menu.add_separator() edit_menu.add_command(label="Select All", command=lambda: self.select_all(), accelerator="Ctrl+A") edit_menu.add_command(label="Delete", command=self.clear, accelerator="Del") # edit_menu.add_separator() # edit_menu.add_command(label="Settings...", command=settings, accelerator="Ctrl+S") # Adding it to the menu_bar menu_bar.add_cascade(label="Edit", menu=edit_menu) # Creating the Help menu help_menu = Menu(menu_bar, tearoff=False) help_menu.add_command(label="About...", command=about) # Adding it to the menu_bar menu_bar.add_cascade(label="Help", menu=help_menu) # Bind the shortcuts to their specified functions def initiate_shortcuts(self): self.master.bind("<KeyRelease>", lambda event: self.on_text_change()) self.master.bind("<Control-n>", lambda event: self.new_file()) self.master.bind("<Control-o>", lambda event: self.open_file()) self.master.bind("<Control-s>", lambda event: self.save_file()) self.master.bind("<Control-Shift-s>", lambda event: self.save_as_file()) self.master.bind("<Control-q>", lambda event: self.exit()) self.master.bind("<Control-z>", lambda event: self.undo()) self.master.bind("<Control-y>", lambda event: self.redo()) self.text_window.bind("<Control-a>", lambda event: self.select_all()) # self.master.bind("<Control-s>", lambda event: settings()) self.master.bind("<Button-3>", lambda event: self.right_click_popup(event)) # Display context menu popup def right_click_popup(self, event): try: # Used +45 and + 12 to corner it self.context_popup_menu.tk_popup(event.x_root + 45, event.y_root + 12, 0) finally: self.context_popup_menu.grab_release() # Scaling the text_window to fit the screen def create_notepad(self): self.text_window.pack(fill="both", expand=True) # Returns the value of the text field def get_text_data(self): return self.text_window.get('1.0', END + '-1c') # Clears the text off the screen, resets the variables def clear_text(self): self.text_window.delete('1.0', END) self.current_file_path = '' self.current_file_text = '' # Called when typing, sets the is_saved variable def on_text_change(self): # If the text in the textbox is equal to the saved text in the variable # This is used when opening a file, changing something, then undoing that change if self.get_text_data() == self.current_file_text: self.is_saved = True else: # If the saved file exists or is valid if os.path.isfile(self.current_file_path): # Open the file, save it's data to this_file with open(self.current_file_path, "r") as f: this_file = f.read() # If this_file is equal to the same text in the textbox # Used if no changes were made, and if they were, set to False self.is_saved = True if this_file == self.get_text_data( ) else False else: # If the data is not equal to variable, and no file, then changes # must have been made self.is_saved = False # MENU CONTROL FUNCTIONS # Clear current selection, erase the current file if saved def new_file(self): # If it's saved, clear it and set the file to saved if self.is_saved is True: self.clear_text() self.is_saved = True else: # Popup the saved popup popup_value = is_saved_popup() if popup_value == "yes": # Save the file, clear it and set the is_saved to True if self.save_file() is True: self.clear_text() self.is_saved = True elif popup_value == "no": # Don't save the file, but clear it and set the is_saved to True self.clear_text() self.is_saved = True else: # Something went wrong print("Error: new_file error") # Open a file if the current file is saved, then insert new file data def open_file(self): # If file is saved, open the open_file window if self.is_saved is True: self.open_file_popup() else: # Save the file, if it's saved, open the open_file window popup_value = is_saved_popup() if popup_value == "yes": if self.save_file() is True: self.is_saved = True self.open_file_popup() # Open the open_file window elif popup_value == "no": self.open_file_popup() else: # An error occurred print("Error: open_file error") # The function that displays the open_file popup def open_file_popup(self): # Gets old data from current file old_file = self.current_file_path # Opens the file location, stores it in file_name file_name = filedialog.askopenfilename( title="Open", filetypes=(("Text files", "*.txt"), ("All files", "*.*"))) # If a file was actually selected, open it if file_name is not '': with open(file_name) as f: data = f.read() # Clear current text self.clear_text() # Set the path variable of the new file self.current_file_path = file_name if os.path.isfile( file_name) else old_file # Add the file data to the text_box self.text_window.insert(INSERT, data) # Add the file data to the variable self.current_file_text = data # is_saved is True self.is_saved = True # Save file, if file exists, overwrite it, otherwise, call save_as_file function def save_file(self): # If the file path exists if os.path.isfile(self.current_file_path): # Stores the current text data into the variable self.current_file_text = self.get_text_data() # Saves the data to the existing file (overwriting) with open(self.current_file_path, "w") as f: return True if f.writelines( self.get_text_data()) is True else False else: # File doesn't exist, call save_as_file if self.save_as_file() is True: return True # Saves file with asksaveasfile to open a save as window. def save_as_file(self): # Gets old file path old_file = self.current_file_path # Opens save_as window file_name = filedialog.asksaveasfilename( title="Save As", defaultextension=".txt", filetypes=(("Text files", "*.txt"), ("All files", "*.*"))) # Set current file path self.current_file_path = old_file if file_name is None else file_name # If the file_path already exists if os.path.isfile(self.current_file_path): # Copy the current text to the variable self.current_file_text = self.get_text_data() # Writes to the named file with open(self.current_file_path, "w") as f: f.writelines(self.get_text_data()) return True else: # A file wasn't selected if file_name is '': print("Error: File is none") return False # Create a new file to store the data self.current_file_text = self.get_text_data() with open(file_name, 'w'): pass self.is_saved = True return True # Exit override command def exit(self): # If the file is saved, exit if self.is_saved is True: self.master.quit() else: # If the file is not saved, call the saved_popup popup_value = is_saved_popup() if popup_value == "yes": # Save and then quit if self.save_file() is True: self.is_saved = True self.quit() elif popup_value == "no": # Don't save, just quit self.master.quit() else: # An error occurred print("Error: open_file error") # Undo last action def undo(self): self.text_window.edit_undo() # Redo last action def redo(self): self.text_window.edit_redo() # Clear (delete) the selected text def clear(self): self.text_window.delete(SEL_FIRST, SEL_LAST) self.text_window.update() # Select the selected text (without new line) def select_all(self): self.text_window.tag_add(SEL, "1.0", END + '-1c') self.text_window.mark_set(INSERT, "1.0") self.text_window.see(INSERT) return 'break'
class WbRunner(tk.Frame): def __init__(self, tool_name=None, master=None): # First, try to find the WhiteboxTools exe directory if _platform == 'win32': ext = '.exe' else: ext = '' exe_name = "whitebox_tools{}".format(ext) self.exe_path = path.dirname(path.abspath(__file__)) os.chdir(self.exe_path) for filename in glob.iglob('**/*', recursive=True): if filename.endswith(exe_name): self.exe_path = path.dirname(path.abspath(filename)) break wbt.set_whitebox_dir(self.exe_path) ttk.Frame.__init__(self, master) self.script_dir = os.path.dirname(os.path.realpath(__file__)) self.grid() self.tool_name = tool_name self.master.title("WhiteboxTools Runner") # widthpixels = 800 # heightpixels = 600 # self.master.geometry('{}x{}'.format(widthpixels, heightpixels)) # self.master.resizable(0, 0) # self.master.lift() if _platform == "darwin": os.system( '''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''' ) self.create_widgets() self.working_dir = str(Path.home()) def create_widgets(self): toplevel_frame = ttk.Frame(self, padding='0.1i') (self.toolslist, selected_item) = self.get_tools_list() self.tools_frame = ttk.LabelFrame(toplevel_frame, text="{} Available Tools".format( len(self.toolslist)), padding='0.1i') self.toolnames = tk.StringVar(value=self.toolslist) self.tools_listbox = tk.Listbox(self.tools_frame, height=22, listvariable=self.toolnames) self.tools_listbox.bind("<<ListboxSelect>>", self.update_tool_help) self.tools_listbox.grid(row=0, column=0, sticky=tk.NSEW) self.tools_listbox.columnconfigure(0, weight=10) self.tools_listbox.rowconfigure(0, weight=1) s = ttk.Scrollbar(self.tools_frame, orient=tk.VERTICAL, command=self.tools_listbox.yview) s.grid(row=0, column=1, sticky=(tk.N, tk.S)) self.tools_listbox['yscrollcommand'] = s.set self.tools_frame.grid(row=0, column=0, sticky=tk.NSEW) self.tools_frame.columnconfigure(0, weight=10) self.tools_frame.columnconfigure(1, weight=1) self.tools_frame.rowconfigure(0, weight=1) overall_frame = ttk.Frame(toplevel_frame, padding='0.1i') # json_str = '{"default_value": null, "description": "Directory containing data files.", "flags": ["--wd"], "name": "Working Directory", "optional": true, "parameter_type": "Directory"}' # self.wd = FileSelector(json_str, overall_frame) # self.wd.grid(row=0, column=0, sticky=tk.NSEW) current_tool_frame = ttk.Frame(overall_frame, padding='0.1i') self.current_tool_lbl = ttk.Label( current_tool_frame, text="Current Tool: {}".format(self.tool_name), justify=tk.LEFT) # , font=("Helvetica", 12, "bold") self.current_tool_lbl.grid(row=0, column=0, sticky=tk.W) self.view_code_button = ttk.Button(current_tool_frame, text="View Code", width=12, command=self.view_code) self.view_code_button.grid(row=0, column=1, sticky=tk.E) current_tool_frame.grid(row=1, column=0, sticky=tk.NSEW) current_tool_frame.columnconfigure(0, weight=1) current_tool_frame.columnconfigure(1, weight=1) tool_args_frame = ttk.Frame(overall_frame, padding='0.0i') self.tool_args_frame = ttk.Frame(overall_frame, padding='0.0i') self.tool_args_frame.grid(row=2, column=0, sticky=tk.NSEW) self.tool_args_frame.columnconfigure(0, weight=1) # args_frame = ttk.Frame(overall_frame, padding='0.1i') # self.args_label = ttk.Label(args_frame, text="Tool Arguments:", justify=tk.LEFT) # self.args_label.grid(row=0, column=0, sticky=tk.W) # args_frame2 = ttk.Frame(args_frame, padding='0.0i') # self.args_value = tk.StringVar() # self.args_text = ttk.Entry(args_frame2, width=45, justify=tk.LEFT, textvariable=self.args_value) # self.args_text.grid(row=0, column=0, sticky=tk.NSEW) # self.args_text.columnconfigure(0, weight=1) # self.clearButton = ttk.Button(args_frame2, text="Clear", width=4, command=self.clear_args_box) # self.clearButton.pack(pady=10, padx=10) # self.clearButton.grid(row=0, column=1, sticky=tk.E) # self.clearButton.columnconfigure(0, weight=1) # args_frame2.grid(row=1, column=0, sticky=tk.NSEW) # args_frame2.columnconfigure(0, weight=10) # args_frame2.columnconfigure(1, weight=1) # args_frame.grid(row=2, column=0, sticky=tk.NSEW) # args_frame.columnconfigure(0, weight=1) # # Add the bindings # if _platform == "darwin": # self.args_text.bind("<Command-Key-a>", self.args_select_all) # else: # self.args_text.bind("<Control-Key-a>", self.args_select_all) buttonsFrame = ttk.Frame(overall_frame, padding='0.1i') self.run_button = ttk.Button(buttonsFrame, text="Run", width=8, command=self.run_tool) # self.run_button.pack(pady=10, padx=10) self.run_button.grid(row=0, column=0) self.quitButton = ttk.Button(buttonsFrame, text="Cancel", width=8, command=self.cancel_operation) self.quitButton.grid(row=0, column=1) buttonsFrame.grid(row=3, column=0, sticky=tk.E) output_frame = ttk.Frame(overall_frame, padding='0.1i') outlabel = ttk.Label(output_frame, text="Output:", justify=tk.LEFT) outlabel.grid(row=0, column=0, sticky=tk.NW) k = wbt.tool_help(self.tool_name) self.out_text = ScrolledText(output_frame, width=63, height=10, wrap=tk.NONE, padx=7, pady=7) self.out_text.insert(tk.END, k) self.out_text.grid(row=1, column=0, sticky=tk.NSEW) self.out_text.columnconfigure(0, weight=1) output_frame.grid(row=4, column=0, sticky=tk.NSEW) output_frame.columnconfigure(0, weight=1) # Add the binding if _platform == "darwin": self.out_text.bind("<Command-Key-a>", self.select_all) # self.out_text.bind("<Command-Key-A>", self.select_all) else: self.out_text.bind("<Control-Key-a>", self.select_all) progress_frame = ttk.Frame(overall_frame, padding='0.1i') self.progress_label = ttk.Label(progress_frame, text="Progress:", justify=tk.LEFT) self.progress_label.grid(row=0, column=0, sticky=tk.E, padx=5) self.progress_var = tk.DoubleVar() self.progress = ttk.Progressbar(progress_frame, orient="horizontal", variable=self.progress_var, length=200, maximum=100) self.progress.grid(row=0, column=1, sticky=tk.E) progress_frame.grid(row=5, column=0, sticky=tk.E) overall_frame.grid(row=0, column=1, sticky=tk.NSEW) overall_frame.columnconfigure(0, weight=1) toplevel_frame.columnconfigure(0, weight=1) toplevel_frame.columnconfigure(1, weight=4) # self.pack(fill=tk.BOTH, expand=1) # toplevel_frame.columnconfigure(0, weight=1) # toplevel_frame.rowconfigure(0, weight=1) toplevel_frame.grid(row=0, column=0, sticky=tk.NSEW) # Select the appropriate tool, if specified, otherwise the first tool self.tools_listbox.select_set(selected_item) self.tools_listbox.event_generate("<<ListboxSelect>>") self.tools_listbox.see(selected_item) menubar = tk.Menu(self) filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command(label="Set Working Directory", command=self.set_directory) filemenu.add_command(label="Locate WhiteboxTools exe", command=self.select_exe) filemenu.add_command(label="Refresh Tools", command=self.refresh_tools) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.quit) menubar.add_cascade(label="File", menu=filemenu) editmenu = tk.Menu(menubar, tearoff=0) editmenu.add_command( label="Cut", command=lambda: self.focus_get().event_generate("<<Cut>>")) editmenu.add_command( label="Copy", command=lambda: self.focus_get().event_generate("<<Copy>>")) editmenu.add_command( label="Paste", command=lambda: self.focus_get().event_generate("<<Paste>>")) menubar.add_cascade(label="Edit ", menu=editmenu) helpmenu = tk.Menu(menubar, tearoff=0) helpmenu.add_command(label="About", command=self.help) helpmenu.add_command(label="License", command=self.license) menubar.add_cascade(label="Help ", menu=helpmenu) self.master.config(menu=menubar) # self.get_toolboxes() def help(self): self.print_to_output(wbt.version()) def license(self): self.print_to_output(wbt.license()) def set_directory(self): try: self.working_dir = filedialog.askdirectory( initialdir=self.exe_path) wbt.set_working_dir(self.working_dir) except: messagebox.showinfo( "Warning", "Could not find WhiteboxTools executable file.") def select_exe(self): try: filename = filedialog.askopenfilename(initialdir=self.exe_path) self.exe_path = path.dirname(path.abspath(filename)) wbt.set_whitebox_dir(self.exe_path) self.refresh_tools() except: messagebox.showinfo( "Warning", "Could not find WhiteboxTools executable file.") def run_tool(self): # wd_str = self.wd.get_value() wbt.set_working_dir(self.working_dir) # args = shlex.split(self.args_value.get()) args = [] for widget in self.tool_args_frame.winfo_children(): v = widget.get_value() if v: args.append(v) elif not widget.optional: messagebox.showinfo( "Error", "Non-optional tool parameter not specified.") return self.print_line_to_output("") # self.print_line_to_output("Tool arguments:{}".format(args)) # self.print_line_to_output("") # Run the tool and check the return value for an error if wbt.run_tool(self.tool_name, args, self.custom_callback) == 1: print("Error running {}".format(self.tool_name)) else: self.run_button["text"] = "Run" self.progress_var.set(0) self.progress_label['text'] = "Progress:" self.progress.update_idletasks() def print_to_output(self, value): self.out_text.insert(tk.END, value) self.out_text.see(tk.END) def print_line_to_output(self, value): self.out_text.insert(tk.END, value + "\n") self.out_text.see(tk.END) def cancel_operation(self): wbt.cancel_op = True self.print_line_to_output("Cancelling operation...") self.progress.update_idletasks() def view_code(self): webbrowser.open_new_tab(wbt.view_code(self.tool_name).strip()) def update_tool_help(self, event): selection = self.tools_listbox.curselection() self.tool_name = self.tools_listbox.get(selection[0]) self.out_text.delete('1.0', tk.END) for widget in self.tool_args_frame.winfo_children(): widget.destroy() k = wbt.tool_help(self.tool_name) self.print_to_output(k) j = json.loads(wbt.tool_parameters(self.tool_name)) param_num = 0 for p in j['parameters']: json_str = json.dumps(p, sort_keys=True, indent=2, separators=(',', ': ')) pt = p['parameter_type'] if 'ExistingFileOrFloat' in pt: ff = FileOrFloat(json_str, self, self.tool_args_frame) ff.grid(row=param_num, column=0, sticky=tk.NSEW) param_num = param_num + 1 elif ('ExistingFile' in pt or 'NewFile' in pt or 'Directory' in pt): fs = FileSelector(json_str, self, self.tool_args_frame) fs.grid(row=param_num, column=0, sticky=tk.NSEW) param_num = param_num + 1 elif 'FileList' in pt: b = MultifileSelector(json_str, self, self.tool_args_frame) b.grid(row=param_num, column=0, sticky=tk.W) param_num = param_num + 1 elif 'Boolean' in pt: b = BooleanInput(json_str, self.tool_args_frame) b.grid(row=param_num, column=0, sticky=tk.W) param_num = param_num + 1 elif 'OptionList' in pt: b = OptionsInput(json_str, self.tool_args_frame) b.grid(row=param_num, column=0, sticky=tk.W) param_num = param_num + 1 elif ('Float' in pt or 'Integer' in pt or 'String' in pt or 'StringOrNumber' in pt or 'StringList' in pt): b = DataInput(json_str, self.tool_args_frame) b.grid(row=param_num, column=0, sticky=tk.NSEW) param_num = param_num + 1 else: messagebox.showinfo( "Error", "Unsupported parameter type: {}.".format(pt)) self.update_args_box() self.out_text.see("%d.%d" % (1, 0)) def update_args_box(self): s = "" self.current_tool_lbl['text'] = "Current Tool: {}".format( self.tool_name) # self.spacer['width'] = width=(35-len(self.tool_name)) for item in wbt.tool_help(self.tool_name).splitlines(): if item.startswith("-"): k = item.split(" ") if "--" in k[1]: value = k[1].replace(",", "") else: value = k[0].replace(",", "") if "flag" in item.lower(): s = s + value + " " else: if "file" in item.lower(): s = s + value + "='{}' " else: s = s + value + "={} " # self.args_value.set(s.strip()) def clear_args_box(self): self.args_value.set("") def args_select_all(self, event): self.args_text.select_range(0, tk.END) return 'break' def custom_callback(self, value): ''' A custom callback for dealing with tool output. ''' if "%" in value: try: str_array = value.split(" ") label = value.replace(str_array[len(str_array) - 1], "").strip() progress = float(str_array[len(str_array) - 1].replace( "%", "").strip()) self.progress_var.set(int(progress)) self.progress_label['text'] = label except ValueError as e: print("Problem converting parsed data into number: ", e) except Exception as e: print(e) else: self.print_line_to_output(value) self.update( ) # this is needed for cancelling and updating the progress bar def select_all(self, event): self.out_text.tag_add(tk.SEL, "1.0", tk.END) self.out_text.mark_set(tk.INSERT, "1.0") self.out_text.see(tk.INSERT) return 'break' def get_tools_list(self): list = [] selected_item = -1 for item in wbt.list_tools().splitlines(): if item: if "available tools" not in item.lower(): value = item.split(":")[0] list.append(value) if value == self.tool_name: selected_item = len(list) - 1 if selected_item == -1: selected_item = 0 self.tool_name = list[0] return (list, selected_item) def get_toolboxes(self): toolboxes = set() for item in wbt.toolbox().splitlines( ): # run wbt.toolbox with no tool specified--returns all if item: tb = item.split(":")[1].strip() toolboxes.add(tb) for v in sorted(toolboxes): # print(v) self.print_line_to_output(v) def refresh_tools(self): (self.toolslist, selected_item) = self.get_tools_list() self.tools_listbox.delete(0, len(self.toolslist)) for item in self.toolslist: self.tools_listbox.insert(len(self.toolslist), item) self.tools_frame["text"] = "{} Available Tools".format( len(self.toolslist))
class textEditor: def __init__(self): self.root = Tk() self.root.title('My Text Editor') self.text = ScrolledText(self.root, width=100, height=50) # if using .grid(), the area of text will be on the left when in full screen mode. self.text.pack() menubar = Menu(self.root) filemenu = Menu(menubar) menubar.add_cascade(label="File", menu=filemenu) filemenu.add_command(label="New", command=self.new_file) filemenu.add_command(label="Open", command=self.open_file) filemenu.add_command(label="Save", command=self.save_file) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.exit) editmenu = Menu(menubar) menubar.add_cascade(label="Edit", menu=editmenu) fontmenu = Menu(menubar) menubar.add_cascade(label="Font", menu=fontmenu) fontmenu.add_command(label="Courier", command=self.font_courier) fontmenu.add_command(label="Helvetica", command=self.font_helvetica) fontmenu.add_command(label="Times", command=self.font_times) fontmenu.add_command(label="Roman", command=self.font_roman) menubar.add_command(label="Find", command=self.find_pattern) self.root.config(menu=menubar) self.root.mainloop() def save_file(self): data = self.text.get("1.0", "end-1c") savelocation = filedialog.asksaveasfilename(defaultextension='.txt', title='Save Text') with open(savelocation, "w+") as f: try: f.write(data) except: messagebox.showerror(title="Oops!", message="Unable to save it...") def font_times(self): self.text.config(font=("times", 12)) def font_courier(self): self.text.config(font=("Courier", 15)) def font_helvetica(self): self.text.config(font=("Helvetica", 12)) def font_roman(self): self.text.config(font=("Times New Roman", 12, "bold")) def open_file(self): f = filedialog.askopenfile(mode='r') t = f.read() self.text.delete(0.0, END) self.text.insert(0.0, t) def new_file(self): if len(self.text.get('1.0', END + '-1c')) > 0: ask_for_save = messagebox.askquestion( 'save', 'do you want to save the file') if ask_for_save == 'yes': self.save_file() else: self.text.delete(0.0, END) self.root.title('My Text Editor') def exit(self): ask_for_exit = messagebox.askquestion( "Exit", "Are you sure you want to exit?") if ask_for_exit == 'yes': self.root.destroy() def handle_click(self): self.text.tag_config('Found', background='white', foreground='red') def find_pattern(self): self.text.tag_remove("Found", '1.0', END) find = simpledialog.askstring("Find....", "Enter text:") # prevent frozen because of inputing nothing in find. if not find: return idx = '0.0' if find: idx = '1.0' while 1: idx = self.text.search(find, idx, nocase=1, stopindex=END) if not idx: break lastidx = '%s+%dc' % (idx, len(find)) self.text.tag_add('Found', idx, lastidx) idx = lastidx self.text.bind("<1>", self.handle_click()) data = self.text.get('1.0', END) occurance = data.upper().count(find.upper()) if occurance > 1: label = messagebox.showinfo( "Find", find + " has occurances " + str(occurance) + " times.") elif occurance == 1: label = messagebox.showinfo( "Find", find + " has just occurances " + str(occurance) + " time.") else: label = messagebox.showinfo("Find", "No results")
class GetResourceApp(BaseWin): def __init__(self, tk_win): BaseWin.__init__(self, tk_win) self.input_url = StringVar() self.input_url.set('https://www.meijubie.com/movie/index44655.html') self.processing = False self.selectProcessor = StringVar() # 处理请求的个数 self.current_name = '' def set_init_window(self): self.tk_win.grid_rowconfigure(1, weight=1) self.tk_win.grid_columnconfigure(0, weight=1) labelframe = LabelFrame(text="输入") labelframe.grid_columnconfigure(1, weight=1) labelframe.grid(column=0, row=0, padx=10, pady=10, sticky=EW) Label(labelframe, text="目标网址", justify=LEFT, width=10).grid(row=0, column=0) entry = Entry(labelframe, textvariable=self.input_url) entry.grid(row=0, column=1, sticky=EW, padx=5) entry.bind('<Key-Return>', self.getResourceLink) self.button = Button(labelframe, text="获取", command=self.getResourceLink, width=10) self.button.grid(row=0, column=2, sticky=E, padx=5) Label(labelframe, text="处理器", justify=LEFT, width=10).grid(row=1, column=0) select_process = ttk.Combobox(labelframe, textvariable=self.selectProcessor, state="readonly", values=PROCESS_FUN_NAME_LIST, width=90) select_process.set("请选择网址处理器") select_process.grid(row=1, column=1, sticky=EW, columnspan=2, padx=5, pady=5) if len(PROCESS_FUN_NAME_LIST) > 0: select_process.set(PROCESS_FUN_NAME_LIST[0]) output_frame = LabelFrame(text="链接结果") output_frame.grid(column=0, row=1, sticky=NSEW, padx=10) self.copy_btn = Button(output_frame, text="复制到剪贴板", command=lambda: self.copy(self.output_txt)) self.copy_btn.config(state=DISABLED) self.copy_btn.pack() self.output_txt = ScrolledText(output_frame) self.output_txt.pack(side=TOP, expand=TRUE, fill=BOTH, padx=10, pady=10) self.output_txt.bind( "<Button-3>", lambda x: self.rightKey(x, self.output_txt)) # 绑定右键鼠标事件 self.output_txt.bind("<<Selection>>", self.on_text_selection) # 绑定选择事件 # self.output_txt.grid(column=0, columnspan=4) # self.vbar = ttk.Scrollbar(output_frame, orient=VERTICAL, command=self.output_txt.yview) # self.output_txt.configure(yscrollcommand=self.vbar.set) def on_text_selection(self, event=NONE): # try: # selection = self.output_txt.get(SEL_FIRST, SEL_LAST) # except Exception: # selection = NONE # if selection is not NONE and len(selection) > 0: if self.output_txt.tag_ranges("sel"): self.copy_btn.config(state=NORMAL) else: self.copy_btn.config(state=DISABLED) def getResourceLink(self, event=NONE): if self.processing: return self.processing = True # 创建进度条 self.gress_bar = GressBar() # 禁用按钮 self.button.state = DISABLED th = threading.Thread(target=self.doGetResourceLink) th.setDaemon(True) th.start() # 启动进度条 self.gress_bar.start() pass def doGetResourceLink(self): self.current_name = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) self.output_txt.insert( END, '#########################Begin:%s##########################\n' % self.current_name) request_url = self.input_url.get() if not request_url: self.output_txt.insert(END, '请求的网址为空\n') self.end_process() return self.output_txt.insert(END, request_url + '\n') self.output_txt.insert(END, '\n') processor = PROCESS_FUN_DICT[self.selectProcessor.get()] if processor is None: self.output_txt.insert(END, '未找到对应的网站处理器\n') self.end_process() return last_time = time.time_ns() try: results = processor.getDownloadLink(request_url) except Exception as e: self.output_txt.insert(END, '%s\n' % e.args) self.end_process() return index_start = self.output_txt.index("end-1c linestart") for item in results: self.output_txt.insert(END, item + '\n') index_end = self.output_txt.index("end-1c linestart") self.output_txt.insert( END, '\n耗时=%d毫秒\n' % ((time.time_ns() - last_time) / 1E6)) self.end_process(index_end, index_start) def end_process(self, index_end=END, index_start=END): self.output_txt.insert( END, '###########################End:%s##########################\n' % self.current_name) self.gress_bar.quit() self.button.state = NORMAL self.processing = False # 移除之前的选择 self.output_txt.tag_remove(SEL, '1.0', END) # 设置选中状态 print("\nstart=%s,end=%s\n" % (index_start, index_end)) self.output_txt.tag_add(SEL, index_start, index_end) self.output_txt.focus_set()
class ChatGUI(Frame): def __init__(self, parent, conn): #Frame.__init__(self, parent, background="grey") self.parent = parent self.conn = conn self.centerWindow() self.initUI() def initUI(self): self.lineCounter = 0 # create a custom font self.customFontHeader = font.Font( family="Calibri", slant="italic" ) #family="Helvetica", weight="bold", slant="italic") self.customFontMessage = font.Font(family="Calibri") self.parent.title("Python Chat") frame = Frame(self.parent) frame.pack(fill=BOTH, expand=1, side=LEFT) self.box = ScrolledText(frame, wrap=WORD, relief=GROOVE, width=30, height=18, font=self.customFontMessage) self.box.insert(END, 'Welcome to Python Chat!') self.box.config(state=DISABLED) self.box.pack(expand="yes", fill=BOTH, side=TOP) self.textarea = Text(frame, width=30, height=5) #self.textarea.insert(END, "") self.textarea.bind( "<KeyRelease-Return>", self.gettext) #Se metto on press, rimane una newline in piu self.textarea.pack(expand="yes", fill=BOTH, side=TOP) okButton = Button(frame, text="Panic Button", activebackground="red", command=self.sendFile) okButton.pack(expand="no", fill=BOTH, side=TOP) self.usersFrame = Frame(self.parent) self.usersFrame.pack(fill=BOTH, expand=1, side=RIGHT) self.userListbox = Listbox(self.usersFrame, width=3) self.userListbox.pack(fill=BOTH, expand=1) self.updateUsersFrame() def centerWindow(self): w = 600 h = 475 sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - w) / 2 y = (sh - h) / 2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) def gettext(self, e): #e sta per event, questo e' un listener text = self.textarea.get( "1.0", END ) # 1.0: row:columa - END-2c rimuove l'ultimo carattere, una newline \r\n if "\n" in text: text = text.replace("\n", "") self.textarea.delete( "0.0", END ) #NON VA: il problema e' che viene inviato il carattere di newline ma non incluso nell'area a causa della bind mi sa. Devo escluderlo io self.sendToServer(text) def printConversation(self, message): self.box.config(state=NORMAL) self.box.insert(END, "\n" + message) self.lineCounter = self.lineCounter + 2 #m = re.match("\[.*\] From .*\n", self.box.get("0.0", END)) m = re.search("\[.*\].*:", message, re.MULTILINE) if m is not None: #print("MATCH") #print(m.group(0)) #print(str(m.start(0)) + "_" + str(m.end(0))) #print("COUNTER") #print(str(self.lineCounter) + "." + str(m.start(0)+1) + "___" + str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_add("header", str(self.lineCounter) + "." + str(m.start(0)), str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_config("header", font=self.customFontHeader, foreground="blue") self.box.config(state=DISABLED) #self.box.yview_scroll(10000,"units") self.box.see(END) def sendToServer(self, messageToSend): self.conn.send(messageToSend.encode(encoding='utf_8', errors='strict')) def sendFile(self): #aprire una dialog di quelle predefinite (Sfoglia...) #capire come fare la send di un file sul socket... pass def updateUsersFrame(self): global connectedClients self.userListbox.delete(0, END) self.userListbox.insert(END, "Connected users") for item in connectedClients: self.userListbox.insert(END, item)
class ChatGUI(Frame): def __init__(self, parent, conn): #Frame.__init__(self, parent, background="grey") self.parent = parent self.conn = conn self.centerWindow() self.initUI() def initUI(self): self.lineCounter = 0 # create a custom font self.customFontHeader = font.Font(family="Calibri", slant = "italic") #family="Helvetica", weight="bold", slant="italic") self.customFontMessage = font.Font(family="Calibri") self.parent.title("Python Chat") frame = Frame(self.parent) frame.pack(fill=BOTH, expand=1, side=LEFT) self.box = ScrolledText(frame, wrap=WORD, relief = GROOVE, width=30, height=18, font=self.customFontMessage) self.box.insert(END, 'Welcome to Python Chat!') self.box.config(state=DISABLED) self.box.pack(expand="yes", fill=BOTH, side=TOP) self.textarea = Text(frame, width=30, height=5) #self.textarea.insert(END, "") self.textarea.bind("<KeyRelease-Return>", self.gettext) #Se metto on press, rimane una newline in piu self.textarea.pack(expand="yes", fill=BOTH, side=TOP) okButton = Button(frame, text="Panic Button", activebackground="red", command=self.sendFile) okButton.pack(expand="no", fill=BOTH, side=TOP) self.usersFrame = Frame(self.parent) self.usersFrame.pack(fill=BOTH, expand=1, side=RIGHT) self.userListbox = Listbox(self.usersFrame, width=3) self.userListbox.pack(fill=BOTH, expand=1) self.updateUsersFrame() def centerWindow(self): w = 600 h = 475 sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - w)/2 y = (sh - h)/2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) def gettext(self, e): #e sta per event, questo e' un listener text = self.textarea.get("1.0", END) # 1.0: row:columa - END-2c rimuove l'ultimo carattere, una newline \r\n if "\n" in text: text = text.replace("\n", "") self.textarea.delete("0.0", END) #NON VA: il problema e' che viene inviato il carattere di newline ma non incluso nell'area a causa della bind mi sa. Devo escluderlo io self.sendToServer(text) def printConversation(self, message): self.box.config(state=NORMAL) self.box.insert(END,"\n" + message) self.lineCounter = self.lineCounter + 2 #m = re.match("\[.*\] From .*\n", self.box.get("0.0", END)) m = re.search("\[.*\].*:", message, re.MULTILINE) if m is not None: #print("MATCH") #print(m.group(0)) #print(str(m.start(0)) + "_" + str(m.end(0))) #print("COUNTER") #print(str(self.lineCounter) + "." + str(m.start(0)+1) + "___" + str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_add("header", str(self.lineCounter) + "." + str(m.start(0)), str(self.lineCounter) + "." + str(m.end(0))) self.box.tag_config("header", font=self.customFontHeader, foreground = "blue") self.box.config(state=DISABLED) #self.box.yview_scroll(10000,"units") self.box.see(END) def sendToServer(self, messageToSend): self.conn.send(messageToSend.encode(encoding='utf_8', errors='strict')) def sendFile(self): #aprire una dialog di quelle predefinite (Sfoglia...) #capire come fare la send di un file sul socket... pass def updateUsersFrame(self): global connectedClients self.userListbox.delete(0, END) self.userListbox.insert(END, "Connected users") for item in connectedClients: self.userListbox.insert(END, item)
class Tkui(base.BaseUI): """ This is a ui class which handles the complete Tk user interface. """ def __init__(self): """ Initializes.""" base.BaseUI.__init__(self) # internal ui queue self._event_queue = queue.Queue() # map of session -> (bold, foreground, background) self._currcolors = {} # ses -> string self._unfinishedcolor = {} self._viewhistory = 0 self._do_i_echo = 1 # holds a map of window names -> window references self._windows = {} # instantiate all the widgets self._tk = Tk() self._tk.geometry("800x600") self.settitle() fnt = tkinter.font.Font(family="FixedSys", size=10) self._entry = CommandEntry(self._tk, self, fg='white', bg='black', insertbackground='yellow', font=fnt, insertwidth='2') self._entry.pack(side='bottom', fill='both') self._topframe = Frame(self._tk) self._topframe.pack(side='top', fill='both', expand=1) self._txt = ScrolledText(self._topframe, fg='white', bg='black', font=fnt, height=20) self._txt.pack(side='bottom', fill='both', expand=1) self._txt.bind("<KeyPress>", self._ignoreThis) self._txtbuffer = ScrolledText(self._topframe, fg='white', bg='black', font=fnt, height=20) self._txtbuffer.bind("<KeyPress-Escape>", self.escape) self._txtbuffer.bind("<KeyPress>", self._ignoreThis) self._entry.focus_set() self._initColorTags() self.dequeue() exported.hook_register("config_change_hook", self.configChangeHandler) exported.hook_register("to_user_hook", self.write) # FIXME - fix this explanation. this is just terrible. tc = config.BoolConfig( "saveinputhighlight", 0, 1, "Allows you to change the behavior of the command entry. When " "saveinputhighlight is off, we discard whatever is on the entry " "line. When it is on, we will retain the contents allowing you " "to press the enter key to do whatever you typed again.") exported.add_config("saveinputhighlight", tc) self._quit = 0 def runui(self): global HELP_TEXT exported.add_help("tkui", HELP_TEXT) exported.write_message("For tk help type \"#help tkui\".") exported.add_command("colorcheck", colorcheck_cmd) # run the tk mainloop here self._tk.mainloop() def wantMainThread(self): # The tkui needs the main thread of execution so we return # a 1 here. return 1 def quit(self): if not self._quit: self._quit = 1 self._topframe.quit() def dequeue(self): qsize = self._event_queue.qsize() if qsize > 10: qsize = 10 for i in range(qsize): ev = self._event_queue.get_nowait() ev.execute(self) self._tk.after(25, self.dequeue) def settitle(self, title=""): """ Sets the title bar to the Lyntin title plus the given string. @param title: the title to set @type title: string """ if title: title = constants.LYNTINTITLE + title else: title = constants.LYNTINTITLE self._event_queue.put(_TitleEvent(self._tk, title)) def removeWindow(self, windowname): """ This removes a NamedWindow from our list of NamedWindows. @param windowname: the name of the window to write to @type windowname: string """ if windowname in self._windows: del self._windows[windowname] def writeWindow(self, windowname, message): """ This writes to the window named "windowname". If the window does not exist, we spin one off. It handles ansi text and messages just like writing to the main window. @param windowname: the name of the window to write to @type windowname: string @param message: the message to write to the window @type message: string or Message instance """ self._event_queue.put(_WriteWindowEvent(windowname, message)) def writeWindow_internal(self, windowname, message): if windowname not in self._windows: self._windows[windowname] = NamedWindow(windowname, self, self._tk) self._windows[windowname].write(message) def _ignoreThis(self, tkevent): """ This catches keypresses from the history buffer.""" # kludge so that ctrl-c doesn't get caught allowing windows # users to copy the buffer.... if tkevent.keycode == 17 or tkevent.keycode == 67: return self._entry.focus() if tkevent.char: # we do this little song and dance so as to pass events # we don't want to deal with to the entry widget essentially # by creating a new event and tossing it in the event list. # it only sort of works--but it's the best code we've got # so far. args = ('event', 'generate', self._entry, "<KeyPress>") args = args + ('-rootx', tkevent.x_root) args = args + ('-rooty', tkevent.y_root) args = args + ('-keycode', tkevent.keycode) args = args + ('-keysym', tkevent.keysym) self._tk.tk.call(args) return "break" def pageUp(self): """ Handles prior (Page-Up) events.""" if self._viewhistory == 0: self._txtbuffer.pack(side='top', fill='both', expand=1) self._viewhistory = 1 self._txtbuffer.delete("1.0", "end") lotofstuff = self._txt.get('1.0', 'end') self._txtbuffer.insert('end', lotofstuff) for t in self._txt.tag_names(): taux = None tst = 0 for e in self._txt.tag_ranges(t): if tst == 0: taux = e tst = 1 else: tst = 0 self._txtbuffer.tag_add(t, str(taux), str(e)) self._txtbuffer.yview('moveto', '1') if os.name != 'posix': self._txtbuffer.yview('scroll', '20', 'units') self._tk.update_idletasks() self._txt.yview('moveto', '1.0') if os.name != 'posix': self._txt.yview('scroll', '220', 'units') else: # yscroll up stuff self._txtbuffer.yview('scroll', '-15', 'units') def pageDown(self): """ Handles next (Page-Down) events.""" if self._viewhistory == 1: # yscroll down stuff self._txtbuffer.yview('scroll', '15', 'units') def escape(self, tkevent): """ Handles escape (Escape) events.""" if self._viewhistory == 1: self._txtbuffer.forget() self._viewhistory = 0 else: self._entry.clearInput() def configChangeHandler(self, args): """ This handles config changes including mudecho. """ name = args["name"] newvalue = args["newvalue"] if name == "mudecho": if newvalue == 1: # echo on self._do_i_echo = 1 self._entry.configure(show='') else: # echo off self._do_i_echo = 0 self._entry.configure(show='*') def _yadjust(self): """Handles y scrolling after text insertion.""" self._txt.yview('moveto', '1') # if os.name != 'posix': self._txt.yview('scroll', '20', 'units') def _clipText(self): """ Scrolls the text buffer up so that the new text written at the bottom of the text buffer can be seen. """ temp = self._txt.index("end") ind = temp.find(".") temp = temp[:ind] if (temp.isdigit() and int(temp) > 800): self._txt.delete("1.0", "100.end") def write(self, args): """ This writes text to the text buffer for viewing by the user. This is overridden from the 'base.BaseUI'. """ self._event_queue.put(_OutputEvent(args)) def write_internal(self, args): mess = args["message"] if type(mess) == bytes: mess = message.Message(mess, message.LTDATA) elif "window" in mess.hints: self.writeWindow_internal(mess.hints["window"], mess) return line = mess.data ses = mess.session if line == '' or self.showTextForSession(ses) == 0: return color, leftover = buffer_write(mess, self._txt, self._currcolors, self._unfinishedcolor) if mess.type == message.MUDDATA: self._unfinishedcolor[ses] = leftover self._currcolors[ses] = color self._clipText() self._yadjust() def convertColor(self, name): """ Tk has this really weird color palatte. So I switched to using color names in most cases and rgb values in cases where I couldn't find a good color name. This method allows me to specify either an rgb or a color name and it converts the color names to rgb. @param name: either an rgb value or a name @type name: string @returns: the rgb color value @rtype: string """ if name.startswith("#"): return name rgb = self._tk._getints( self._tk.tk.call('winfo', 'rgb', self._txt, name)) rgb = "#%02x%02x%02x" % (old_div(rgb[0], 256), old_div( rgb[1], 256), old_div(rgb[2], 256)) print(name, "converted to: ", rgb) return rgb def _initColorTags(self): """ Sets up Tk tags for the text widget (fg/bg/u).""" for ck in list(fg_color_codes.keys()): color = self.convertColor(fg_color_codes[ck]) self._txt.tag_config(ck, foreground=color) self._txtbuffer.tag_config(ck, foreground=color) for ck in list(bg_color_codes.keys()): self._txt.tag_config(ck, background=bg_color_codes[ck]) self._txtbuffer.tag_config(ck, background=bg_color_codes[ck]) self._txt.tag_config("u", underline=1) self._txtbuffer.tag_config("u", underline=1) def colorCheck(self): """ Goes through and displays all the combinations of fg and bg with the text string involved. Purely for debugging purposes. """ fgkeys = ['30', '31', '32', '33', '34', '35', '36', '37'] bgkeys = ['40', '41', '42', '43', '44', '45', '46', '47'] self._txt.insert('end', 'color check:\n') for bg in bgkeys: for fg in fgkeys: self._txt.insert('end', str(fg), (fg, bg)) self._txt.insert('end', str("b" + fg), ("b" + fg, bg)) self._txt.insert('end', '\n') for fg in fgkeys: self._txt.insert('end', str(fg), (fg, "b" + bg)) self._txt.insert('end', str("b" + fg), ("b" + fg, "b" + bg)) self._txt.insert('end', '\n') self._txt.insert('end', '\n') self._txt.insert('end', '\n')
class Editor(Toplevel): @property def text(self): return self.sc_text.get('1.0', END) @text.setter def text(self, value): pos = self.sc_text.yview() self.sc_text.delete('1.0', END) self.sc_text.insert(END, value) self.sc_text.yview_moveto(pos[0]) def __init__(self, master): super().__init__(master) self.index_matches = None self.current_index = None self.search_content = StringVar() self.sc_text = ScrolledText(self, wrap=NONE) self.x_scrollbar_content_text = Scrollbar(self, orient=HORIZONTAL, command=self.sc_text.xview) self.sc_text.configure( xscrollcommand=self.x_scrollbar_content_text.set) self.wrap_text = IntVar() self.wrap_text.set(False) Button(self, text='<-', command=self.click_prev_button).grid(row=0, column=0) self.search_content_entry = Entry(self, textvariable=self.search_content) self.search_content_entry.bind( '<KeyRelease>', lambda event: self.highlight_pattern(event.widget.get())) self.search_content_entry.grid(row=0, column=1, sticky=W + E) Button(self, text='->', command=self.click_next_button).grid(row=0, column=2) Checkbutton(self, text="Wrap Text", variable=self.wrap_text, command=lambda: self.sc_text.config( wrap=NONE if not self.wrap_text.get() else WORD)).grid(row=1, column=0) self.sc_text.grid(row=2, column=0, columnspan=3, sticky=N + S + E + W) self.x_scrollbar_content_text.grid(row=3, column=0, columnspan=3, sticky=W + E) self.columnconfigure(1, weight=1) self.rowconfigure(2, weight=1) self.withdraw() self.protocol('WM_DELETE_WINDOW', lambda t=self: t.withdraw()) def click_next_button(self): if not self.index_matches: return if self.current_index is None: self.current_index = 0 else: self.current_index += 1 self.current_index %= len(self.index_matches) self.sc_text.see(self.index_matches[self.current_index]) def click_prev_button(self): if not self.index_matches: return if self.current_index is None: self.current_index = len(self.index_matches) - 1 else: self.current_index -= 1 self.current_index %= len(self.index_matches) self.sc_text.see(self.index_matches[self.current_index]) def highlight_pattern(self, pattern, start="1.0", end="end"): for t in self.sc_text.tag_names(): self.sc_text.tag_delete(t) if not pattern: return self.index_matches = [] self.current_index = None self.sc_text.tag_config('found', background="green") start = self.sc_text.index(start) end = self.sc_text.index(end) self.sc_text.mark_set("matchStart", start) self.sc_text.mark_set("matchEnd", start) self.sc_text.mark_set("searchLimit", end) count = IntVar() while True: index = self.sc_text.search(pattern, "matchEnd", "searchLimit", count=count) if index == "": break self.sc_text.mark_set("matchStart", index) match_index = "%s+%sc" % (index, count.get()) self.index_matches.append(match_index) self.sc_text.mark_set("matchEnd", match_index) self.sc_text.tag_add('found', "matchStart", "matchEnd")
class myPanel(tkinter.Tk): def __init__(self): tkinter.Tk.__init__(self, 'lsx') self.withdraw() # 先withdraw隐藏再deiconify显示可使setCenter不会导致页面闪烁 self.title('电话簿v1.05 (联系作者:QQ11313213)') # TODO 是否有用 self.keys_var = tkinter.StringVar() self.tex1 = ScrolledText(self) ent1 = tkinter.Entry(self, textvariable=self.keys_var, width=125) ent1.pack(padx=2, pady=2, fill=tkinter.constants.BOTH, side=tkinter.constants.TOP) self.tex1.pack(padx=2, pady=2, fill=tkinter.constants.BOTH, expand=True) self.menu = tkinter.Menu(self, tearoff=0) self.menu.add_command(label='复制', command=self.copyItem) self.menu.add_separator() self.menu.add_command(label='来源') self.menu.add_separator() self.menu.add_command(label='刷新', command=readContacts2) self.menu.add_command(label='前后文', command=self.location) self.menu.add_separator() self.menu.add_command(label='导入文件', command=ImportFiles) self.menu.add_command(label='新增和更改', command=UpdateFile) self.menu0 = tkinter.Menu(self, tearoff=0) self.menu0.add_command(label='刷新', command=readContacts2) self.menu0.add_separator() self.menu0.add_command(label='导入文件', command=ImportFiles) self.menu0.add_command(label='新增和更改', command=UpdateFile) self.menu0.add_separator() submenu = [tkinter.Menu(self, tearoff=0)] self.menu0.add_cascade(label='Designed by Lsx. ', menu=submenu[0]) for key, value in [['Name', 'Li Shixian'], ['Mail', '*****@*****.**'], ['Website', 'github.com/znsoooo/contacts'], ['Wechat', 'Xian_2'], ['Donate', 'xxxx']]: submenu.append(tkinter.Menu(self, tearoff=0)) submenu.append(tkinter.Menu(self, tearoff=0)) submenu[-1].add_command(label=value) submenu[0].add_cascade(label=key, menu=submenu[-1]) self.img_wechat = tkinter.PhotoImage( data=Image.img1) # 没有self会导致显示图片为空白 self.img_donate = tkinter.PhotoImage(data=Image.img2) submenu[8].entryconfig(0, image=self.img_wechat) submenu[10].entryconfig(0, image=self.img_donate) submenu[0].add_separator() submenu[0].add_command(label='All Rights Reserved.', command=bonus) setCenter(self) self.deiconify() ent1.focus() ent1.bind('<KeyRelease>', self.onKeyRelease) self.tex1.bind('<ButtonRelease-3>', self.onRightClick) def select(self, row): self.tex1.mark_set('insert', '%d.0' % row) self.tex1.tag_remove('sel', '0.0', 'end') self.tex1.tag_add('sel', '%d.0' % row, '%d.0' % (row + 1)) def location(self, row=0): if not row: row = self.current_index + 1 self.onKeyRelease(keys='') self.select(row) self.tex1.see('%d.0' % row) def copyItem(self): text = self.tex1.selection_get() self.clipboard_clear() self.clipboard_append(text[:-1]) # 去掉文末换行符 def onRightClick(self, evt=0): self.tex1.focus() # 当焦点在ent1中时 self.current = int(self.tex1.index('current').split('.')[0]) if len(self.index): self.current_index = self.index[self.current - 1] line_last = 0 for line, file in file_list: if line > self.current_index: break else: line_last = line self.menu.entryconfig(2, label='来源: %s (line:%s)' % (file, self.current_index - line_last + 1)) self.menu.entryconfig( 2, command=lambda: os.popen('explorer /select, %s\\%s\\%s' % (os.getcwd(), DATA_FOLDER, file))) self.select(self.current) self.menu.post(evt.x_root, evt.y_root) else: self.menu0.post(evt.x_root, evt.y_root) return self.current def onKeyRelease(self, evt=0, keys=None): if keys is None: keys = self.keys_var.get() keys = keys.lower().split(' ') ss_new = [] self.index = [] for n, s in enumerate(ss): ok = True for key in keys: if key not in s[1]: ok = False if ok: ss_new.append(s[0]) self.index.append(n) # TODO 提出搜索部分到独立的函数 self.tex1.config(state='normal') self.tex1.delete('1.0', 'end') self.tex1.insert('1.0', '\n'.join(ss_new)) self.tex1.config(state='disabled') # 禁止编辑 self.title('电话簿v1.05 (联系作者:QQ11313213) - %s结果' % len(ss_new)) # title更改耗时短可以做到'同时'更改的效果 return ss_new
class Window(): def __init__(self, title, height, width, bg_color, resizable=(False, False)): self.root = tk.Tk() #build te main root #make it more beautiful self.root.title(title) self.root.geometry(f"{width}x{height}+350+150") self.root.config(bg=bg_color) self.root.resizable = (resizable[0], resizable[1]) self.save_auto = tk.BooleanVar() #program it while the buttom is clicked self.root.bind_all("<Control-s>", self.save) self.root.bind_all("<Control-w>", self.make_work) self.root.bind_all("<Control-d>", self.save_as) self.root.bind_all("<Control-n>", self.new) self.root.bind_all("<Control-m>", self.new_win) self.root.bind_all("<Control-o>", self.open) self.root.focus_set() self.root.grab_set() #function of closing window self.root.protocol("WM_DELETE_WINDOW", lambda: self.close_window("root")) #initialization of all objects that i'm gonna use self.default_font = 11 self.word_wrap_choice = tk.BooleanVar(value=True) def run(self): #run function self.draw_menu() self.draw_scrolled_text() self.root.mainloop() def close_window(self, word): #function that apears when we close_window #and asks as wanna we sawe material or not if word == "root": if len(self.st.get("0.0", "1.1")) == 0 or self.name is not None: self.root.destroy() else: choice = messagebox.askyesnocancel( ' action Box', 'Do you wanna save your changes??') if choice is True: self.save_as() elif choice is False: self.root.destroy() elif choice is None: pass return self.st elif word == "win": if len(self.win_st.get("0.0", "1.1")) == 0 or self.name is not None: self.win.destroy() else: choice = messagebox.askyesnocancel( ' action Box', 'Do you wanna save your changes??') if choice: self.save_as() elif choice is False: self.win.destroy() elif choice is None: pass return self.win_st def make_work(self, *args, **kwargs): #function that gets the selected text and #uses another function to aneble our labels ('cut', 'copy', 'paste') self.get_selected = self.st.get(tk.SEL_FIRST, tk.SEL_LAST) self.work_with_selected_text("root") return self.get_selected def make_work_new_win(self, *args, **kwargs): #the sae one as the previoys but it works with new window self.get_selected = self.win_st.get(tk.SEL_FIRST, tk.SEL_LAST) self.work_with_selected_text("win") return self.get_selected #function that open the folders and save our information #can use just clicking 'Ctrl+d' def save_as(self, *args, **kwargs): try: #open main terminal to save our results self.name = fd.asksaveasfilename(filetypes=(("Text file", "*.txt"), ("Python files", "*.py"))) #when we chosed file if opens it with open(self.name, "w") as f: f.write( self.st.get("0.0", tk.END) ) # and write there information that there is in this file except FileNotFoundError: pass return self.name #function that save our information but nou open folders when it was used already #can use just clicking 'Ctrl+s' def save(self, *args, **kwargs): try: if self.name is None: #open main terminal to save our results self.name = fd.asksaveasfilename(filetypes=(("Text file", "*.txt"), ("Python files", "*.py"))) #when we chosed file if opens it with open(self.name, "w") as f: f.write( self.st.get("0.0", tk.END) ) # write there information that there is in this file except FileNotFoundError: pass return self.name #open folders to open file that we're looking for def open(self, name_type, *args, **kwargs): name = fd.askopenfilename() if name_type == "root": #main operation if name: with open(name, "r") as f: #open main teminal self.st.delete("0.0", tk.END) self.st.insert( tk.END, f.read()) #insert the text that we have chosen elif name_type == "win": # the same but only for new_win if name: with open(name, "r") as f: self.win_st.delete("0.0", tk.END) self.win_st.insert(tk.END, f.read()) def work_with_selected_text( self, name_type): #function that nake our labelf feel NORMAL if name_type == "root": if len(self.get_selected ) != 0: #if len of selected text is not zero self.new_menu2.entryconfig( 0, state=tk.NORMAL) #anebling our labels self.new_menu2.entryconfig(1, state=tk.NORMAL) self.new_menu2.entryconfig(2, state=tk.NORMAL) self.new_menu2.entryconfig(3, state=tk.NORMAL) self.new_menu2.entryconfig(4, state=tk.NORMAL) elif name_type == "win": if len(self.get_selected ) != 0: #if len of selected text is not zero self.new_menu_new_win.entryconfig( 0, state=tk.NORMAL) #anebling our labels self.new_menu_new_win.entryconfig(1, state=tk.NORMAL) self.new_menu_new_win.entryconfig(2, state=tk.NORMAL) self.new_menu_new_win.entryconfig(3, state=tk.NORMAL) #main function that creates new window in our Noetepad def new_win(self, *args, **kwargs): #asks if we wanna save our changes choice = messagebox.askyesnocancel('Yes or No or Cancel action Box', 'Do you wanna save your changes??') if choice is False: #if answer is No self.win = tk.Toplevel(self.root) #we create new win #make it looks a bit attractive self.win.title("Untitled") self.win.geometry(f"{900}x{520}+500+150") self.win.config(bg="white") #creating scrollText to meke it like a real Notepadd self.win_st = ScrolledText(self.win, selectforeground="white", fg="black", font=("Consolas", 11, "bold"), wrap="word", width=200, height=100) self.win_st.pack() #pack it in our screen #create a status bur into our screen menu_bar = tk.Menu(self.win) self.win.bind_all("<Control-w>", self.make_work_new_win ) #to uneble our ('cut','copy','paste') labels #creating adition little-memu on our status bar new_menu = tk.Menu(menu_bar, tearoff=0) self.new_menu_new_win = tk.Menu( menu_bar, tearoff=0 ) #we created it as self_object because we're gonna use into #out of this function new_Format = tk.Menu(menu_bar, tearoff=0) new_font = tk.Menu(menu_bar, tearoff=0) new_view = tk.Menu(menu_bar, tearoff=0) new_zoom = tk.Menu(menu_bar, tearoff=0) new_help = tk.Menu(menu_bar, tearoff=0) #add kabels on the each little-menu new_menu.add_command(label="New Ctrl+N", ) new_menu.add_command(label="New Window Ctrl+M", command=self.new_win) new_menu.add_command( label="Open Ctrl+O", command=lambda: self.open("win")) #add function new_menu.add_separator() #add separator for this little-menu new_menu.add_command(label="Save Ctrl + s") new_menu.add_cascade(label="Save as Ctrl + d") new_menu.add_separator() new_menu.add_command(label="exit", command=lambda: self.close_window("win")) #adding special labels self.new_menu_new_win.add_command( label="Cut", command=lambda: self.get_cut("win")) self.new_menu_new_win.add_command( label="Copy", command=lambda: self.get_copy("win")) self.new_menu_new_win.add_command( label="Paste", command=lambda: self.get_paste("win")) self.new_menu_new_win.add_command( label="Delete", command=lambda: self.get_delete("win")) self.new_menu_new_win.add_separator() self.new_menu_new_win.add_command( label="Select All", command=lambda: self.get_select_text("win")) self.new_menu_new_win.add_command( label="Time/Data", command=lambda: self.get_current_time("win")) self.new_menu_new_win.entryconfig( 0, state=tk.DISABLED) #make all of this labels disabled self.new_menu_new_win.entryconfig( 1, state=tk.DISABLED) #make all of this labels disabled self.new_menu_new_win.entryconfig( 2, state=tk.DISABLED) #make all of this labels disabled self.new_menu_new_win.entryconfig( 3, state=tk.DISABLED) #make all of this labels disabled #add checkbutton list of fonts if we wanna change this one new_Format.add_checkbutton(label="Word wrap", variable=self.word_wrap_choice, onvalue=True, offvalue=False, command=self.word_wrap_funk) new_font.add_command( label="Arial", command=lambda: self.make_font("Arial", "win")) new_font.add_command( label="Consolas", command=lambda: self.make_font("Consolas", "win")) new_font.add_command( label="Calibri", command=lambda: self.make_font("Calibri", "win")) new_font.add_command( label="Modern", command=lambda: self.make_font("Modern", "win")) #add zoom labels with commands new_zoom.add_command( label="Zoom in", command=lambda: self.zoom_in_command("zoom in", "win")) new_zoom.add_command( label="Zoom out", command=lambda: self.zoom_in_command("zoom out", "win")) new_zoom.add_command( label="Restore to default settings", command=lambda: self.zoom_in_command("default", "win")) #add this all little-menu to our main menu menu_bar.add_cascade(label="File", menu=new_menu) menu_bar.add_cascade(label="Edit", menu=self.new_menu_new_win) menu_bar.add_cascade(label="Format", menu=new_Format) new_Format.add_cascade(label="Font...", menu=new_font) menu_bar.add_cascade(label="View", menu=new_view) menu_bar.add_cascade(label="Help", menu=new_help) new_view.add_cascade(label="Zoom", menu=new_zoom) self.win.configure(menu=menu_bar) #add our main menu to main root elif choice is True: #in choice is true save_as (wanna save our changes) self.save_as() elif choice is None: #if choice is None, means we cliked on 'Cancel' pass #dont do anything self.win.protocol( "WM_DELETE_WINDOW", lambda: self.close_window("win")) #funk closing new_window return self.win_st, self.win, self.new_menu_new_win #return all elements we will use later def new(self, *args, **kwargs): #new_funk just clean the whole field self.st.delete("0.0", tk.END) def draw_scrolled_text( self): #funk that draw scrolled text on our main root self.st = ScrolledText(self.root, selectforeground="white", fg="black", font=("Consolas", 11, "bold"), width=200, height=100) #all the parameters self.st.pack() return self.st def word_wrap_funk( self): #if we wanna end our line with word we use this funk if self.word_wrap_choice: #checkbuttom that has two types ("true", "false") self.st.configure( wrap="word") #if true we change configuration of dcrilled text def make_font(self, chosenfont, place): #change size of our font if place == "root": #on main root self.st.configure(font=(chosenfont, 11)) elif place == "win": #on new window self.win_st.configure(font=(chosenfont, 11)) def zoom_in_command(self, type_size, place): #funk zooms out font #for main root if type_size == "zoom in" and place == "root": #if zoom_in font getting bigger self.default_font += 2 self.st.configure(font=("Arial", self.default_font)) elif type_size == "zoom out" and place == "root": #if zoom_our font getting smaller self.default_font -= 2 self.st.configure(font=("Arial", self.default_font)) elif type_size == "default" and place == "root": #if default returns start font size self.st.configure(font=("Arial", 11)) #for new window elif type_size == "zoom in" and place == "win": #if zoom_in font getting bigger self.default_font += 2 self.win_st.configure(font=("Arial", self.default_font)) elif type_size == "zoom out" and place == "win": #if zoom_our font getting smaller self.default_font -= 2 self.win_st.configure(font=("Arial", self.default_font)) elif type_size == "default" and place == "win": #if default returns start font size self.win_st.configure(font=("Arial", 11)) return self.default_font def get_cut(self, name_type): #funk that cut selected text if name_type == "root": #for root try: self.storage_for_copy_cut_paste = self.st.get( tk.SEL_FIRST, tk.SEL_LAST) #get selected text self.st.delete("sel.first", "sel.last") #delete selected except Exception: pass return self.storage_for_copy_cut_paste elif name_type == "win": #for new window try: self.storage_for_copy_cut_paste = self.win_st.get( tk.SEL_FIRST, tk.SEL_LAST) #get selected text self.win_st.delete("sel.first", "sel.last") #delete selected except Exception: pass return self.storage_for_copy_cut_paste def get_copy(self, name_type): #funk that copy selected text if name_type == "root": #for root try: self.st.clipboard_clear() self.storage_for_copy_cut_paste = self.st.get( tk.SEL_FIRST, tk.SEL_LAST) #get selected text text = self.storage_for_copy_cut_paste self.st.clipboard_append(text) except Exception: pass return self.storage_for_copy_cut_paste elif name_type == "win": #for new window try: self.win_st.clipboard_clear() self.storage_for_copy_cut_paste = self.win_st.get( tk.SEL_FIRST, tk.SEL_LAST) #get selected text text = self.storage_for_copy_cut_paste self.win_st.clipboard_append(text) except Exception: pass return self.storage_for_copy_cut_paste def get_paste(self, name_type): #funk that paste selected text if name_type == "root": #for root try: text = self.storage_for_copy_cut_paste #get text that has already been set self.st.insert('insert', text) #add it to scrolled text except Exception: pass return self.storage_for_copy_cut_paste elif name_type == "win": #for root try: text = self.storage_for_copy_cut_paste #get text that has already been set self.win_st.insert('insert', text) #add it to scrolled text except Exception: pass return self.storage_for_copy_cut_paste def get_delete(self, name_type): #delete whole selected text if name_type == "root": #for root try: self.st.delete("sel.first", "sel.last") except Exception: pass elif name_type == "win": #for new win try: self.win_st.delete("sel.first", "sel.last") except Exception: pass def about_notepad_command(self): #func thet creates new field to see the #information of this notepad new_win = tk.Toplevel(self.root, width=500, height=500) new_win.geometry("500x400+500+200") new_win.title("About") new_st = ScrolledText(new_win) new_st.insert(tk.END, text) new_st.pack() def get_select_text(self, name_type): if name_type == "root": self.st.tag_add("sel", "1.0", "end") #get selected from root elif name_type == "win": self.win_st.tag_add("sel", "1.0", "end") #get selected from new win def find_word(self): self.win_new = tk.Toplevel(self.root) tk.Label(self.win_new, text="What ti find").grid(row=0, column=0) self.what_to_find = tk.Entry(self.win_new) self.what_to_find.grid(row=0, column=1, columnspan=3) button = tk.Button(self.win_new, text="Find", command=self.find_word_main) button.grid(row=1, column=1) return self.what_to_find, self.new_win def find_word_main(self): position_of_word = self.st.get("0.0", "end").find(self.what_to_find.get()) pos = 1 while position_of_word > len(self.st.get(f"{pos}.0", f"{pos}.100")): position_of_word -= len(self.st.get(f"{pos}.0", f"{pos}.100")) pos += 1 else: position_of_word = self.st.get(f"{pos}.0", "end").find(self.what_to_find.get()) self.st.tag_add( "sel", f"{pos}.{position_of_word}", f"{pos}.{position_of_word + len(self.what_to_find.get())}") self.win_new.destroy() def get_current_time(self, name_type): #show current time d = datetime.today() if name_type == "root": self.st.insert("end", d.strftime("%d-%B-%Y %H:%M:%S")) elif name_type == "win": self.win_st.insert("end", d.strftime("%d-%B-%Y %H:%M:%S")) def new_delete_whole_text(self): #delete everything self.st.delete("1.0", "end") def draw_menu(self): #creating tme main menu on root menu_bar = tk.Menu(self.root) #main menu #creating little menues new_menu = tk.Menu(menu_bar, tearoff=0) self.new_menu2 = tk.Menu( menu_bar, tearoff=0) #we use iy out of this function to make #label in there state Normal new_Format = tk.Menu(menu_bar, tearoff=0) new_font = tk.Menu(menu_bar, tearoff=0) new_view = tk.Menu(menu_bar, tearoff=0) new_zoom = tk.Menu(menu_bar, tearoff=0) new_help = tk.Menu(menu_bar, tearoff=0) #adding label and their command to each little menu bar new_menu.add_command(label="New Ctrl+N", command=self.new_delete_whole_text) new_menu.add_command(label="New Window Ctrl+M", command=self.new_win) new_menu.add_command(label="Open Ctrl+O", command=lambda: self.open("root")) new_menu.add_separator() # add separator new_menu.add_command(label="Save Ctrl + s", command=self.save) new_menu.add_cascade(label="Save as Ctrl + d", command=self.save_as) new_menu.add_separator() new_menu.add_command(label="exit", command=lambda: self.close_window("root")) self.new_menu2.add_command(label="Cut", command=lambda: self.get_cut("root")) self.new_menu2.add_command(label="Copy", command=lambda: self.get_copy("root")) self.new_menu2.add_command(label="Paste", command=lambda: self.get_paste("root")) self.new_menu2.add_command(label="Delete", command=lambda: self.get_delete("root")) self.new_menu2.add_command(label="Find", command=self.find_word) self.new_menu2.add_separator() self.new_menu2.add_command( label="Select All", command=lambda: self.get_select_text("root")) self.new_menu2.add_command( label="Time/Data", command=lambda: self.get_current_time("root")) #making labels disabled self.new_menu2.entryconfig(0, state=tk.DISABLED) self.new_menu2.entryconfig(1, state=tk.DISABLED) self.new_menu2.entryconfig(2, state=tk.DISABLED) self.new_menu2.entryconfig(3, state=tk.DISABLED) self.new_menu2.entryconfig(4, state=tk.DISABLED) #add checkbutton to wrap funk new_Format.add_checkbutton(label="Word wrap", variable=self.word_wrap_choice, onvalue=True, offvalue=False, command=self.word_wrap_funk) # for canging our font new_font.add_command(label="Arial", command=lambda: self.make_font("Arial", "root")) new_font.add_command( label="Consolas", command=lambda: self.make_font("Consolas", "root")) new_font.add_command(label="Calibri", command=lambda: self.make_font("Calibri", "root")) new_font.add_command(label="Modern", command=lambda: self.make_font("Modern", "root")) #zoom funk new_zoom.add_command( label="Zoom in", command=lambda: self.zoom_in_command("zoom in", "root")) new_zoom.add_command( label="Zoom out", command=lambda: self.zoom_in_command("zoom out", "root")) new_zoom.add_command( label="Restore to default settings", command=lambda: self.zoom_in_command("default", "root")) new_help.add_command(label="About Notepad", command=self.about_notepad_command) #add little menus to main menu_bar menu_bar.add_cascade(label="File", menu=new_menu) menu_bar.add_cascade(label="Edit", menu=self.new_menu2) menu_bar.add_cascade(label="Format", menu=new_Format) new_Format.add_cascade(label="Font...", menu=new_font) menu_bar.add_cascade(label="View", menu=new_view) new_view.add_cascade(label="Zoom", menu=new_zoom) menu_bar.add_cascade(label="Help", menu=new_help) #add main menu to root self.root.configure(menu=menu_bar) return self.new_menu2