class GuiGenerateCount(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.pack() #step increment len self._stepLenFrm = Frame(self); self._stepLenFrm.pack() self._stepLenLbl = Label(self._stepLenFrm, text="Step Len: "); self._stepLenLbl.pack(side=LEFT) self._stepLenSpin = Spinbox(self._stepLenFrm, from_=0, to=1000); self._stepLenSpin.pack(side=LEFT) #start value self._startFrm = Frame(self); self._startFrm.pack() self._startLbl = Label(self._startFrm, text="Start Value: "); self._startLbl.pack(side=LEFT) self._startTxt = Entry(self._startFrm); self._startTxt.pack(side=LEFT) self._startTxt.insert(0, "0") def getSettings(self): return { "StepLen": self._stepLenSpin.get(), "StartValue": self._startTxt.get() } def getName(self): return "Counter" def getGeneratorFunction(self): return generateCounter
class RegisterPage(Frame): def __init__(self, master, blockchain=None, client=None): Frame.__init__(self, master) self.blockchain = blockchain self.client = client # user id id_frame = Frame(self) id_frame.pack() id_label = Label(id_frame, text='User ID') id_label.pack(side=LEFT) self.id_entry = Entry(id_frame, bd=5) self.id_entry.pack(side=LEFT) #first name fname_frame = Frame(self) fname_frame.pack() fname_label = Label(fname_frame, text='First Name') fname_label.pack(side=LEFT) self.fname_entry = Entry(fname_frame, bd=5) self.fname_entry.pack(side=LEFT) #last name lname_frame = Frame(self) lname_frame.pack() lname_label = Label(lname_frame, text='Last Name') lname_label.pack(side=LEFT) self.lname_entry = Entry(lname_frame, bd=5) self.lname_entry.pack(side=LEFT) # department departments = [(1, 'cse'), (2, 'arch')] department_frame = Frame(self) department_frame.pack() department_label = Label(department_frame, text='Department') department_label.pack(side=LEFT) self.department_list = Listbox(department_frame, selectmode=SINGLE, selectbackground='Blue', height=len(departments)) for index, dep in departments: self.department_list.insert(index, dep) self.department_list.pack(side=LEFT) #section section_frame = Frame(self) section_frame.pack() section_label = Label(section_frame, text='section') section_label.pack(side=LEFT) self.section_spinbox = Spinbox(section_frame, from_=1, to=3) self.section_spinbox.pack(side=LEFT) # Year year_frame = Frame(self) year_frame.pack() year_label = Label(year_frame, text='Year') year_label.pack() self.year_var = IntVar() years = [('2007', 2007), ('2008', 2008), ('2009', 2009), ('2010', 2010), ('2011', 2011)] for text, value in years: rb = Radiobutton(year_frame, text=text, variable=self.year_var, value=value, command=self.sel) rb.pack(anchor=W) self.label = Label(year_frame) self.label.pack() # password password_frame = Frame(self) password_frame.pack() password_label = Label(password_frame, text='Password') password_label.pack(side=LEFT) self.password_entry = Entry(password_frame, bd=5) self.password_entry.pack(side=LEFT) #Re-password repassword_frame = Frame(self) repassword_frame.pack() repassword_label = Label(repassword_frame, text='Re-password') repassword_label.pack(side=LEFT) self.repassword_entry = Entry(repassword_frame, bd=5) self.repassword_entry.pack(side=LEFT) #register button w = tkinter.Button(self, bg='Green', text='Register', command=self.register) w.pack() def sel(self): selection = 'You selected the year ' + str(self.year_var.get()) self.label.config(text=selection) def register(self): user = User() selected = self.department_list.curselection() if len(selected) < 1: tkinter.messagebox.showerror('Error', 'Department not selected !!!') else: department = self.department_list.get( self.department_list.curselection()) id_ = self.id_entry.get() fname = self.fname_entry.get() lname = self.lname_entry.get() print(str(department)) section = int(self.section_spinbox.get()) print(section) print(type(section)) year = int(self.year_var.get()) print(year) print(type(year)) password = self.password_entry.get() repassword = self.repassword_entry.get() if password == repassword: student = Student(fname, lname, department, section, year, id_, password=password) if user.student_register(student): tkinter.messagebox.showinfo('Register', 'you are Registerd.') else: tkinter.messagebox.showerror('Error', 'Registration failed.') else: tkinter.messagebox.showerror('Error', 'password is incorrect')
class OOP(): def __init__(self): # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") # Disable resizing the window self.win.resizable(0, 0) # Create a Queue self.guiQueue = Queue() self.createWidgets() # populate Tab 2 Entries self.defaultFileEntries() # create MySQL instance self.mySQL = MySQL() def defaultFileEntries(self): self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, 'Z:\\') # bogus path self.fileEntry.config(state='readonly') self.netwEntry.delete(0, tk.END) self.netwEntry.insert(0, 'Z:\\Backup') # bogus path # Combobox callback def _combo(self, val=0): value = self.combo.get() self.scr.insert(tk.INSERT, value + '\n') # Spinbox callback def _spin(self): value = self.spin.get() self.scr.insert(tk.INSERT, value + '\n') # Checkbox callback def checkCallback(self, *ignoredArgs): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton callback function def radCall(self): radSel = self.radVar.get() if radSel == 0: self.mySQL2.configure(text=WIDGET_LABEL + 'in Blue') elif radSel == 1: self.mySQL2.configure(text=WIDGET_LABEL + 'in Gold') elif radSel == 2: self.mySQL2.configure(text=WIDGET_LABEL + 'in Red') # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() def methodInAThread(self, numOfLoops=10): for idx in range(numOfLoops): sleep(1) self.scr.insert(tk.INSERT, str(idx) + '\n') sleep(1) print('methodInAThread():', self.runT.isAlive()) # Running methods in Threads def createThread(self, num): self.runT = Thread(target=self.methodInAThread, args=[num]) self.runT.setDaemon(True) self.runT.start() print(self.runT) print('createThread():', self.runT.isAlive()) # textBoxes are the Consumers of Queue data writeT = Thread(target=self.useQueues, daemon=True) writeT.start() # Create Queue instance def useQueues(self): # Now using a class member Queue while True: qItem = self.guiQueue.get() print(qItem) self.scr.insert(tk.INSERT, qItem + '\n') # Button callback def insertQuote(self): title = self.bookTitle.get() page = self.pageNumber.get() quote = self.quote.get(1.0, tk.END) print(title) print(quote) self.mySQL.insertBooks(title, page, quote) # Button callback def getQuote(self): allBooks = self.mySQL.showBooks() print(allBooks) self.quote.insert(tk.INSERT, allBooks) # Button callback def modifyQuote(self): raise NotImplementedError( "This still needs to be implemented for the SQL command.") ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='MySQL') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Widgets') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.mySQL = ttk.LabelFrame(tab1, text=' Python Database ') self.mySQL.grid(column=0, row=0, padx=8, pady=4) # Creating a Label ttk.Label(self.mySQL, text="Book Title:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget book = tk.StringVar() self.bookTitle = ttk.Entry(self.mySQL, width=34, textvariable=book) self.bookTitle.grid(column=0, row=1, sticky='W') # Adding a Textbox Entry widget book1 = tk.StringVar() self.bookTitle1 = ttk.Entry(self.mySQL, width=34, textvariable=book1) self.bookTitle1.grid(column=0, row=2, sticky='W') # Adding a Textbox Entry widget book2 = tk.StringVar() self.bookTitle2 = ttk.Entry(self.mySQL, width=34, textvariable=book2) self.bookTitle2.grid(column=0, row=3, sticky='W') # Creating a Label ttk.Label(self.mySQL, text="Page:").grid(column=1, row=0, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber.grid(column=1, row=1, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber1 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber1.grid(column=1, row=2, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber2 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber2.grid(column=1, row=3, sticky='W') # Adding a Button self.action = ttk.Button(self.mySQL, text="Insert Quote", command=self.insertQuote) self.action.grid(column=2, row=1) # Adding a Button self.action1 = ttk.Button(self.mySQL, text="Get Quotes", command=self.getQuote) self.action1.grid(column=2, row=2) # Adding a Button self.action2 = ttk.Button(self.mySQL, text="Mody Quote", command=self.modifyQuote) self.action2.grid(column=2, row=3) # Add some space around each widget for child in self.mySQL.winfo_children(): child.grid_configure(padx=2, pady=4) quoteFrame = ttk.LabelFrame(tab1, text=' Book Quotation ') quoteFrame.grid(column=0, row=1, padx=8, pady=4) # Using a scrolled Text control quoteW = 40 quoteH = 6 self.quote = scrolledtext.ScrolledText(quoteFrame, width=quoteW, height=quoteH, wrap=tk.WORD) self.quote.grid(column=0, row=8, sticky='WE', columnspan=3) # Add some space around each widget for child in quoteFrame.winfo_children(): child.grid_configure(padx=2, pady=4) #====================================================================================================== # Tab Control 2 #====================================================================================================== # We are creating a container frame to hold all other widgets -- Tab2 self.mySQL2 = ttk.LabelFrame(tab2, text=WIDGET_LABEL) self.mySQL2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons self.chVarDis = tk.IntVar() self.check1 = tk.Checkbutton(self.mySQL2, text="Disabled", variable=self.chVarDis, state='disabled') self.check1.select() self.check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.mySQL2, text="UnChecked", variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.mySQL2, text="Toggle", variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace( 'w', lambda unused0, unused1, unused2: self.checkCallback()) self.chVarEn.trace( 'w', lambda unused0, unused1, unused2: self.checkCallback()) # Radiobutton list colors = ["Blue", "Gold", "Red"] self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): curRad = 'rad' + str(col) curRad = tk.Radiobutton(self.mySQL2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips ToolTip(curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.mySQL2, text=' Labels within a Frame ') labelsFrame.grid(column=0, row=7, pady=6) # Place labels into the container element - vertically ttk.Label(labelsFrame, text="Choose a number:").grid(column=0, row=0) ttk.Label(labelsFrame, text="Label 2").grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=6, pady=1) number = tk.StringVar() self.combo = ttk.Combobox(self.mySQL2, width=12, textvariable=number) self.combo['values'] = (1, 2, 4, 42, 100) self.combo.grid(column=1, row=7, sticky=tk.W) self.combo.current(0) self.combo.bind('<<ComboboxSelected>>', self._combo) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.mySQL2, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin) self.spin.grid(column=2, row=7, sticky='W,', padx=6, pady=1) # Using a scrolled Text control scrolW = 40 scrolH = 1 self.scr = scrolledtext.ScrolledText(self.mySQL2, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=8, sticky='WE', columnspan=3) # Create Manage Files Frame ------------------------------------------------ mngFilesFrame = ttk.LabelFrame(tab2, text=' Manage Files: ') mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print(fName) self.fileEntry.config(state='enabled') self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) if len(fName) > self.entryLen: self.fileEntry.config(width=len(fName) + 3) # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text="Browse to File...", command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) #----------------------------------------------------- file = tk.StringVar() self.entryLen = scrolW - 4 self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.grid(column=1, row=0, sticky=tk.W) #----------------------------------------------------- logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() file = src.split('/')[-1] dst = self.netwEntry.get() + '\\' + file try: shutil.copy(src, dst) mBox.showinfo('Copy File to Network', 'Succes: File copied.') except FileNotFoundError as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as ex: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex)) cb = ttk.Button(mngFilesFrame, text="Copy File To : ", command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) # Creating a Menu Bar ========================================================== menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label="New") fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self._quit) menuBar.add_cascade(label="File", menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About") menuBar.add_cascade(label="Help", menu=helpMenu) # Change the main windows icon self.win.iconbitmap('pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() # Place cursor into name Entry self.bookTitle.focus() # Add a Tooltip to the Spinbox ToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets ToolTip(self.bookTitle, 'This is an Entry control.') ToolTip(self.action, 'This is a Button control.') ToolTip(self.scr, 'This is a ScrolledText control.')
class App: def __init__(self): self.window = tk.Tk() self.window.title("Cripto Escitala") self.window.geometry('430x410') self.window.config(bg="#FFFFFF") self.escitala = Escitala() frameHead = Frame(self.window) lbl_method = tk.Label(frameHead, text='Metodo') lbl_method.grid(column=0, row=0, sticky='W', padx=5) lbl_n_col = tk.Label(frameHead, text='Nro Columnas') lbl_n_col.grid(column=2, row=0, sticky='W', padx=10) lbl_ord_col = tk.Label(frameHead, text='Orden Col: ejm {1,3,2}') lbl_ord_col.grid(column=3, row=0, sticky='W', padx=5) frameHead.grid(column=0, row=0) self.frame = Frame(self.window) self.combo = Combobox(self.frame) self.combo['values'] = ("Encriptar", "Desencriptar") self.combo.grid(column=0, row=0, sticky='W', padx=10) self.spin = Spinbox(self.frame, from_=2, to=500, width=5) self.spin.grid(column=1, row=0, sticky='W', padx=10) self.input_ord_col = Entry(self.frame) self.input_ord_col.grid(column=2, row=0, sticky='W', padx=10) buton = tk.Button(self.frame, text='Start', command=self.clicked) buton.grid(column=3, row=0, sticky='W', padx=10) self.frame.grid(column=0, row=1) lbl_txt_init = tk.Label(self.window, text='Input') lbl_txt_init.grid(column=0, row=3, sticky='W', padx=10) self.scroll_txt_init = tk.scrolledtext.ScrolledText(self.window, width=50, height=10) self.scroll_txt_init.grid(column=0, row=4, sticky='W', padx=10) lbl_txt_end = tk.Label(self.window, text='Output') lbl_txt_end.grid(column=0, row=5, sticky='W', padx=10) self.scroll_txt_end = scrolledtext.ScrolledText(self.window, width=50, height=10) self.scroll_txt_end.grid(column=0, row=6, sticky='W', padx=10) self.window.mainloop() def clicked(self): # Clear buffer f self.scroll_txt_end.delete(0.0, tk.END) indices = self.convertir_indices(self.input_ord_col.get()) n_col = int(self.spin.get()) self.verificar_ind_col(indices, n_col) typeAction = self.combo.get() textInput = self.scroll_txt_init.get( "0.0", tk.END)[:-1] # Eliminamos el ultimo caracter '\n' if textInput == "": messagebox.showerror( 'Mensaje Error', 'Input vacio, Ingrese el texto a encriptar/desencriptar') if typeAction == "": messagebox.showerror('Mensaje Error', 'Seleccione el metodo') elif typeAction == "Encriptar": textOutput = self.escitala.encriptar_con_orden( textInput, n_col, indices) else: textOutput = self.escitala.desencriptar_con_orden( textInput, n_col, indices) # Put new string into of stroll self.scroll_txt_end.insert(tk.INSERT, textOutput) def convertir_indices(self, text_indices): try: indices = text_indices[text_indices.index('{') + 1:text_indices.index('}')] indices = [int(l) - 1 for l in indices.split(',')] return indices except: messagebox.showerror('Mensaje Error', 'Error al ingresar el orden de las columnas') def verificar_ind_col(self, indices, n_col): if (n_col != len(indices)): messagebox.showerror( 'Mensaje Error', 'Error en la cantidad de los ordenes de las columnas') for i in range(n_col): if (not (i in indices)): messagebox.showerror( 'Mesaje Error', f'Error, el orden {i+1} no se encuentra en los ordenes de las columnas' )
class OOP(): def __init__(self): # Initializer method # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") # Create a Queue self.gui_queue = Queue() self.create_widgets() self.defaultFileEntries() # Start TCP/IP server in its own thread svr_thread = Thread(target=start_server, daemon=True) svr_thread.start() def defaultFileEntries(self): self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fDir) if len(fDir) > self.entryLen: self.fileEntry.config(width=35) # limit width to adjust GUI self.fileEntry.config(state='readonly') self.netwEntry.delete(0, tk.END) self.netwEntry.insert(0, netDir) if len(netDir) > self.entryLen: self.netwEntry.config(width=35) # limit width to adjust GUI # Create Queue instance def use_queues(self, loops=5): # Now using a class member Queue while True: q_item = self.gui_queue.get() print(q_item) self.scrol.insert(tk.INSERT, q_item + '\n') def method_in_a_thread(self, num_of_loops=10): for idx in range(num_of_loops): sleep(1) self.scrol.insert(tk.INSERT, str(idx) + '\n') # Running methods in Threads def create_thread(self, num=1): self.run_thread = Thread(target=self.method_in_a_thread, args=[num]) self.run_thread.setDaemon(True) self.run_thread.start() # start queue in its own thread write_thread = Thread(target=self.use_queues, args=[num], daemon=True) write_thread.start() # Button callback def click_me(self): self.action.configure(text='Hello ' + self.name.get()) bq.write_to_scrol(self) sleep(2) html_data = url.get_html() print(html_data) try: self.scrol.insert(tk.INSERT, html_data) except Exception as ex: print(ex) # Spinbox callback def _spin(self): value = self.spin.get() self.scrol.insert(tk.INSERT, value + '\n') # GUI Callback def checkCallback(self, *ignored_args): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton Callback def radCall(self): radSel = self.radVar.get() if radSel == 0: self.mighty2.configure(text='Blue') elif radSel == 1: self.mighty2.configure(text='Gold') elif radSel == 2: self.mighty2.configure(text='Red') # update progressbar in callback loop def run_progressbar(self): self.progress_bar["maximum"] = 100 for i in range(101): sleep(0.05) self.progress_bar["value"] = i # increment progressbar self.progress_bar.update() # have to call update() in loop self.progress_bar["value"] = 0 # reset/clear progressbar def start_progressbar(self): self.progress_bar.start() def stop_progressbar(self): self.progress_bar.stop() def progressbar_stop_after(self, wait_ms=1000): self.win.after(wait_ms, self.progress_bar.stop) def usingGlobal(self): global GLOBAL_CONST GLOBAL_CONST = 777 # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() ##################################################################################### def create_widgets(self): tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='Tab 1') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Tab 2') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # LabelFrame using tab1 as the parent mighty = ttk.LabelFrame(tab1, text=' Mighty Python ') mighty.grid(column=0, row=0, padx=8, pady=4) # Modify adding a Label using mighty as the parent instead of win a_label = ttk.Label(mighty, text="Enter a name:") a_label.grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget self.name = tk.StringVar() # self.name_entered = ttk.Entry(mighty, width=24, textvariable=self.name) self.name_entered = ttk.Entry(mighty, width=16, textvariable=self.name) self.name_entered.grid(column=0, row=1, sticky='W') self.name_entered.delete(0, tk.END) self.name_entered.insert(0, '< default name >') # Adding a Button self.action = ttk.Button(mighty, text="Click Me!", command=self.click_me) self.action.grid(column=2, row=1) ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) number = tk.StringVar() self.number_chosen = ttk.Combobox(mighty, width=14, textvariable=number, state='readonly') self.number_chosen['values'] = (1, 2, 4, 42, 100) self.number_chosen.grid(column=1, row=1) self.number_chosen.current(0) # Adding a Spinbox widget self.spin = Spinbox(mighty, values=(1, 2, 4, 42, 100), width=5, bd=9, command=self._spin) # using range self.spin.grid(column=0, row=2, sticky='W') # align left # Using a scrolled Text control scrol_w = 38 scrol_h = 10 # increase sizes self.scrol = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) self.scrol.grid(column=0, row=3, sticky='WE', columnspan=3) for child in mighty.winfo_children( ): # add spacing to align widgets within tabs child.grid_configure(padx=4, pady=2) #===================================================================================== # Tab Control 2 ---------------------------------------------------------------------- self.mighty2 = ttk.LabelFrame(tab2, text=' The Snake ') self.mighty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(self.mighty2, text="Disabled", variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=0, sticky=tk.W) chVarUn = tk.IntVar() check2 = tk.Checkbutton(self.mighty2, text="UnChecked", variable=chVarUn) check2.deselect() check2.grid(column=1, row=0, sticky=tk.W) chVarEn = tk.IntVar() check3 = tk.Checkbutton(self.mighty2, text="Enabled", variable=chVarEn) check3.deselect() check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons chVarUn.trace('w', lambda unused0, unused1, unused2: self.checkCallback()) chVarEn.trace('w', lambda unused0, unused1, unused2: self.checkCallback()) # First, we change our Radiobutton global variables into a list colors = ["Blue", "Gold", "Red"] # create three Radiobuttons using one variable self.radVar = tk.IntVar() # Next we are selecting a non-existing index value for radVar self.radVar.set(99) # Now we are creating all three Radiobutton widgets within one loop for col in range(3): curRad = tk.Radiobutton(self.mighty2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=1, sticky=tk.W) # And now adding tooltips ToolTip(curRad, 'This is a Radiobutton control') # Add a Progressbar to Tab 2 self.progress_bar = ttk.Progressbar(tab2, orient='horizontal', length=336, mode='determinate') self.progress_bar.grid(column=0, row=3, pady=2) # Create a container to hold buttons buttons_frame = ttk.LabelFrame(self.mighty2, text=' ProgressBar ') buttons_frame.grid(column=0, row=2, sticky='W', columnspan=2) # Add Buttons for Progressbar commands ttk.Button(buttons_frame, text=" Run Progressbar ", command=self.run_progressbar).grid(column=0, row=0, sticky='W') ttk.Button(buttons_frame, text=" Start Progressbar ", command=self.start_progressbar).grid(column=0, row=1, sticky='W') ttk.Button(buttons_frame, text=" Stop immediately ", command=self.stop_progressbar).grid(column=1, row=0, sticky='W') ttk.Button(buttons_frame, text=" Stop after second ", command=self.progressbar_stop_after).grid(column=1, row=1, sticky='W') for child in buttons_frame.winfo_children(): child.grid_configure(padx=2, pady=2) for child in self.mighty2.winfo_children(): child.grid_configure(padx=8, pady=2) # Create Manage Files Frame ------------------------------------------------ mngFilesFrame = ttk.LabelFrame(tab2, text=' Manage Files: ') mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print(fName) self.fileEntry.config(state='enabled') self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) if len(fName) > self.entryLen: self.fileEntry.config(width=len(fName) + 3) # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text="Browse to File...", command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) #----------------------------------------------------- file = tk.StringVar() self.entryLen = scrol_w - 4 self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.grid(column=1, row=0, sticky=tk.W) #----------------------------------------------------- logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() file = src.split('/')[-1] dst = self.netwEntry.get() + '\\' + file try: shutil.copy(src, dst) msg.showinfo('Copy File to Network', 'Succes: File copied.') except FileNotFoundError as err: msg.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as ex: msg.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex)) cb = ttk.Button(mngFilesFrame, text="Copy File To : ", command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) # Creating a Menu Bar ========================================================== menu_bar = Menu(self.win) self.win.config(menu=menu_bar) # Add menu items file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label="New") file_menu.add_separator() file_menu.add_command(label="Exit", command=self._quit) menu_bar.add_cascade(label="File", menu=file_menu) # Display a Message Box def _msgBox(): msg.showinfo( 'Python Message Info Box', 'A Python GUI created using tkinter:\nThe year is 2019.') # Add another Menu to the Menu Bar and an item help_menu = Menu(menu_bar, tearoff=0) help_menu.add_command( label="About", command=_msgBox) # display messagebox when clicked menu_bar.add_cascade(label="Help", menu=help_menu) # Change the main windows icon self.win.iconbitmap('pyc.ico') # It is not necessary to create a tk.StringVar() # strData = tk.StringVar() strData = self.spin.get() # call function self.usingGlobal() # self.name_entered.focus() # Set focus to Tab 2 # tabControl.select(1) # Add Tooltips ----------------------------------------------------- # Add a Tooltip to the Spinbox ToolTip(self.spin, 'This is a Spinbox control') # Add Tooltips to more widgets ToolTip(self.name_entered, 'This is an Entry control') ToolTip(self.action, 'This is a Button control') ToolTip(self.scrol, 'This is a ScrolledText control')
class OOP(): def __init__(self, language='en'): # Create instance self.win = tk.Tk() self.i18n = I18N(language) # self.i18n = I18N(language) # Add a title self.win.title(self.i18n.title) # Callback methods now in different module self.callBacks = Callbacks(self) # Disable resizing the window self.win.resizable(0,0) # Create a Queue self.guiQueue = Queue() self.createWidgets() # populate Tab 2 Entries self.callBacks.defaultFileEntries() # create MySQL instance self.mySQL = MySQL() # create Logger instance fullPath = path.realpath(__file__) self.log = Logger(fullPath) # create Log Level instance self.level = LogLevel() ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab # tabControl.add(tab1, text='MySQL') # Add the tab -- COMMENTED OUT FOR CH08 tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Widgets') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.mySQL = ttk.LabelFrame(tab1, text=' Python Database ') self.mySQL.grid(column=0, row=0, padx=8, pady=4) # Creating a Label ttk.Label(self.mySQL, text="Book Title:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget book = tk.StringVar() self.bookTitle = ttk.Entry(self.mySQL, width=34, textvariable=book) self.bookTitle.grid(column=0, row=1, sticky='W') # Adding a Textbox Entry widget book1 = tk.StringVar() self.bookTitle1 = ttk.Entry(self.mySQL, width=34, textvariable=book1) self.bookTitle1.grid(column=0, row=2, sticky='W') # Adding a Textbox Entry widget book2 = tk.StringVar() self.bookTitle2 = ttk.Entry(self.mySQL, width=34, textvariable=book2) self.bookTitle2.grid(column=0, row=3, sticky='W') # Creating a Label ttk.Label(self.mySQL, text="Page:").grid(column=1, row=0, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber.grid(column=1, row=1, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber1 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber1.grid(column=1, row=2, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber2 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber2.grid(column=1, row=3, sticky='W') # Adding a Button self.action = ttk.Button(self.mySQL, text="Insert Quote", command=self.callBacks.insertQuote) self.action.grid(column=2, row=1) # Adding a Button self.action1 = ttk.Button(self.mySQL, text="Get Quotes", command=self.callBacks.getQuote) self.action1.grid(column=2, row=2) # Adding a Button self.action2 = ttk.Button(self.mySQL, text="Mody Quote", command=self.callBacks.modifyQuote) self.action2.grid(column=2, row=3) # Add some space around each widget for child in self.mySQL.winfo_children(): child.grid_configure(padx=2, pady=4) quoteFrame = ttk.LabelFrame(tab1, text=' Book Quotation ') quoteFrame.grid(column=0, row=1, padx=8, pady=4) # Using a scrolled Text control quoteW = 40; quoteH = 6 self.quote = scrolledtext.ScrolledText(quoteFrame, width=quoteW, height=quoteH, wrap=tk.WORD) self.quote.grid(column=0, row=8, sticky='WE', columnspan=3) # Add some space around each widget for child in quoteFrame.winfo_children(): child.grid_configure(padx=2, pady=4) #====================================================================================================== # Tab Control 2 #====================================================================================================== # We are creating a container frame to hold all other widgets -- Tab2 self.widgetFrame = ttk.LabelFrame(tab2, text=self.i18n.WIDGET_LABEL) self.widgetFrame.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons self.chVarDis = tk.IntVar() self.check1 = tk.Checkbutton(self.widgetFrame, text=self.i18n.disabled, variable=self.chVarDis, state='disabled') self.check1.select() self.check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.widgetFrame, text=self.i18n.unChecked, variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W ) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.widgetFrame, text=self.i18n.toggle, variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) self.chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) # Radiobutton list colors = self.i18n.colors self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): self.curRad = 'rad' + str(col) self.curRad = tk.Radiobutton(self.widgetFrame, text=colors[col], variable=self.radVar, value=col, command=self.callBacks.radCall) self.curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips tt.createToolTip(self.curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.widgetFrame, text=self.i18n.labelsFrame) labelsFrame.grid(column=0, row=7, pady=6) # Place labels into the container element - vertically ttk.Label(labelsFrame, text=self.i18n.chooseNumber).grid(column=0, row=0) self.lbl2 = tk.StringVar() self.lbl2.set(self.i18n.label2) ttk.Label(labelsFrame, textvariable=self.lbl2).grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=6, pady=1) number = tk.StringVar() self.combo = ttk.Combobox(self.widgetFrame, width=12, textvariable=number) self.combo['values'] = (1, 2, 4, 42, 100) self.combo.grid(column=1, row=7, sticky=tk.W) self.combo.current(0) self.combo.bind('<<ComboboxSelected>>', self.callBacks._combo) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.widgetFrame, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self.callBacks._spin) self.spin.grid(column=2, row=7, sticky='W,', padx=6, pady=1) # Using a scrolled Text control scrolW = 40; scrolH = 1 self.scr = scrolledtext.ScrolledText(self.widgetFrame, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=8, sticky='WE', columnspan=3) # Adding a TZ Button self.allTZs = ttk.Button(self.widgetFrame, text=self.i18n.timeZones, command=self.callBacks.allTimeZones) self.allTZs.grid(column=0, row=9, sticky='WE') # Adding local TZ Button self.localTZ = ttk.Button(self.widgetFrame, text=self.i18n.localZone, command=self.callBacks.localZone) self.localTZ.grid(column=1, row=9, sticky='WE') # Adding getTime TZ Button self.dt = ttk.Button(self.widgetFrame, text=self.i18n.getTime, command=self.callBacks.getDateTime) self.dt.grid(column=2, row=9, sticky='WE') # Create Manage Files Frame ------------------------------------------------ mngFilesFrame = ttk.LabelFrame(tab2, text=self.i18n.mgrFiles) mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print(fName) self.fileEntry.config(state='enabled') self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) if len(fName) > self.entryLen: self.fileEntry.config(width=len(fName) + 3) # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text=self.i18n.browseTo, command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) #----------------------------------------------------- file = tk.StringVar() self.entryLen = scrolW - 4 self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.grid(column=1, row=0, sticky=tk.W) #----------------------------------------------------- logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() file = src.split('/')[-1] dst = self.netwEntry.get() + '\\'+ file try: shutil.copy(src, dst) mBox.showinfo('Copy File to Network', 'Succes: File copied.') except FileNotFoundError as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as ex: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex)) cb = ttk.Button(mngFilesFrame, text=self.i18n.copyTo, command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) # Creating a Menu Bar ========================================================== menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label=self.i18n.new) fileMenu.add_separator() fileMenu.add_command(label=self.i18n.exit, command=self.callBacks._quit) menuBar.add_cascade(label=self.i18n.file, menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label=self.i18n.about) menuBar.add_cascade(label=self.i18n.help, menu=helpMenu) # Change the main windows icon self.win.iconbitmap(r'C:\Python34\DLLs\pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() # Place cursor into name Entry self.bookTitle.focus() # Add a Tooltip to the Spinbox tt.createToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets tt.createToolTip(self.bookTitle, 'This is an Entry control.') tt.createToolTip(self.action, 'This is a Button control.') tt.createToolTip(self.scr, 'This is a ScrolledText control.')
class OOP(): def __init__(self): # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") self.createWidgets() # Button callback def clickMe(self): self.action.configure(text='Hello ' + self.name.get()) # Button callback Clear Text def clearScrol(self): self.scr.delete('1.0', tk.END) # Spinbox callback def _spin(self): value = self.spin.get() print(value) self.scr.insert(tk.INSERT, value + '\n') # Checkbox callback def checkCallback(self, *ignoredArgs): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton callback function def radCall(self): radSel=self.radVar.get() if radSel == 0: self.monty2.configure(text='Blue') elif radSel == 1: self.monty2.configure(text='Gold') elif radSel == 2: self.monty2.configure(text='Red') # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() def usingGlobal(self): GLOBAL_CONST = 777 print(GLOBAL_CONST) ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='Tab 1') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Tab 2') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.monty = ttk.LabelFrame(tab1, text=' Monty Python ') self.monty.grid(column=0, row=0, padx=8, pady=4) # Changing our Label ttk.Label(self.monty, text="Enter a name:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget self.name = tk.StringVar() nameEntered = ttk.Entry(self.monty, width=12, textvariable=self.name) nameEntered.grid(column=0, row=1, sticky='W') # Adding a Button self.action = ttk.Button(self.monty, text="Click Me!", command=self.clickMe) self.action.grid(column=2, row=1) ttk.Label(self.monty, text="Choose a number:").grid(column=1, row=0) number = tk.StringVar() numberChosen = ttk.Combobox(self.monty, width=12, textvariable=number) numberChosen['values'] = (1, 2, 4, 42, 100) numberChosen.grid(column=1, row=1) numberChosen.current(0) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.monty, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin) self.spin.grid(column=0, row=2) # Using a scrolled Text control scrolW = 30; scrolH = 3 self.scr = scrolledtext.ScrolledText(self.monty, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=3, sticky='WE', columnspan=3) # TODO: ch11 new #------------------------------------------------------------------------- #------------------------------------------------------------------------- # Adding another Button self.action = ttk.Button(self.monty, text="Clear Text", command=self.clearScrol) self.action.grid(column=2, row=2) # Adding more Feature Buttons startRow = 4 for idx in range(12): if idx < 2: colIdx = idx col = colIdx else: col += 1 if not idx % 3: startRow += 1 col = 0 b = ttk.Button(self.monty, text="Feature " + str(idx+1)) b.grid(column=col, row=startRow) # Tab Control 3 ----------------------------------------- tab3 = ttk.Frame(tabControl) # Add a tab tabControl.add(tab3, text='Tab 3') # Make tab visible # We are creating a container frame to hold all other widgets -- Tab3 monty3 = ttk.LabelFrame(tab3, text=' New Features ') monty3.grid(column=0, row=0, padx=8, pady=4) # Adding more Feature Buttons startRow = 4 for idx in range(24): if idx < 2: colIdx = idx col = colIdx else: col += 1 if not idx % 3: startRow += 1 col = 0 b = ttk.Button(monty3, text="Feature " + str(idx+1)) b.grid(column=col, row=startRow) # Add some space around each label for child in monty3.winfo_children(): child.grid_configure(padx=8) #------------------------------------------------------------------------- # TODO: ch11 new end # Tab Control 2 refactoring ----------------------------------------- # We are creating a container frame to hold all other widgets -- Tab2 self.monty2 = ttk.LabelFrame(tab2, text=' Holy Grail ') self.monty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(self.monty2, text="Disabled", variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.monty2, text="UnChecked", variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W ) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.monty2, text="Toggle", variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) self.chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) # ~ Tab Control 2 refactoring ----------------------------------------- # Radiobutton list colors = ["Blue", "Gold", "Red"] self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): curRad = 'rad' + str(col) curRad = tk.Radiobutton(self.monty2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips tt.createToolTip(curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.monty2, text=' Labels in a Frame ') labelsFrame.grid(column=0, row=7) # Place labels into the container element - vertically ttk.Label(labelsFrame, text="Label1").grid(column=0, row=0) ttk.Label(labelsFrame, text="Label2").grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=8) # Creating a Menu Bar menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label="New") fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self._quit) menuBar.add_cascade(label="File", menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About") menuBar.add_cascade(label="Help", menu=helpMenu) # Change the main windows icon self.win.iconbitmap(r'C:\Python34\DLLs\pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') print(strData.get()) # Default tkinter Variable Classes intData = tk.IntVar() print(intData.get()) print(tk.DoubleVar()) print(tk.BooleanVar()) # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() print("Hello " + strData) # Printing the Global works print(GLOBAL_CONST) # call method self.usingGlobal() # Place cursor into name Entry nameEntered.focus() # Add a Tooltip to the Spinbox tt.createToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets tt.createToolTip(nameEntered, 'This is an Entry control.') tt.createToolTip(self.action, 'This is a Button control.') tt.createToolTip(self.scr, 'This is a ScrolledText control.')
class AppUI(): m_branchs = ['分行本部', '柯桥支行', '嵊州支行', '上虞支行', '世纪街支行', '诸暨支行', '新昌支行'] m_ips = [ '', '11.43.1.', '11.43.2.', '11.43.3.', '11.43.4.', '11.43.5.', '11.43.6.' ] m_floorIPs = [ '11.43.128.', '11.43.129.', '11.43.130.', '11.43.131.', '11.43.132.', '11.43.133.', '11.43.134.' ] m_floors = ['一楼', '二楼', '三楼', '四楼', '五楼', '六楼', '十八楼'] def __init__(self): self.root = Tk() self.root.option_add('*Dialog.msg.font', 'Helvetica 12') self.ft = tkFont.Font(family='FangSong', size=20, weight=tkFont.BOLD) self.selectedBranch = '' self.selectedFloor = '' self.create_menu(self.root) self.create_content(self.root) self.root.title("绍兴分行运维自动化工具") self.root.update() self.center_window() def center_window(self): curWidth = self.root.winfo_width() # get current width curHeight = self.root.winfo_height() # get current height scnWidth, scnHeight = self.root.maxsize( ) # get screen width and height tmpcnf = '+%d+%d' % ((scnWidth - curWidth) / 2, (scnHeight - curHeight) / 2) self.root.geometry(tmpcnf) self.root.mainloop() def create_menu(self, root): #创建菜单栏 menu = Menu(root) #创建二级菜单 help_menu = Menu(menu, tearoff=0) help_menu.add_command(label="本系统由宁波银行绍兴分行金融科技部开发。" + "\r\n如有问题请联系运维阮金国 王立刚8831") about_menu = Menu(menu, tearoff=0) about_menu.add_command(label="version:1.0") #在菜单栏中添加以下一级菜单 menu.add_cascade(label="帮助", menu=help_menu) menu.add_cascade(label="关于", menu=about_menu) root['menu'] = menu def create_content(self, root): frm = LabelFrame(height=200, width=300, text='IP管理', borderwidth=3) frm.grid(row=0, column=0, pady=10) ttk.Label(frm, text=" 机 构: ", font=self.ft).grid(row=0, column=0, pady=10) self.branchWidget = ttk.Combobox(frm, textvariable=StringVar, state="readonly", width=10, font=self.ft) self.branchWidget['values'] = self.m_branchs self.branchWidget.bind("<<ComboboxSelected>>", self.branchGet) self.branchWidget.grid(row=0, column=1, columnspan=3, padx=10, pady=10) ttk.Label(frm, text=" 楼 层: ", font=self.ft).grid(row=1, column=0, pady=10) self.floorWidget = ttk.Combobox(frm, textvariable=StringVar, state="disabled", width=10, font=self.ft) self.floorWidget.bind("<<ComboboxSelected>>", self.floorGet) self.floorWidget.grid(row=1, column=1, columnspan=3, padx=10, pady=10) ttk.Label(frm, text=" 座位号: ", font=self.ft).grid(row=2, column=0, pady=10) ttk.Label(frm, text=" A", font=self.ft).grid(row=2, column=1, pady=10) self.netportWidget = Spinbox(frm, from_=0, to=255, width=5, bd=8, font=self.ft) self.netportWidget.grid(row=2, column=2) button = ttk.Button(frm, text="点我查看座位号", command=self.viewHelp) button.grid(row=2, column=3) ttk.Button(frm, text="设置IP", command=self.changeIP).grid(row=3, column=0, padx=10, pady=10) self.progress_bar = ttk.Progressbar(frm, orient='horizontal', mode='determinate', maximum=100, length=180) self.progress_bar.grid(row=3, column=1, columnspan=3, padx=10, pady=10) def viewHelp(self): tkinter.messagebox.showwarning( '提示', '请查座位下网口号上\n A口后面的数字' + '\n Axx Bxx' + '\n 口 口') def branchGet(self, Event): self.selectedBranch = self.branchWidget.get() if self.m_branchs[0] == self.selectedBranch: self.floorWidget['values'] = self.m_floors self.floorWidget.configure(state='readonly') else: self.floorWidget.set('') self.floorWidget.configure(state='disabled') def floorGet(self, Event): self.selectedFloor = self.floorWidget.get() def getArrIndex(self, ele, array): for i in range(len(array)): if ele == array[i]: return i return -1 def updateProcess(self, process): self.progress_bar['value'] = process self.progress_bar.update() def changeIP(self): ip = '' subnetmask = '255.255.255.0' gateway = '' self.updateProcess(10) selectedBranch = self.getArrIndex(self.selectedBranch, self.m_branchs) if -1 == selectedBranch: self.updateProcess(0) tkinter.messagebox.showwarning('提示', '请选择机构') return elif 0 == selectedBranch: #分行本级 selectedFloor = self.getArrIndex(self.selectedFloor, self.m_floors) if -1 == selectedFloor: self.updateProcess(0) tkinter.messagebox.showwarning('提示', '请选择楼层') return ip = self.m_floorIPs[selectedFloor] else: ip = self.m_ips[selectedBranch] self.updateProcess(30) netport = self.netportWidget.get() if '0' == netport: self.updateProcess(0) tkinter.messagebox.showwarning('提示', '请选择座位号') return gateway = ip + '254' ip = ip + netport dns = ['11.43.240.193', '11.43.240.194'] print('ip:' + ip + ',gateway:' + gateway) self.updateProcess(40) # Obtain network adaptors configurations nic_configs = wmi.WMI().Win32_NetworkAdapterConfiguration( IPEnabled=True) # First network adaptor nic = nic_configs[0] self.updateProcess(60) # Set IP address, subnetmask and default gateway # Note: EnableStatic() and SetGateways() methods require *lists* of values to be passed returnValue = nic.EnableStatic(IPAddress=[ip], SubnetMask=[subnetmask]) self.updateProcess(80) nic.SetDNSServerSearchOrder(DNSServerSearchOrder=dns) nic.SetGateways(DefaultIPGateway=[gateway]) self.updateProcess(100) if 0 == returnValue[0]: tkinter.messagebox.showwarning('提示', 'ip修改成功!') else: tkinter.messagebox.showerror('错误', 'ip修改失败!') self.updateProcess(0)
class VisAnaGUI(tk.LabelFrame): ## constants for current mode PLOT_MODE = 10 ANALYTICS_MODE = 11 ## constants for shown cluster plot SMALL_MULTIPLES = 20 SMALL_HISTOS = 21 #update levels, each level includes all lower ones NOTHING=0 TIMELINE_SELECTION=1 TIMELINE_DAYSINPLOT=2 PLOT=3 PLOT_DATA=4 DATA_TIDYUP=5 def __init__(self, master=None, ds=None): #self.dates = [] #for dt in rrule.rrule(rrule.DAILY, # dtstart=datetime(2014,1,1,0,0,0), # until=datetime(2015,1,1,0,0,0)): # self.dates.append(dt.date()) self.mode = self.PLOT_MODE self.cluster_k = 4 self.mininterval=60 ## save data source self.ds = ds #type:datasource.DataSource # self.ds.groupby("all_days", datasource.TIME_ATTR, "COUNT","base", bydate=True) #self.ds.aggregateTime("all_days", "COUNT",60,"base") # self.ds.aggregateTime("all_days", "COUNT",24*60,"base") #self.ds.link("show") #self.df=ds.get_base_data().df() ## parameter variables for listboxes self.param_list = list(ds.get_data("base").get_attr_names())#["MasterTime", "Small", "Large", "OutdoorTemp","RelHumidity"] self.param2 = self.param_list[1] self.param1 = self.param_list[2] self.aggregation_limit=360 ## simple string to describe last action (for history) self.action_str = "Show base data" self.plot_tooltip=None self.select_rect=None self.draw_frame(master) self.mouse_pressed=None self.clause=dict() ## save time of last update to prevent too many ## updates when using sliders self.last_action = time() ## delay after last data update and action (in ms) self.UPDATE_DELAY = 500 ## was there an action triggering an update? # (0=no, 1=only the timeline, 2=axes and timeline, 3=with selection, 4 with tidyup) self.unprocessed_action = self.DATA_TIDYUP ## calls check_for_update() method after delay has passed self.after(self.UPDATE_DELAY, self.check_for_update) ## dummy variable to ignore first update. sliders trigger an ## event at startup, which would lead to redundant update of data self.ignore_start_trigger = True ## draw data at startup self.update_data() ####################### # UI CREATION def draw_frame(self, master): tk.LabelFrame.__init__(self, master)#, bg="red") root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) root.title("Visual Analyser - Gui") self.grid(column=0, row=0, sticky=(tk.N,tk.W,tk.E,tk.S)) self.columnconfigure(1, weight=1) self.rowconfigure(3,weight=1) self.rowconfigure(2,minsize=100) #self.configure(background="red") self.create_widgets() ## creates all GUI elements def create_widgets(self): self.toolbar=tk.LabelFrame(self) self.toolbar.grid(column=0, row=0, sticky=(tk.W, tk.N, tk.E), columnspan=5) self.QUIT = tk.Button(self.toolbar, text="QUIT", fg="red", command=root.destroy) self.QUIT.grid(column=0, row=0, sticky=(tk.W, tk.N)) self.reset_view_btn = tk.Button(self.toolbar) self.reset_view_btn["text"] = "Reset the View" self.reset_view_btn["command"] = self.reset_to_start self.reset_view_btn.grid(column=1, row=0, sticky=(tk.W, tk.N)) self.toggle_hist_btn = tk.Button(self.toolbar) self.toggle_hist_btn["text"] = "Toggle History" self.toggle_hist_btn["command"] = self.toggle_history self.toggle_hist_btn.grid(column=4, row=0, sticky=(tk.W, tk.N)) # self.tdvar = tk.StringVar(value="0") # self.tidy_up = tk.Checkbutton(self.toolbar, text='Tidy Up Data', command=self.handle_tidy_up, # variable=self.tdvar) # self.tidy_up.grid(column=2, row=0, sticky=(tk.W, tk.N)) self.rgvar = tk.StringVar(value="0") self.regression = tk.Checkbutton(self.toolbar, text='Draw Regression', command=self.handle_regression, variable=self.rgvar) self.regression.grid(column=3, row=0, sticky=(tk.W, tk.N)) self.left_sidebar = tk.Frame(self) self.left_sidebar.grid(column=0, row=3, sticky=(tk.N, tk.E, tk.W)) self.projector = self.create_listboxes(self.left_sidebar) self.projector.grid(column=0, row=0, sticky=(tk.N, tk.E, tk.W)) self.selector = Selector_old.Selector_old(self.left_sidebar, self.ds, self.handle_selector_change) self.selector.grid(column=0, row=1, sticky=(tk.N, tk.E, tk.W)) self.history_text = "::LOG::\n" self.create_history() self.create_plot() def create_history(self): self.history_shown = True self.history = tk.Text(self, width=45) self.history.grid(column=2, row=3, sticky=(tk.N, tk.E, tk.S), rowspan=2) self.history.insert('end', self.history_text) self.history.see("end") self.historyslider = tk.Scrollbar(self,orient=tk.VERTICAL, command=self.history.yview) self.historyslider.grid(column=3, row=3, sticky=(tk.N, tk.S), rowspan=2) self.history['yscrollcommand'] = self.historyslider.set def create_listboxes(self, parent) -> tk.LabelFrame: frame=tk.LabelFrame(parent)#, bg="red") self.paramlabel = tk.Label(frame, text="Choose Parameters") self.paramlabel.grid(column=0, row=0, sticky=(tk.N, tk.E, tk.W), columnspan=2) ## listboxes for parameter selection self.param1lbl = tk.Label(frame, text="X-Axis:") self.param1lbl.grid(column=0, row=1, sticky=(tk.N, tk.E, tk.W)) self.param1var = StringVar() self.param1var.set(self.param1) self.param1box=Combobox(frame, textvariable=self.param1var, state="readonly") self.param1box['values'] = self.param_list self.param1box.bind('<<ComboboxSelected>>', self.handle_paramsChanged) self.param1box.grid(column=1, row=1, sticky=(tk.N, tk.E, tk.W)) self.param1lbl = tk.Label(frame, text="Y-Axis:") self.param1lbl.grid(column=0, row=2, sticky=(tk.N, tk.E, tk.W)) self.param2var = StringVar() self.param2var.set(self.param2) self.param2box = Combobox(frame, textvariable=self.param2var, state="readonly") self.param2box['values'] = self.param_list self.param2box.bind('<<ComboboxSelected>>', self.handle_paramsChanged) self.param2box.grid(column=1, row=2, sticky=(tk.N, tk.E, tk.W)) # self.param2box = Listbox(self.projector, exportselection=0) # for item in self.param_list: # self.param2box.insert("end", item) # param2_index = self.param_list.index(self.param2) # self.param2box.select_set(param2_index) # self.param2box.bind('<<ComboboxSelected>>', self.handle_paramsChanged) # self.param2box.grid(column=0, row=2, sticky=(tk.N, tk.E, tk.W)) self.var = StringVar(frame) self.var.set(str(self.aggregation_limit)) self.noise_spin = Spinbox(frame, from_=1, to=1440, textvariable=self.var ,width=4) self.noise_spin.grid(column=0, row=3, sticky=(tk.E, tk.W)) self.testbutton = tk.Button(frame) self.testbutton["text"] = "Aggregate values (minutes)" self.testbutton["command"] = self.handle_aggregate_btn self.testbutton.grid(column=1, row=3, sticky=(tk.W, tk.N)) return frame # ## add sliders to GUI # def create_sliders(self): # ## init sliders # # #self.filter = tk.LabelFrame(self, bg="#0066ff") # self.filter = tk.LabelFrame(self, bg="red") # self.filter.grid(column=0, row=1, sticky=(tk.N, tk.E, tk.W),columnspan=5) # self.filter.columnconfigure(1, weight=1) # self.filter.columnconfigure(0, weight=0) # # self.startSlider = Scale(self.filter, from_=0, to=365, orient=HORIZONTAL, command=self.update_start) # self.startSlider.set(0) # self.endSlider = Scale(self.filter, from_=0, to=365, orient=HORIZONTAL, command=self.update_end) # self.endSlider.set(365) # # ## add sliders and labels to GUI # self.startSlider.grid(column=1, row=0, sticky=(tk.W, tk.N, tk.E)) # self.startlabel = tk.Label(self.filter, text="FROM \tVALUE") # self.startlabel.grid(column=0, row=0, sticky=(tk.W)) # self.endSlider.grid(column=1, row=1, sticky=(tk.W, tk.S, tk.E)) # self.endlabel = tk.Label(self.filter, text="TO \tVALUE") # self.endlabel.grid(column=0, row=1, sticky=(tk.W)) #add an empty plot to the GUI def create_plot(self): self.fig = Figure(figsize=(5, 5), dpi=100) #type:Figure self.ax = self.fig.add_subplot(111) #type:Axes #self.ax2 = self.fig.add_subplot(212) self.ax.grid(True) self.canvas = FigureCanvasTkAgg(self.fig, self) ##type:FigureCanvasTkAgg self.canvas.mpl_connect('motion_notify_event', self.handle_hover) self.canvas.mpl_connect('button_press_event', self.handle_mouse_down) self.canvas.mpl_connect('button_release_event', self.handle_mouse_up) #self.canvas.mpl_connect('pick_event', self.draw_tooltip) self.canvas.get_tk_widget().grid(column=1, row=3, sticky=(tk.N, tk.E, tk.W, tk.S)) # self.canvas_tb = NavigationToolbar2TkAgg(self.canvas, self.canvas.get_tk_widget()) #self.ctbwidget=tk.Frame(self) #self.ctbwidget.grid(column=1, row=4, sticky=(tk.N, tk.E, tk.W, tk.S)) #self.canvas_tb = NavigationToolbar2TkAgg(self.canvas, self.ctbwidget) util.zoom_factory(self.ax) ############################ # UI HANDLER ## generate clusters and asks for custom grain classes def create_clusters(self, in_table="base"): ## call dialogue window to ask for custom grain classes Mbox = GrainSelection.Mbox Mbox.root = root mbox = Mbox() ## wait for answer root.wait_window(mbox.top) ## -> result is in mbox.classesDict ## ask if valid answer has been submitted if mbox.success: ## fetch answers in dict with changed labels custom_classes_dict = {} #print(mbox.classesDict) for k,v in mbox.classesDict.items(): col = "GRAIN_CLASS_"+str(k) custom_classes_dict[col] = v self.c_param_list = sorted(list(custom_classes_dict.keys())) #print("CREATE CLUSTERS") ## call analytics functions analytics.create_distributions(in_table, "out", self.ds, custom_classes_dict=custom_classes_dict) self.centroids = analytics.calc_clusters(in_table="cluster_distr", out_table="clustered", datasource=self.ds, k=self.cluster_k, colNames=self.c_param_list) #print("\tCLUSTERED") ## change state variables so the proper graph is displayed self.mode = self.ANALYTICS_MODE #self.plot_type = self.SMALL_HISTOS self.plot_type = self.SMALL_MULTIPLES #print("change mode to ",self.mode) ## TODO: might need to be changed?! self.unprocessed_action=self.PLOT_DATA self.add_to_history("generate clusters") self.action_str = "Generate clusters" #print("\tCLUSTERING FINISHED") ## dummy method def reset_to_start(self): self.create_clusters() self.clean_tooltip(True) #self.param1box.select_set(self.param_list.index("Large")) #self.param2box.select_set(self.param_list.index("Small")) # self.startSlider.set(0) # self.endSlider.set(365) self.var.set("1") self.handle_aggregate_btn() #self.tdvar.set("0") self.unprocessed_action=self.DATA_TIDYUP self.add_to_history("reset to basedata") self.action_str = "Show base data" #print("hi there, everyone!") def toggle_history(self): if self.history_shown: self.destroy_history() else: self.create_history() def destroy_history(self): self.history_shown = False self.history.destroy() self.historyslider.destroy() #self.history_text = self.history. def handle_aggregate_btn(self): self.aggregation_limit = int(self.noise_spin.get()) self.action_str = "Aggregated values: "+str(self.aggregation_limit)+"min" self.trigger_update(level=self.PLOT_DATA) # def handle_tidy_up(self): # if self.tdvar.get() is "0": # self.action_str="show raw data" # else: # self.action_str="tidy up data, remove all points where:" \ # "\n OutdoorTemp>40 or Small<0 or Large<0 or " \ # "\n RelHumidity<0" # self.trigger_update(level=self.DATA_TIDYUP) def handle_regression(self): if self.rgvar.get() is "0": self.action_str="hide regression" else: self.action_str="draw regression" self.trigger_update(level=self.PLOT) def handle_view_change(self,ax=None): if ax is None: ax=self.ax self.handle_changed_axes() print("viewport changed to", ax.get_xlim(), ax.get_ylim()) ######### ## SLIDER METHODS ## we need separate update functions for the sliders, ## as we could otherwise not distinguish between changing ## the first or second slider ######### # ## triggered by changing startslider value # def update_start(self, event): # fromVal = self.startSlider.get() # endVal = self.endSlider.get() # if endVal < fromVal: # self.endSlider.set(fromVal) # # self.handle_slider_update() # # ## triggered by changing endslider value # def update_end(self, event): # fromVal = self.startSlider.get() # endVal = self.endSlider.get() # if endVal < fromVal: # self.startSlider.set(endVal) # # self.handle_slider_update() # # ## handle data update event, i.e. a slider changed. # def handle_slider_update(self): # fromVal = self.startSlider.get() # endVal = self.endSlider.get() # self.startlabel["text"] = "FROM \t"+str(self.dates[fromVal]) # self.endlabel["text"] = "TO \t"+str(self.dates[endVal]) # self.trigger_update(level=self.PLOT_DATA) # self.last_action = time() # self.action_str = "New time interval: "+str(self.dates[fromVal])+" - "+str(self.dates[endVal]) ## handle data update event, i.e. a slider changed. def handle_selector_change(self,clause): self.clause=clause self.trigger_update(level=self.PLOT_DATA) self.last_action = time() self.action_str = "New selection: "+str(clause) ## a different parameter was chosen def handle_paramsChanged(self, e): #self.param1 = self.param_list[self.param1box.curselection()[0]] self.param1 = self.param1var.get() self.param1box.select_clear() self.param2 = self.param2var.get() self.param2box.select_clear() # self.param2 = self.param_list[self.param2box.curselection()[0]] self.action_str = "New parameters: " + self.param1 + " & " + self.param2 self.trigger_update(level=self.PLOT) ################### # PLOT-EVENT HANDLER def handle_changed_axes(self): self.clean_tooltip() xlim = self.ax.get_xlim() ylim = self.ax.get_xlim() text="Focus changed to: x=[{:.1f};{:.1f}] and y=[{:.1f};{:.1f}]".format(xlim[0], xlim[1], ylim[0], ylim[1]) self.add_to_history(text) ## is called by the plot to confirm if the mouseevent was inside/on a plotted line or a marker def handle_pick(self, line, mouseevent): if mouseevent.button == 1: return self.handle_mouse_event(mouseevent) else: return False,dict() ## is called to to do something when the mouse hovers over the plot and has changed its position. ## if no mousebutton is pressed and no points were selected, a hover-tooltip is shown. ## if the left button is pressed, (re-)draw the selection indicator i=1 def handle_hover(self, mouseevent): if not mouseevent.button in [1,3] and self.select_rect is None: isover, props = self.handle_mouse_event(mouseevent) if isover: self.draw_tooltip(mouseevent, props["ind"]) elif mouseevent.button in [1,3]: ## handle case if mouse is outside the canvas if mouseevent.xdata == None: xmin = self.mouse_pressed[0] xmax = self.mouse_pressed[0] ymin = self.mouse_pressed[1] ymax = self.mouse_pressed[1] else: xmin = min(mouseevent.xdata, self.mouse_pressed[0]) xmax = max(mouseevent.xdata, self.mouse_pressed[0]) ymin = min(mouseevent.ydata, self.mouse_pressed[1]) ymax = max(mouseevent.ydata, self.mouse_pressed[1]) bbox=(xmin, ymin, xmax, ymax) self.clean_tooltip(True, emit=False) bbox2=self.ax.transData.transform(bbox) c_height = self.canvas.figure.bbox.height bbox3=(bbox2[0], c_height-bbox2[1], bbox2[2],c_height-bbox2[3]) self.select_rect = self.canvas.get_tk_widget().create_rectangle(bbox3, dash=".") ## is called whenever a mousebutton is clicked while the mouse is over the plot. ## if the left button is pushed, we begin to draw a selection area def handle_mouse_down(self, mouseevent): if mouseevent.button in [1,3]: self.clean_tooltip(True) self.mouse_pressed=(mouseevent.xdata, mouseevent.ydata) ## is called whenever a mouse button is released while hovering over the plot ## if the left button was pressed and there are points within the selection area, select those points and show a ## tooltip containing information about those selected points. If not, clean up. def handle_mouse_up(self, mouseevent): if mouseevent.button in [1,3]: ## handle case if mouse is outside the canvas if mouseevent.xdata == None: xmin = self.mouse_pressed[0] xmax = self.mouse_pressed[0] ymin = self.mouse_pressed[1] ymax = self.mouse_pressed[1] else: xmin = min(mouseevent.xdata, self.mouse_pressed[0]) xmax = max(mouseevent.xdata, self.mouse_pressed[0]) ymin = min(mouseevent.ydata, self.mouse_pressed[1]) ymax = max(mouseevent.ydata, self.mouse_pressed[1]) if xmin == xmax and ymin == ymax: self.clean_tooltip(True) else: if mouseevent.button == 1: if self.param1 == datasource.TIME_ATTR: xmin = mdates.num2date(xmin) xmax = mdates.num2date(xmax) if self.param2 == datasource.TIME_ATTR: ymin = mdates.num2date(ymin) ymax = mdates.num2date(ymax) self.ds.select("selected", self.param1, xmin, xmax, "show") self.ds.select("selected", self.param2, ymin, ymax, "selected") ind=self.df("selected").index.values if len(ind)>0: self.action_str="Selected area from ({:.1f}; {:.1f})\n\t to ({:.1f}; {:.1f})".format(xmin,ymin,xmax,ymax) #self.add_to_history(text) self.draw_tooltip(mouseevent,ind, True) self.trigger_update(level=self.TIMELINE_SELECTION) else: self.clean_tooltip(True) else: self.clean_tooltip(True, emit=False) self.ax.set_xlim((xmin,xmax)) self.ax.set_ylim((ymin,ymax)) self.canvas.draw() ## handle any mouse event where it has to be clarified whether there's a marker under the mouse or not. If so, ## return all index values of the concerning markers. def handle_mouse_event(self, mouseevent, radius=5): """ find the points within a certain radius from the mouse in data coords and attach the index numbers of the found elements which are the data points that were picked """ self.clean_tooltip() #print("PICKER") #print(mouseevent, vars(mouseevent)) if self.param1 == datasource.TIME_ATTR or self.param2 == datasource.TIME_ATTR: return False,dict() xydata=self.ax.transData.transform(self.df("show")[[self.param1, self.param2]]).transpose() try: mxy= self.ax.transData.transform([mouseevent.xdata,mouseevent.ydata]) except ValueError: return False,dict() xdata=xydata[0] ydata=xydata[1] mousex=mxy[0] mousey=mxy[1] if mouseevent.xdata is None: return False, dict() d = pd.np.sqrt((xdata - mousex)**2. + (ydata - mousey)**2.) ind = self.df("show").index.values[pd.np.nonzero(pd.np.less_equal(d, radius))[0]] if len(ind) >0: props = dict(ind=ind) return True, props else: return False, dict() ## draws a tooltip and generates the information it contains from an event with/and a list of index values def draw_tooltip(self, event, ind=None, selected=False): if ind is None: ind=event.ind event=event.mouseevent # Generate the Tooltip-String selstr="" if selected: selstr= "selected " if len(ind) is 1: text=selstr + "value:" self.ds.select_ids("selected", ind, "show") for col,cdata in self.df("selected").iteritems(): text += '\n {}: \t{}'.format(col, cdata[ind[0]]) else: text = selstr + "%s values:" % len(ind) if not selected: self.ds.select_ids("selected", ind, "show") self.ds.aggregate("sel_aggremin", "MIN", in_table="selected") self.ds.aggregate("sel_aggremax", "MAX", in_table="selected") for col,cdata in self.df("sel_aggremin").iteritems(): text += '\n {}: \t{} to {}'.format(col, cdata[0], self.df("sel_aggremax")[col][0]) # Draw the box and write the string on it c_height=self.canvas.figure.bbox.height c_width=self.canvas.figure.bbox.width y=c_height-event.y x=event.x #get bounding box of a possible tooltip self.plot_tooltip=self.canvas.get_tk_widget().create_text(x+2, y, anchor=tk.NW,text=text) bbox=self.canvas.get_tk_widget().bbox(self.plot_tooltip) self.canvas.get_tk_widget().delete(self.plot_tooltip) # print("bbox:", bbox) #make sure the tooltip is within bounds if bbox[2]>c_width: adj = -2 if bbox[3]>c_height: anchor=tk.SE else: anchor=tk.NE else: adj = 2 if bbox[3]>c_height: anchor=tk.SW else: anchor=tk.NW #get the new bounding box if anchor is not tk.NW: # =^= the anchor had to be modified self.plot_tooltip=self.canvas.get_tk_widget().create_text(x+adj, y, anchor=anchor,text=text) bbox=self.canvas.get_tk_widget().bbox(self.plot_tooltip) self.canvas.get_tk_widget().delete(self.plot_tooltip) self.plot_tooltip_rect = self.canvas.get_tk_widget().create_rectangle(bbox, fill="yellow") self.plot_tooltip=self.canvas.get_tk_widget().create_text(x+adj, y, anchor=anchor,text=text) # draws a timeline (as a plot) def draw_timeline(self): #df = self.df("show") ## create value for each day in data, ## depending on whether it is selected, shown etc. #shown_dates = self.build_contained_dict(df) if self.aggregation_limit <= self.mininterval: self.ds.aggregateTime("all_days", "COUNT", self.mininterval, "base") else: self.ds.aggregateTime("all_days", "COUNT", self.aggregation_limit, "base") selected_dates=[] if self.select_rect is not None: print("b",self.ds.exists("selected")) #self.ds.groupby2("selected_days", datasource.TIME_ATTR, "COUNT", "selected", bydate=True) #self.ds.aggregateTime("selected_days", "COUNT",24*60, "selected") self.ds.aggregateTime("selected_days", "COUNT",1, "selected") selected_dates = self.df("selected_days").index.values shown_dates=self.df("shown_dates").index.values base_dates=self.df("all_days").index.values ## extract first and last date start_date = base_dates[0] end_date = base_dates[-1] #days_diff = ((end_date-start_date) / np.timedelta64(1, 'D')) ## prepare data for timeline days = [] values = [] #print(self.df("all_days").head(2)) #self.df("all_days"). for date in self.df("all_days").index.values: self.df("all_days") col1_has_values=((self.param1 == datasource.TIME_ATTR) or (self.df("all_days")[self.param1][date]>0)) col2_has_values=((self.param2 == datasource.TIME_ATTR) or (self.df("all_days")[self.param2][date]>0)) if col1_has_values and col2_has_values: days.append(date) ##if random() < 0.01: #if self.dates[self.startSlider.get()] <= day < self.dates[self.endSlider.get()]: if date in shown_dates: values.append("blue") if date in selected_dates: #if random() < 0.05: values.append("red") else: values.append("lightskyblue") #print("d:",days, values) ## plot timeline fig = Figure(figsize=(12,1), dpi=75) ax = fig.add_subplot(111) ax.scatter(days, [1]*len(days), c=values, marker='|', s=300)#, fontsize=10) #fig.xt hfmt = mdates.DateFormatter("1. %b '%y") # fig.subplots_adjust(left=0.03, right=0.97, top=1) ax.xaxis.set_major_formatter(hfmt) fig.autofmt_xdate() #ax.set_xticklabels(ax.xaxis.get_minorticklabels(), rotation=0) #ax.set_xlim([datetime(2014,1,1,0,0,0), datetime(2015,1,1,0,0,0)]) ax.set_xlim([start_date, end_date]) ## everything after this is turning off stuff that's plotted by default ax.yaxis.set_visible(False) ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) ax.spines['top'].set_visible(False) ax.xaxis.set_ticks_position('bottom') ax.get_yaxis().set_ticklabels([]) fig.tight_layout(pad=0) #print(fig.get_figheight()) #fig.subplots_adjust(top=1, right=0.99) ## add to GUI self.timeline = FigureCanvasTkAgg(fig, self) self.timeline.get_tk_widget().grid(column=0, row=2, sticky=(tk.N, tk.E, tk.W, tk.S),columnspan=5) #print("h:",self.timeline.figure.bbox.height) ##################### # UPDATE-FUNCTIONS ## is called regularly, after the given delay def check_for_update(self): ## if there is an unprocessed action older than ## the given delay, update data #self.check_listbox_changes() if self.unprocessed_action>self.NOTHING and \ (time() - self.last_action) > self.UPDATE_DELAY/1000: ## simply block the very first update... ## (there might be prettier solutions) if self.ignore_start_trigger: self.ignore_start_trigger = False else: ## update data self.update_data() #print("checking for updates...") self.after(self.UPDATE_DELAY, self.check_for_update) """ general data tasks: after_tidyup [-> apply sliders ->] time-limited [-> (don't) aggregate ->] show show [-> select ->] selected [-> get min and max ->] """ ## draw new data according to current positions of date sliders and the aggregation limit def update_data(self): #if self.unprocessed_action >= self.DATA_TIDYUP: #if self.tdvar.get() is "0": # self.ds.link("after_tidyup","base") #else: # self.ds.select("after_tidyup", "Large",a=0, in_table="base") # self.ds.select("after_tidyup", "OutdoorTemp",b=40, in_table="after_tidyup") # self.ds.select("after_tidyup", "RelHumidity",a=0, in_table="after_tidyup") # self.ds.select("after_tidyup", "Small",a=0, in_table="after_tidyup") #self.action_str = "tidy up data, remove all points where:" \ # "\n\tOutdoorTemp>40 or Small<0 or Large<0 or " \ # "\n\tRelHumidity<0 or RelHumidity>100" if self.unprocessed_action >=self.PLOT_DATA: #fromVal = self.startSlider.get() #endVal = self.endSlider.get() #self.ds.link("time-limited","after_tidyup") #self.ds.select(out_table="time-limited", attr_name=datasource.TIME_ATTR, # a=self.dates[fromVal], b=self.dates[endVal], in_table="after_tidyup") #self.df = self.ds.get_data("time_filter").df() self.ds.select_complex("sel",self.clause, "base") if self.aggregation_limit==1: self.ds.link("show", "sel") else: self.ds.aggregateTime(out_table="show", mode="AVG", minutes=self.aggregation_limit, in_table="sel") #self.ds.aggregate(out_table="show", mode="AVG", limit=self.aggregation_limit, in_table="base") #self.ds.groupby("shown_dates",datasource.TIME_ATTR, "COUNT", "show", bydate=True) self.ds.aggregateTime("shown_dates","COUNT", self.aggregation_limit, in_table="sel") #self.ds.aggregateTime("shown_dates","COUNT", 24*60,"show") # try: if self.unprocessed_action>=self.PLOT: if self.mode == self.PLOT_MODE: print("draw normal plots") self.draw_plot() elif self.mode == self.ANALYTICS_MODE: print("draw cluster plots") if self.plot_type == self.SMALL_MULTIPLES: print("\tdraw small multiples") self.create_multiple_plots() elif self.plot_type == self.SMALL_HISTOS: print("\tdraw small histograms") self.create_distr_plots() self.draw_timeline() #print("add_to_history:",self.action_str) if self.action_str is not None: self.add_to_history(self.action_str) # except: # pass self.unprocessed_action=self.NOTHING def create_distr_plots(self): self.clean_tooltip(True) self.fig = Figure(figsize=(5, 5), dpi=100) #type:Figure self.ax = self.fig.add_subplot(111) #type:Axes #subplot_num = 0 #print(self.centroids) y_pos = np.arange(len(self.c_param_list)) #print(y_pos) width = 0.95/self.cluster_k #colors = ["#d62728", "blue", "green", "brown"] for c in range(0, self.cluster_k): #subplot_num += 1 ystdev = [] one_value_cluster = self.df("clustered").loc[self.df("clustered")['clusterlabels'] == c] #for i in range(0, len(datasource.GRAIN_COLS)): for i in range(0, len(self.c_param_list)): col = one_value_cluster[self.c_param_list[i]] stdev = np.std(col) ystdev.append(stdev) cen = [self.centroids[c][i] for i in range(0, len(self.c_param_list))] ## cluster label for legend c_label = "Cluster "+str(c) self.ax.bar(y_pos + width*(c-(self.cluster_k/2.3)), cen, width, align="center", alpha=0.75, color=COLORS[c], ecolor="black", yerr=ystdev, label=c_label) self.ax.grid(True) #self.ax.set_xticklabels #self.ax.set_ylim(0, 1, emit=False) max_y_val = max(map(max, self.centroids)) self.ax.set_ylim(0, max_y_val+0.1, emit=False) self.ax.set_xticks(y_pos + width / 4) self.ax.set_xticklabels(self.c_param_list) self.ax.callbacks.connect('xlim_changed', self.handle_view_change) self.ax.callbacks.connect('ylim_changed', self.handle_view_change) ## add legend self.ax.legend(loc="upper right", shadow=True) self.canvas = FigureCanvasTkAgg(self.fig, self) ##type:FigureCanvasTkAgg #self.canvas.mpl_connect('motion_notify_event', self.handle_hover) #self.canvas.mpl_connect('button_press_event', self.handle_mouse_down) #self.canvas.mpl_connect('button_release_event', self.handle_mouse_up) #self.canvas.mpl_connect('pick_event', self.draw_tooltip) self.canvas.get_tk_widget().grid(column=1, row=3, sticky=(tk.N, tk.E, tk.W, tk.S)) # self.canvas_tb = NavigationToolbar2TkAgg(self.canvas, self.canvas.get_tk_widget()) #self.ctbwidget=tk.Frame(self) #self.ctbwidget.grid(column=1, row=4, sticky=(tk.N, tk.E, tk.W, tk.S)) #self.canvas_tb = NavigationToolbar2TkAgg(self.canvas, self.ctbwidget) util.zoom_factory(self.ax) self.fig.tight_layout(pad=0) self.canvas.draw() #print("DISTRIBUTIONS PLOTTED") #add an empty plot to the GUI def create_multiple_plots(self): self.clean_tooltip(True) self.fig = Figure(figsize=(5, 5), dpi=100) #type:Figure param_combos = [] subplot_num = 0 paraLen = len(self.c_param_list) axarr = [[]] dummy = [[]] sharey = {} for qi in range(0, paraLen): q = self.c_param_list[qi] #subplot_num = ((subplot_num%10)*10)+111 #print("subplot_num=",str(subplot_num)) for pi in range(0, paraLen): #print("qi =",str(qi)) p = self.c_param_list[pi] #subplot_num += 1 if pi < qi:#not p == q: subplot_num = (qi-1)*(paraLen-1) + (pi+1) print(subplot_num) #print("\tsubplot_num=",str(subplot_num)) param_combos.append((p,q)) x = self.df("clustered")[p] y = self.df("clustered")[q] print("pi=",str(pi),"qi=",str(qi)) #if qi>0 & pi>0: # self.ax = self.fig.add_subplot(paraLen-1, paraLen-1, subplot_num, sharex=axarr[0][pi-1], sharey=axarr[qi][0]) #if qi>1: # ax1 = self.fig.add_subplot(paraLen-1, paraLen-1, subplot_num, sharex=sharex[pi]) #if pi>1: # ax1 = self.fig.add_subplot(paraLen-1, paraLen-1, subplot_num, sharey=sharey[qi]) #else: ax1 = self.fig.add_subplot(paraLen-1, paraLen-1, subplot_num) #if pi==0: # print("add sharey for",str(qi)) # sharey[qi] = ax1 #print(self.centroids[1,0]) for i in range(self.cluster_k): one_value_cluster = self.df("clustered").loc[self.df("clustered")['clusterlabels'] == i] ax1.scatter(one_value_cluster[self.c_param_list[pi]], one_value_cluster[self.c_param_list[qi]], color=COLORS[i], marker=".", alpha=0.1, s=2) #print("i:",str(i),"pi:",str(pi),"qi:",str(qi)) ax1.plot(self.centroids[i][pi],self.centroids[i][qi],'kx') #self.plot=self.ax.scatter(x=x, y=y, marker="o", linewidths=0,picker=self.handle_pick) if qi == paraLen-1: paraLabel = p if "GRAIN_CLASS" in p: #custom class paraLabel = "CLASS"+p[-1] ax1.set_xlabel(paraLabel) else: ax1.set_xticklabels([]) if pi == 0: paraLabel = q if "GRAIN_CLASS" in q: #custom class paraLabel = "CLASS"+q[-1] ax1.set_ylabel(paraLabel) else: ax1.set_yticklabels([]) ax1.grid(True) ax1.set_xlim(x.min(), x.max(), emit=False) ax1.set_ylim(y.min(), y.max(), emit=False) #ax1.callbacks.connect('xlim_changed', self.handle_view_change) #ax1.callbacks.connect('ylim_changed', self.handle_view_change) #axarr[-1].append(ax1) #dummy[-1].append(0) #if pi == paraLen-1: # axarr.append([]) # dummy.append([]) #print(axarr) self.canvas = FigureCanvasTkAgg(self.fig, self) ##type:FigureCanvasTkAgg #self.canvas.mpl_connect('motion_notify_event', self.handle_hover) #self.canvas.mpl_connect('button_press_event', self.handle_mouse_down) #self.canvas.mpl_connect('button_release_event', self.handle_mouse_up) #self.canvas.mpl_connect('pick_event', self.draw_tooltip) self.canvas.get_tk_widget().grid(column=1, row=3, sticky=(tk.N, tk.E, tk.W, tk.S)) # self.canvas_tb = NavigationToolbar2TkAgg(self.canvas, self.canvas.get_tk_widget()) #self.ctbwidget=tk.Frame(self) #self.ctbwidget.grid(column=1, row=4, sticky=(tk.N, tk.E, tk.W, tk.S)) #self.canvas_tb = NavigationToolbar2TkAgg(self.canvas, self.ctbwidget) util.zoom_factory(self.ax) self.fig.tight_layout(pad=0) self.canvas.draw() ## update view with specified data def draw_plot(self): #ax.plot(self.df[self.param1], self.df[self.param2], marker="o", linewidth=0, picker=self.line_picker) self.clean_tooltip(True) self.ax.clear() self.ax.grid(True) x=self.ds.get_data("show").get_column(self.param1) y=self.ds.get_data("show").get_column(self.param2) #if self.param1 == datasource.TIME_ATTR or self.param2 == datasource.TIME_ATTR: # #self.plot=self.ax.plot(x, y,picker=self.handle_pick)#, marker="o", linewidths=0,picker=self.handle_pick) # self.plot = self.ax.scatter(x=x, y=y, picker=self.handle_pick) #else: self.plot=self.ax.scatter(x=x, y=y, marker="o",color="black", s=4, alpha=0.2,linewidths=0, picker=self.handle_pick) self.ax.set_xlabel(self.param1) self.ax.set_ylabel(self.param2) self.ax.set_xlim(x.min(), x.max(), emit=False) self.ax.set_ylim(y.min(), y.max(), emit=False) self.ax.callbacks.connect('xlim_changed', self.handle_view_change) self.ax.callbacks.connect('ylim_changed', self.handle_view_change) #self.canvas. self.fig.tight_layout(pad=0) if self.rgvar.get() is not "0" and not (self.param2 == datasource.TIME_ATTR): self.draw_regression() self.canvas.draw() def draw_regression(self): ## we need to remove rows with NaNs first completedf = self.df("show") completedf = completedf[pd.notnull(completedf[self.param1])] completedf = completedf[pd.notnull(completedf[self.param2])] if self.param1 == datasource.TIME_ATTR: completedf["delta_time"] = (completedf[datasource.TIME_ATTR] - completedf[datasource.TIME_ATTR].min()) / np.timedelta64(1, "m") X = completedf["delta_time"].to_frame() else: X = completedf[self.param1].to_frame() y = completedf[self.param2].to_frame() lr = LinearRegression() lr.fit(X,y) print(lr.coef_) if self.param1 == datasource.TIME_ATTR: self.ax.plot(completedf[datasource.TIME_ATTR], lr.predict(X), color="red") else: self.ax.plot(X, lr.predict(X), color="red") ################# # helper-functions def df(self, name=None) -> pd.DataFrame: return self.ds.get_data(name).df() ## add line to history window def add_to_history(self, text): self.history_text += "\n" + text if self.history_shown: self.history.insert('end', "\n" + text) # + "\n") self.history.see("end") ## remove the tooltip if shown def clean_tooltip(self, with_select_rect=False, emit=True): if self.plot_tooltip is not None: self.canvas.get_tk_widget().delete(self.plot_tooltip) self.canvas.get_tk_widget().delete(self.plot_tooltip_rect) self.plot_tooltip = None if with_select_rect and self.select_rect is not None: self.canvas.get_tk_widget().delete(self.select_rect) self.select_rect=None if emit: self.action_str = None self.trigger_update(self.TIMELINE_SELECTION) def trigger_update(self,level): self.unprocessed_action = max(self.unprocessed_action,level)
class BlackHoleGUI: """GUI controling a blackhole instance.""" def __init__(self, blackhole=None): """GUI controling a blackhole instance.""" if blackhole is None: self.blackhole = BlackHole() else: self.blackhole = blackhole self.create_interface() def create_interface(self): """Create the interface.""" root = Tk() frame = Frame(root) root.title("Black hole options") frame.pack() open_file_button = Button(frame, text="Open image", width=14, command=self.open_file_name) open_file_button.grid(row=0, column=0) L1 = Label(frame, text="radius") L1.grid(row=1, column=0) var = StringVar(root) var.set(self.blackhole.Rs) self.radius = Spinbox(frame, from_=1e-100, to=1e100, textvariable=var, bd=2, width=7) self.radius.grid(row=1, column=1) L2 = Label(frame, text="distance") L2.grid(row=2, column=0) var = StringVar(root) var.set(self.blackhole.D) self.distance = Spinbox(frame, from_=1e-100, to=1e100, textvariable=var, bd=2, width=7) self.distance.grid(row=2, column=1) compute_button = Button(frame, text="Compute", width=14, command=self.compute) compute_button.grid(row=1, column=2) self.message = Label(frame, text="", width=20) self.message.grid(row=1, column=3) self.message5 = Label(frame, text="", width=20) self.message5.grid(row=2, column=3) L3 = Label(frame, text="Image size") L3.grid(row=3, column=0) var = StringVar(root) var.set(self.blackhole.axe_X) self.size = Spinbox(frame, from_=1, to=1e100, textvariable=var, bd=2, width=7) self.size.grid(row=3, column=1) self.message2 = Label(frame, text="", width=20) self.message2.grid(row=3, column=3) save_button = Button(frame, text="Save image", width=14, command=self.img_save) save_button.grid(row=4, column=2) self.message4 = Label(frame, text="") self.message4.grid(row=4, column=3) message6 = Label(frame, text="Fix background") message6.grid(row=5, column=0) fixed_background = BooleanVar() C1 = Checkbutton(frame, text="", variable=fixed_background, onvalue=True, offvalue=False) C1.grid(row=5, column=1) L4 = Label(frame, text="images") L4.grid(row=6, column=0) var = StringVar(root) var.set(10) self.number = Spinbox(frame, from_=1, to=1e100, textvariable=var, bd=2, width=7) self.number.grid(row=6, column=1) save_gif_button = Button(frame, text="Save animation", width=14, command=self.save_gif) save_gif_button.grid(row=6, column=2) self.message3 = Label(frame, text="") self.message3.grid(row=6, column=3) root.mainloop() def compute(self): """Call the compute method of the blackhole instance.""" if not self.test_GUI(): return None self.reset_msg() try: if float(self.distance.get()) <= 0 or float(self.radius.get()) <= 0: self.message["text"] = "Can't be 0 or negative" return None elif (float(self.distance.get()) == self.blackhole.D and float(self.radius.get()) == self.blackhole.Rs and int(self.size.get()) == self.blackhole.axe_X and self.blackhole.img_matrix_x is not None): self.message["text"] = "same values as before" return None elif float(self.distance.get()) < float(self.radius.get()): self.message["text"] = "Inside black hole !" return None else: self.blackhole.D = float(self.distance.get()) self.blackhole.Rs = float(self.radius.get()) except ValueError: self.message["text"] = "radius, distance" self.message5["text"] = "& image size are floats" return None if self.blackhole.axe_X != int(self.size.get()): try: self.increase_resolution() except ValueError as ex: print(ex) return None self.message["text"] = "Computing" self.blackhole.compute(self.blackhole.Rs, self.blackhole.D) self.message["text"] = "Done !" def increase_resolution(self): """Increase the image size and correct offset and zoom to match the new size.""" if not self.test_GUI(): return None self.reset_msg() if int(self.size.get()) <= 0: self.message2["text"] = "Can't be 0 or negative" raise ValueError("Can't be 0 or negative") elif int(self.size.get()) == self.blackhole.axe_X: self.message2["text"] = "same size as before" else: # self.message2["text"] = "Computing" new_size_image = int(self.size.get()) self.blackhole.offset_X += self.blackhole.offset_X2 self.blackhole.offset_X2 = 0 res_fact = new_size_image/self.blackhole.axe_X self.blackhole.axe_X = new_size_image self.blackhole.offset_X *= res_fact self.blackhole.zoom *= res_fact try: self.blackhole.img_resize(self.blackhole.axe_X) self.blackhole.img_debut = img_offset_X( self.blackhole.img_debut, self.blackhole.offset_X) except ValueError as ex: print("error when resizing image") raise ValueError(ex) def img_save(self): """Save the image img2 with the parameters values. GUI version.""" if not self.test_GUI(): return None self.reset_msg() file_name, extension = return_folder_file_extension(self.blackhole.img_name)[1:] image_name_save = "%s_D=%s_Rs=%s_size=%s_offset=%i%s" % (file_name, self.blackhole.D, self.blackhole.Rs, self.blackhole.axe_X, self.blackhole.offset_X+self.blackhole.offset_X2, extension) if self.blackhole.img2 is not None: self.blackhole.img2.save(image_name_save) print("Saved "+image_name_save) self.message4["text"] = "Saved "+image_name_save else: self.message4["text"] = "No image to save" def save_gif(self): """Call the gif method if the blackhole instance.""" if not self.test_GUI(): return None self.reset_msg() file_name, extension = return_folder_file_extension(self.blackhole.img_name)[1:] if self.blackhole.img2 is not None: self.message3["text"] = "Computing" else: self.message3["text"] = "No image to save" return None try: if int(self.number.get()) <= 0: print("Can't be 0 or negative") self.message3["text"] = "Can't be 0 or negative" else: self.blackhole.gif(int(self.number.get())) image_name_save = "%s_D=%s_Rs=%s_size=%s_offset=%s%s" % (file_name, self.blackhole.D, self.blackhole.Rs, self.blackhole.axe_X, "*", extension) self.message3["text"] = "Saved "+image_name_save except Exception: print("need integer") self.message3["text"] = "need integer" def open_file_name(self): """Open a new image and aply the previous parameters. Compute a new black hole if parameters were changed. Source: https://gist.github.com/Yagisanatode/0d1baad4e3a871587ab1""" if not self.test_GUI(): return None self.reset_msg() img_name = askopenfilename( # initialdir="", filetypes=[("Image File", ".png .jpg")], title="Image file") if img_name: size = int(self.size.get()) self.blackhole.open(img_name, size=size) if self.blackhole.img_matrix_x is not None: if self.blackhole.axe_X != self.blackhole.img_matrix_x.shape[1]: self.blackhole.compute(self.blackhole.Rs, self.blackhole.D) self.blackhole.offset_X += self.blackhole.offset_X2 self.blackhole.offset_X2 = 0 self.blackhole.img_debut = img_offset_X( self.blackhole.img_debut, self.blackhole.offset_X) self.blackhole.img2 = self.blackhole.img_pixels(self.blackhole.img_debut) self.blackhole.plot() def reset_msg(self): """Reset all GUI messages.""" if not self.test_GUI(): return None self.message5["text"] = "" self.message4["text"] = "" self.message3["text"] = "" self.message2["text"] = "" self.message["text"] = "" def test_GUI(self): """Return True if the GUI is active and False otherwise.""" try: temp = self.message["text"] self.message["text"] = "" self.message["text"] = temp return True except Exception: print("The GUI is not openned, function ignored") return False
class OOP(): def __init__(self): # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") self.createWidgets() # Button callback def clickMe(self): self.action.configure(text='Hello ' + self.name.get()) # Button callback Clear Text def clearScrol(self): self.scr.delete('1.0', tk.END) # Spinbox callback def _spin(self): value = self.spin.get() print(value) self.scr.insert(tk.INSERT, value + '\n') # Checkbox callback def checkCallback(self, *ignoredArgs): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton callback function def radCall(self): radSel=self.radVar.get() if radSel == 0: self.monty2.configure(text='Blue') elif radSel == 1: self.monty2.configure(text='Gold') elif radSel == 2: self.monty2.configure(text='Red') # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() def usingGlobal(self): GLOBAL_CONST = 777 print(GLOBAL_CONST) ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='Tab 1') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Tab 2') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.monty = ttk.LabelFrame(tab1, text=' Mighty Python ') self.monty.grid(column=0, row=0, padx=8, pady=4) # Changing our Label ttk.Label(self.monty, text="Enter a name:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget self.name = tk.StringVar() nameEntered = ttk.Entry(self.monty, width=12, textvariable=self.name) nameEntered.grid(column=0, row=1, sticky='W') # Adding a Button self.action = ttk.Button(self.monty, text="Click Me!", command=self.clickMe) self.action.grid(column=2, row=1) ttk.Label(self.monty, text="Choose a number:").grid(column=1, row=0) number = tk.StringVar() numberChosen = ttk.Combobox(self.monty, width=12, textvariable=number) numberChosen['values'] = (1, 2, 4, 42, 100) numberChosen.grid(column=1, row=1) numberChosen.current(0) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.monty, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin) self.spin.grid(column=0, row=2) # Using a scrolled Text control scrolW = 30; scrolH = 3 self.scr = scrolledtext.ScrolledText(self.monty, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=3, sticky='WE', columnspan=3) #------------------------------------------------------------------------- # Adding another Button self.action = ttk.Button(self.monty, text="Clear Text", command=self.clearScrol) self.action.grid(column=2, row=2) # Tab Control 2 refactoring ----------------------------------------- # We are creating a container frame to hold all other widgets -- Tab2 self.monty2 = ttk.LabelFrame(tab2, text=' Holy Grail ') self.monty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(self.monty2, text="Disabled", variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.monty2, text="UnChecked", variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W ) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.monty2, text="Toggle", variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) self.chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) # ~ Tab Control 2 refactoring ----------------------------------------- # Radiobutton list colors = ["Blue", "Gold", "Red"] self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): curRad = 'rad' + str(col) curRad = tk.Radiobutton(self.monty2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips tt.createToolTip(curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.monty2, text=' Labels in a Frame ') labelsFrame.grid(column=0, row=7) # Place labels into the container element - vertically ttk.Label(labelsFrame, text="Label1").grid(column=0, row=0) ttk.Label(labelsFrame, text="Label2").grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=8) # Creating a Menu Bar menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label="New") fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self._quit) menuBar.add_cascade(label="File", menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About") menuBar.add_cascade(label="Help", menu=helpMenu) # Change the main windows icon self.win.iconbitmap('pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') print(strData.get()) # Default tkinter Variable Classes intData = tk.IntVar() print(intData.get()) print(tk.DoubleVar()) print(tk.BooleanVar()) # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() print("Hello " + strData) # Printing the Global works print(GLOBAL_CONST) # call method self.usingGlobal() # Place cursor into name Entry nameEntered.focus() # Add a Tooltip to the Spinbox tt.createToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets tt.createToolTip(nameEntered, 'This is an Entry control.') tt.createToolTip(self.action, 'This is a Button control.') tt.createToolTip(self.scr, 'This is a ScrolledText control.')
class Interface: """ GUI class """ def __init__(self, master): # colour swatches self.gray1 = "#f6f6f6" self.gray2 = "#eaeaea" self.gray3 = "#d9d9d9" # key parameters self.running = False self.sect_width = 360 self.rb_choice = StringVar() self.dob1_val = StringVar() self.dob2_val = StringVar() self.df_records = StringVar() master.geometry("800x600+200+200") master.title("Red Snapper") master.resizable(False, False) master.configure(background=self.gray1) # LEFT SECTION LAYER # -------------------------------------------------------------------- self.sect_left = Frame(master) self.sect_left.place(x=15, y=15, width=self.sect_width, height=570) self.sect_left.config(relief=RIDGE) self.sect_left.config(background=self.gray2) # RIGHT SECTION LAYER # -------------------------------------------------------------------- self.sect_right = Frame(master) self.sect_right.place(x=-15, y=200, width=self.sect_width, height=385) self.sect_right.place(relx=1.0, anchor="ne") self.sect_right.config(relief=RIDGE) self.sect_right.config(background=self.gray2) # Sliders layer self.layer_sliders = Frame(self.sect_left) self.layer_sliders.place(y=0, width=self.sect_width, height=320) self.layer_sliders.config(**self.layer_props(self.gray2)) self.lab_sliders = Label(self.layer_sliders) self.lab_sliders.config(**self.title_props("Parameters")) self.lab_sliders.pack() # DOB layer self.layer_dob = Frame(self.sect_left) self.layer_dob.place(y=320, width=self.sect_width, height=80) self.layer_dob.config(**self.layer_props(self.gray2)) self.lab_dob = Label(self.layer_dob) self.lab_dob.config(**self.title_props("Birthdays range")) self.lab_dob.pack() # Export layer self.layer_export = Frame(self.sect_left) self.layer_export.place(y=400, width=self.sect_width, height=80) self.layer_export.config(**self.layer_props(self.gray2)) self.lab_export = Label(self.layer_export) self.lab_export.config(**self.title_props("Export format")) self.lab_export.pack() # Run layer self.layer_run = Frame(self.sect_left) self.layer_run.place(y=480, width=self.sect_width, height=100) self.layer_run.config(**self.layer_props(self.gray2)) self.lab_run = Label(self.layer_run) self.lab_run.config(**self.title_props("Run")) self.lab_run.pack() # About layer self.layer_about = Frame(self.sect_right) self.layer_about.place(width=self.sect_width, height=385) self.layer_about.config(**self.layer_props(self.gray2)) self.lab_about = Label(self.layer_about) self.lab_about.config(**self.title_props("About Red Snapper")) self.lab_about.pack() # sliders self.sli_wom = Scale(self.layer_sliders, from_=0, to=100) self.sli_wom.config(**self.sli_props()) self.sli_wom.config(label="Percentage of women in dataset.") self.sli_wom.pack(padx=20, pady=10) self.sli_wom.set(50) self.sli_nam = Scale(self.layer_sliders, from_=0, to=100) self.sli_nam.config(**self.sli_props()) self.sli_nam.config(label="Percentage of people with double name") self.sli_nam.pack(padx=20, pady=0) self.sli_nam.set(25) self.sli_sur = Scale(self.layer_sliders, from_=0, to=100) self.sli_sur.config(**self.sli_props()) self.sli_sur.config(label="Percentage of people with double surname") self.sli_sur.pack(padx=20, pady=10) self.sli_sur.set(15) # DOB Layer - From Date self.dob1_val.set("1945") self.lab_dob1 = Label(self.layer_dob, text="From date") self.lab_dob1.config(**self.label_props()) self.lab_dob1.pack(side=LEFT, padx=5) self.box_dob1 = Spinbox(self.layer_dob) self.box_dob1.config(from_=1945, to=1996, textvariable=self.dob1_val) self.box_dob1.config(**self.date_props()) self.box_dob1.pack(side=LEFT) # DOB Layer - To Date self.dob2_val.set("1997") self.lab_dob2 = Label(self.layer_dob, text="To date") self.lab_dob2.config(**self.label_props()) self.lab_dob2.pack(side=LEFT, padx=17) self.box_dob2 = Spinbox(self.layer_dob) self.box_dob2.config(from_=1946, to=1997, textvariable=self.dob2_val) self.box_dob2.config(**self.date_props()) self.box_dob2.pack(side=LEFT) # Export layer - JSON / CSV radio buttons self.rb_choice.set("CSV") self.rb1 = Radiobutton(self.layer_export, text="Save as CSV", variable=self.rb_choice, value="CSV") self.rb1.config(**self.radio_props()) self.rb1.place(y=35, x=50) self.rb2 = Radiobutton(self.layer_export, text="Save as JSON", variable=self.rb_choice, value="JSON") self.rb2.config(**self.radio_props()) self.rb2.place(y=35, x=200) # Run layer - no of records spinbox self.df_records.set("100") self.box_gen = Spinbox(self.layer_run) self.box_gen.config(from_=1, to=999999, textvariable=self.df_records) self.box_gen.config(increment=1000, width=19) self.box_gen.place(x=70, y=53) self.lab_gen = Label(self.layer_run, text="Number of records") self.lab_gen.config(**self.label_props()) self.lab_gen.place(x=70, y=30) # Run layer - generate button self.btn_run = ttk.Button(self.layer_run) self.btn_run.place(x=225, y=35, height=40) self.btn_run_reset() # header & logo section self.sect_logo = Frame(master) self.sect_logo.place(x=-15, y=30, width=350, height=120) self.sect_logo.place(relx=1.0, anchor="ne") self.logo = PhotoImage(file="./redsnapper/interface/logo.png") self.lab_logo = Label(self.sect_logo, image=self.logo) self.lab_logo.config(background=self.gray1) self.lab_logo.pack() # About box_about = Text(self.layer_about) box_about.config(**self.text_props()) box_about.pack(pady=10, padx=10) txt = """This program allows generating thousands of rows filled with pseudo-random data. """ \ + """\nThe generated records (like name, """ \ + """ surname, date of birth, e-mail address) can be used to provide sample data to: - test query performance of your database - practice data operations with BI tools.""" \ + """ \nThe application uses 4 processes to generate data simultaneously. """ \ + """ It takes about 25 seconds to create 1 million rows of data.\n""" box_about.insert(END, txt) # styling wrapped into functions for reusability def sli_props(self): """ bundle popular attributes of TK control so they can be reused :return: dict of bundled props """ return { "length": 300, "orient": HORIZONTAL, "sliderrelief": FLAT, "showvalue": 1, "resolution": 1, "sliderlength": 25, "tickinterval": 100, "font": ("Arial", 8), "activebackground": "#333333", "background": "#666666", "troughcolor": "#d0d4d2", "foreground": "#eeeeee", "highlightthickness": 8, "highlightcolor": "#ffffff", "highlightbackground": self.gray3, "borderwidth": 1 } @staticmethod def layer_props(bgcolor): """ bundle popular attributes of TK control so they can be reused :return: dict of bundled props """ return {"relief": RIDGE, "background": bgcolor} def title_props(self, title): """ bundle popular attributes of TK control so they can be reused :return: dict of bundled props """ return { "text": title, "background": self.gray3, "width": self.sect_width, "borderwidth": 1, "relief": RIDGE } def radio_props(self): """ bundle popular attributes of TK control so they can be reused :return: dict of bundled props """ return { "background": self.gray2, "activebackground": self.gray2, } def date_props(self): """ bundle popular attributes of TK control so they can be reused :return: dict of bundled props """ return { "width": 8, "increment": 1, "font": ("Arial", 8), "background": "#666666", "buttonbackground": "#666666", "foreground": "#eeeeee", "highlightthickness": 8, "highlightcolor": "#ffffff", "highlightbackground": self.gray2, "borderwidth": 1 } def label_props(self): """ bundle popular attributes of TK control so they can be reused :return: dict of bundled props """ return { "background": self.gray2, "highlightcolor": "#ffffff", "highlightbackground": self.gray2, "borderwidth": 1 } def text_props(self): """ bundle popular attributes of TK control so they can be reused :return: dict of bundled props """ return { "font": ("Arial", 11), "background": self.gray1, "foreground": "#212121", "highlightthickness": 8, "highlightbackground": self.gray1, "highlightcolor": self.gray1, "borderwidth": 0, "wrap": "word", "spacing1": 11, "spacing2": 7, } def produce_props(self): """ produce dict of key GUI parameters selected by user :return: no return parameters """ rows = int(self.box_gen.get()) props = { "pgender": self.sli_wom.get(), "pdname": self.sli_nam.get(), "pdsurname": self.sli_sur.get(), "dob1": self.box_dob1.get(), "dob2": self.box_dob2.get(), } dataset = Dataset().run_workload(rows, **props) exp_format = self.rb_choice.get() if exp_format == "CSV": Export().to_csv(dataset) else: Export().to_json(dataset) self.btn_run_reset() return def btn_run_reset(self): """ abort button (when generating) :return: no return parameters """ self.running = False self.btn_run.config(text="Generate", command=self.btn_run_start) return def btn_run_start(self): """ handle the run button :return: no return parameters """ self.running = True newthread = threading.Thread(target=self.produce_props) newthread.start() self.btn_run.config(text="Abort", command=self.btn_run_reset) return
class OOP(): def __init__(self, language='en'): # Create instance self.win = tk.Tk() self.i18n = I18N(language) # self.i18n = I18N(language) # Add a title self.win.title(self.i18n.title) # Callback methods now in different module self.callBacks = Callbacks(self) # Disable resizing the window self.win.resizable(0, 0) # Create a Queue self.guiQueue = Queue() self.createWidgets() # populate Tab 2 Entries self.callBacks.defaultFileEntries() # create MySQL instance self.mySQL = MySQL() # create Logger instance fullPath = path.realpath(__file__) self.log = Logger(fullPath) # create Log Level instance self.level = LogLevel() ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab # tabControl.add(tab1, text='MySQL') # Add the tab -- COMMENTED OUT FOR CH08 tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Widgets') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.mySQL = ttk.LabelFrame(tab1, text=' Python Database ') self.mySQL.grid(column=0, row=0, padx=8, pady=4) # Creating a Label ttk.Label(self.mySQL, text="Book Title:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget book = tk.StringVar() self.bookTitle = ttk.Entry(self.mySQL, width=34, textvariable=book) self.bookTitle.grid(column=0, row=1, sticky='W') # Adding a Textbox Entry widget book1 = tk.StringVar() self.bookTitle1 = ttk.Entry(self.mySQL, width=34, textvariable=book1) self.bookTitle1.grid(column=0, row=2, sticky='W') # Adding a Textbox Entry widget book2 = tk.StringVar() self.bookTitle2 = ttk.Entry(self.mySQL, width=34, textvariable=book2) self.bookTitle2.grid(column=0, row=3, sticky='W') # Creating a Label ttk.Label(self.mySQL, text="Page:").grid(column=1, row=0, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber.grid(column=1, row=1, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber1 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber1.grid(column=1, row=2, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber2 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber2.grid(column=1, row=3, sticky='W') # Adding a Button self.action = ttk.Button(self.mySQL, text="Insert Quote", command=self.callBacks.insertQuote) self.action.grid(column=2, row=1) # Adding a Button self.action1 = ttk.Button(self.mySQL, text="Get Quotes", command=self.callBacks.getQuote) self.action1.grid(column=2, row=2) # Adding a Button self.action2 = ttk.Button(self.mySQL, text="Mody Quote", command=self.callBacks.modifyQuote) self.action2.grid(column=2, row=3) # Add some space around each widget for child in self.mySQL.winfo_children(): child.grid_configure(padx=2, pady=4) quoteFrame = ttk.LabelFrame(tab1, text=' Book Quotation ') quoteFrame.grid(column=0, row=1, padx=8, pady=4) # Using a scrolled Text control quoteW = 40 quoteH = 6 self.quote = scrolledtext.ScrolledText(quoteFrame, width=quoteW, height=quoteH, wrap=tk.WORD) self.quote.grid(column=0, row=8, sticky='WE', columnspan=3) # Add some space around each widget for child in quoteFrame.winfo_children(): child.grid_configure(padx=2, pady=4) #====================================================================================================== # Tab Control 2 #====================================================================================================== # We are creating a container frame to hold all other widgets -- Tab2 self.widgetFrame = ttk.LabelFrame(tab2, text=self.i18n.WIDGET_LABEL) self.widgetFrame.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons self.chVarDis = tk.IntVar() self.check1 = tk.Checkbutton(self.widgetFrame, text=self.i18n.disabled, variable=self.chVarDis, state='disabled') self.check1.select() self.check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.widgetFrame, text=self.i18n.unChecked, variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.widgetFrame, text=self.i18n.toggle, variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace( 'w', lambda unused0, unused1, unused2: self.checkCallback()) self.chVarEn.trace( 'w', lambda unused0, unused1, unused2: self.checkCallback()) # Radiobutton list colors = self.i18n.colors self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): self.curRad = 'rad' + str(col) self.curRad = tk.Radiobutton(self.widgetFrame, text=colors[col], variable=self.radVar, value=col, command=self.callBacks.radCall) self.curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips tt.createToolTip(self.curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.widgetFrame, text=self.i18n.labelsFrame) labelsFrame.grid(column=0, row=7, pady=6) # Place labels into the container element - vertically ttk.Label(labelsFrame, text=self.i18n.chooseNumber).grid(column=0, row=0) self.lbl2 = tk.StringVar() self.lbl2.set(self.i18n.label2) ttk.Label(labelsFrame, textvariable=self.lbl2).grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=6, pady=1) number = tk.StringVar() self.combo = ttk.Combobox(self.widgetFrame, width=12, textvariable=number) self.combo['values'] = (1, 2, 4, 42, 100) self.combo.grid(column=1, row=7, sticky=tk.W) self.combo.current(0) self.combo.bind('<<ComboboxSelected>>', self.callBacks._combo) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.widgetFrame, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self.callBacks._spin) self.spin.grid(column=2, row=7, sticky='W,', padx=6, pady=1) # Using a scrolled Text control scrolW = 40 scrolH = 1 self.scr = scrolledtext.ScrolledText(self.widgetFrame, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=8, sticky='WE', columnspan=3) # Adding a TZ Button self.allTZs = ttk.Button(self.widgetFrame, text=self.i18n.timeZones, command=self.callBacks.allTimeZones) self.allTZs.grid(column=0, row=9, sticky='WE') # Adding local TZ Button self.localTZ = ttk.Button(self.widgetFrame, text=self.i18n.localZone, command=self.callBacks.localZone) self.localTZ.grid(column=1, row=9, sticky='WE') # Adding getTime TZ Button self.dt = ttk.Button(self.widgetFrame, text=self.i18n.getTime, command=self.callBacks.getDateTime) self.dt.grid(column=2, row=9, sticky='WE') # Create Manage Files Frame ------------------------------------------------ mngFilesFrame = ttk.LabelFrame(tab2, text=self.i18n.mgrFiles) mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print(fName) self.fileEntry.config(state='enabled') self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) if len(fName) > self.entryLen: self.fileEntry.config(width=len(fName) + 3) # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text=self.i18n.browseTo, command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) #----------------------------------------------------- file = tk.StringVar() self.entryLen = scrolW - 4 self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.grid(column=1, row=0, sticky=tk.W) #----------------------------------------------------- logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() file = src.split('/')[-1] dst = self.netwEntry.get() + '\\' + file try: shutil.copy(src, dst) mBox.showinfo('Copy File to Network', 'Succes: File copied.') except FileNotFoundError as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as ex: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex)) cb = ttk.Button(mngFilesFrame, text=self.i18n.copyTo, command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) # Creating a Menu Bar ========================================================== menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label=self.i18n.new) fileMenu.add_separator() fileMenu.add_command(label=self.i18n.exit, command=self.callBacks._quit) menuBar.add_cascade(label=self.i18n.file, menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label=self.i18n.about) menuBar.add_cascade(label=self.i18n.help, menu=helpMenu) # Change the main windows icon self.win.iconbitmap(r'C:\Python34\DLLs\pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() # Place cursor into name Entry self.bookTitle.focus() # Add a Tooltip to the Spinbox tt.createToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets tt.createToolTip(self.bookTitle, 'This is an Entry control.') tt.createToolTip(self.action, 'This is a Button control.') tt.createToolTip(self.scr, 'This is a ScrolledText control.')
class OOP(): def __init__(self): # Initializer method # Create instance self.win = tk.Tk() tt.create_ToolTip(self.win, 'Hello GUI') # Add a title self.win.title("Python GUI") self.create_widgets() self.defaultFileEntries() self.guiQueue = Queue() def defaultFileEntries(self): self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fDir) if len(fDir) > self.entryLen: self.fileEntry.config(width=len(fDir) + 3) # Readonly would make it impossible to change to the actual file we # want to copy # self.fileEntry.config(state='readonly') self.netwEntry.delete(0, tk.END) self.netwEntry.insert(0, netDir) if len(netDir) > self.entryLen: self.netwEntry.config(width=len(netDir) + 3) def useQueues(self): self.guiQueue = Queue() for idx in range(10): self.guiQueue.put('Message from a queue' + str(idx)) while True: print(self.guiQueue.get()) def methodInAThread(self, numOfLoops=10): for idx in range(numOfLoops): sleep(1) self.scr.insert(tk.INSERT, str(idx) + '\n') sleep(1) print('methodInAThread():', self.runT.isAlive()) # textBoxes are the Consumers of Queue data writeT = Thread(target=self.useQueues, daemon=True) writeT.start() # Running methods in Threads def createThread(self, num): self.runT = Thread(target=self.methodInAThread, args=[num]) self.runT.setDaemon(True) self.runT.start() print(self.runT) print('createThread():', self.runT.isAlive()) # textBoxes are the consumers of queue data writeT = Thread(target=self.useQueues, daemon=True) writeT.start() # Create Queue instance def useQueues(self): print(self.guiQueue) while True: print(self.guiQueue.get()) # Modified Button Click Function def click_me(self): # Passing in the current class instance (self) print(self) bq.writeToScrol(self) # Spinbox callback def _spin(self): value = self.spin.get() print(value) self.scr.insert(tk.INSERT, value + '\n') # GUI Callback def checkCallback(self, *ignored_args): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton Callback def radCall(self): radSel = self.radVar.get() if radSel == 0: self.mighty2.configure(text='Blue') elif radSel == 1: self.mighty2.configure(text='Gold') elif radSel == 2: self.mighty2.configure(text='Red') # update progressbar in callback loop def run_progressbar(self): self.progress_bar["maximum"] = 100 for i in range(101): sleep(0.05) self.progress_bar["value"] = i # increment progressbar self.progress_bar.update() # have to call update() in loop self.progress_bar["value"] = 0 # reset/clear progressbar def start_progressbar(self): self.progress_bar.start() def stop_progressbar(self): self.progress_bar.stop() def progressbar_stop_after(self, wait_ms=1000): self.win.after(wait_ms, self.progress_bar.stop) def usingGlobal(self): global GLOBAL_CONST print(GLOBAL_CONST) GLOBAL_CONST = 777 print(GLOBAL_CONST) # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() ##################################################################################### def create_widgets(self): tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='Tab 1') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Tab 2') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # LabelFrame using tab1 as the parent mighty = ttk.LabelFrame(tab1, text=' Mighty Python ') mighty.grid(column=0, row=0, padx=8, pady=4) # Modify adding a Label using mighty as the parent instead of win a_label = ttk.Label(mighty, text="Enter a name:") a_label.grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget self.name = tk.StringVar() name_entered = ttk.Entry(mighty, width=24, textvariable=self.name) name_entered.grid(column=0, row=1, sticky='W') # Adding a Button self.action = ttk.Button(mighty, text="Click Me!", command=self.click_me) self.action.grid(column=2, row=1) ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) number = tk.StringVar() self.number_chosen = ttk.Combobox(mighty, width=14, textvariable=number, state='readonly') self.number_chosen['values'] = (1, 2, 4, 42, 100) self.number_chosen.grid(column=1, row=1) self.number_chosen.current(0) # Adding a Spinbox widget self.spin = Spinbox(mighty, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin) # using range self.spin.grid(column=0, row=2, sticky='W') # Using a scrolled Text control scrol_w = 40 scrol_h = 10 self.scr = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) self.scr.grid(column=0, row=3, sticky='WE', columnspan=3) # Tab Control 2 ---------------------------------------------------------------------- # We are creating a container frame to hold all other widgets -- Tab2 self.mighty2 = ttk.LabelFrame(tab2, text=' The Snake ') self.mighty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(self.mighty2, text="Disabled", variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=0, sticky=tk.W) chVarUn = tk.IntVar() check2 = tk.Checkbutton(self.mighty2, text="UnChecked", variable=chVarUn) check2.deselect() check2.grid(column=1, row=0, sticky=tk.W) chVarEn = tk.IntVar() check3 = tk.Checkbutton(self.mighty2, text="Enabled", variable=chVarEn) check3.deselect() check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) # First, we change our Radiobutton global variables into a list colors = ["Blue", "Gold", "Red"] # create three Radiobuttons using one variable self.radVar = tk.IntVar() # Next we are selecting a non-existing index value for radVar self.radVar.set(99) # Now we are creating all three Radiobutton widgets within one loop for col in range(3): curRad = tk.Radiobutton(self.mighty2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=1, sticky=tk.W) # row=6 # Add a Progressbar to Tab 2 self.progress_bar = ttk.Progressbar(tab2, orient='horizontal', length=286, mode='determinate') self.progress_bar.grid(column=0, row=3, pady=2) # Create a container to hold buttons buttons_frame = ttk.LabelFrame(self.mighty2, text=' ProgressBar ') buttons_frame.grid(column=0, row=2, sticky='W', columnspan=2) # Add Buttons for Progressbar commands ttk.Button(buttons_frame, text=" Run Progressbar ", command=self.run_progressbar).grid(column=0, row=0, sticky='W') ttk.Button(buttons_frame, text=" Start Progressbar ", command=self.start_progressbar).grid(column=0, row=1, sticky='W') ttk.Button(buttons_frame, text=" Stop immediately ", command=self.stop_progressbar).grid(column=0, row=2, sticky='W') ttk.Button(buttons_frame, text=" Stop after second ", command=self.progressbar_stop_after).grid(column=0, row=3, sticky='W') for child in buttons_frame.winfo_children(): child.grid_configure(padx=2, pady=2) for child in self.mighty2.winfo_children(): child.grid_configure(padx=8, pady=2) # Creating a Menu Bar menu_bar = Menu(self.win) self.win.config(menu=menu_bar) # Add menu items file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label="New") file_menu.add_separator() file_menu.add_command(label="Exit", command=self._quit) menu_bar.add_cascade(label="File", menu=file_menu) ############################################################################ # Create Manage Files Frame mngFilesFrame = ttk.LabelFrame(tab2, text=' Manage Files: ') mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') # fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print("fName: " + fName) self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) self.fileEntry.config(width=len(fName) + 3) # self.fileEntry.config(state='readonly') # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text="Browse to File...", command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) file = tk.StringVar() self.entryLen = scrol_w self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.bind("<Return>", (lambda event: copyFile())) self.fileEntry.grid(column=1, row=0, sticky=tk.W) logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() if len(src.split('/')) > 2: file = src.split('/')[-1] else: file = src.split("\\")[-1] dst = self.netwEntry.get() + '\\' + file try: shutil.copy(src, dst) mBox.showinfo('Copy File to Network', 'Success: File copied') except FileNotFoundError as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) cb = ttk.Button(mngFilesFrame, text="Copy File To : ", command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) ########################################################################### # Display a Message Box def _msgBox(): msg.showinfo('Python Message Info Box', 'A Python GUI created using tkinter:\nThe year is 2017.') # Add another Menu to the Menu Bar and an item help_menu = Menu(menu_bar, tearoff=0) help_menu.add_command(label="About", command=_msgBox) # display messagebox when clicked menu_bar.add_cascade(label="Help", menu=help_menu) # Change the main windows icon # self.win.iconbitmap('pyc.ico') # It is not necessary to create a tk.StringVar() # strData = tk.StringVar() strData = self.spin.get() print("Spinbox value: " + strData) # call function self.usingGlobal() #name_entered.focus() tabControl.select(1)
win.iconbitmap(r'C:\Python34\DLLs\pyc.ico') # Using tkinter Variable Classes # strData = tk.StringVar() # strData.set('Hello StringVar') # print(strData.get()) # Default tkinter Variable Classes # intData = tk.IntVar() # print(intData.get()) # print(tk.DoubleVar()) # print(tk.BooleanVar()) # It is not necessary to create a tk.StringVar() # strData = tk.StringVar() strData = spin.get() # print("Hello " + strData) # Printing the Global works # print(GLOBAL_CONST) def usingGlobal(): GLOBAL_CONST = 777 # print(GLOBAL_CONST) global GLOBAL_CONST print(GLOBAL_CONST) # call function usingGlobal() # Place cursor into name Entry
class OOP(): def __init__(self): # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") # Disable resizing the window self.win.resizable(0, 0) # Create a Queue self.guiQueue = Queue() self.createWidgets() # populate Tab 2 Entries self.defaultFileEntries() # Start TCP/IP server in its own thread svrT = Thread(target=startServer, daemon=True) svrT.start() def defaultFileEntries(self): # populate Entry before making it read-only #self.fileEntry.config(state='readonly') self.fileEntry.delete(0, tk.END) #self.fileEntry.insert(0, fDir) self.fileEntry.insert(0, 'Z:\\') # bogus path # if len(fDir) > self.entryLen: # self.fileEntry.config(width=len(fDir) + 3) self.fileEntry.config(state='readonly') self.netwEntry.delete(0, tk.END) #self.netwEntry.insert(0, netDir) self.netwEntry.insert(0, 'Z:\\Backup') # bogus path # if len(netDir) > self.entryLen: # self.netwEntry.config(width=len(netDir) + 3) # Button callback def clickMe(self): self.action.configure(text='Hello ' + self.name.get()) # # Non-threaded code with sleep freezes the GUI # for idx in range(10): # sleep(5) # self.scr.insert(tk.INSERT, str(idx) + '\n') # # Threaded method does not freeze our GUI # self.createThread() # Passing in the current class instance (self) print(self) bq.writeToScrol(self) sleep(2) htmlData = url.getHtml() print(htmlData) self.scr.insert(tk.INSERT, htmlData) # Spinbox callback def _spin(self): value = self.spin.get() #print(value) self.scr.insert(tk.INSERT, value + '\n') # Checkbox callback def checkCallback(self, *ignoredArgs): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton callback function def radCall(self): radSel = self.radVar.get() if radSel == 0: self.monty2.configure(text='Blue') elif radSel == 1: self.monty2.configure(text='Gold') elif radSel == 2: self.monty2.configure(text='Red') # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() def methodInAThread(self): print('Hi, how are you?') # for idx in range(10): # sleep(5) # self.scr.insert(tk.INSERT, str(idx) + '\n') # def methodInAThread(self, numOfLoops=10): # for idx in range(numOfLoops): # sleep(1) # self.scr.insert(tk.INSERT, str(idx) + '\n') # sleep(1) # print('methodInAThread():', self.runT.isAlive()) # Running methods in Threads def createThread(self, num): self.runT = Thread(target=self.methodInAThread, args=[num]) self.runT.setDaemon(True) self.runT.start() print(self.runT) print('createThread():', self.runT.isAlive()) # textBoxes are the Consumers of Queue data writeT = Thread(target=self.useQueues, daemon=True) writeT.start() # Create Queue instance def useQueues(self): # guiQueue = Queue() # print(guiQueue) # for idx in range(10): # guiQueue.put('Message from a queue: ' + str(idx)) # while True: # print(guiQueue.get()) # Now using a class member Queue while True: qItem = self.guiQueue.get() print(qItem) self.scr.insert(tk.INSERT, qItem + '\n') ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='Tab 1') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Tab 2') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.monty = ttk.LabelFrame(tab1, text=' Monty Python ') self.monty.grid(column=0, row=0, padx=8, pady=4) # Changing our Label ttk.Label(self.monty, text="Enter a name:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget self.name = tk.StringVar() nameEntered = ttk.Entry(self.monty, width=24, textvariable=self.name) nameEntered.grid(column=0, row=1, sticky='W') nameEntered.delete(0, tk.END) nameEntered.insert(0, '< default name >') # Adding a Button self.action = ttk.Button(self.monty, text="Click Me!", command=self.clickMe) self.action.grid(column=2, row=1) ttk.Label(self.monty, text="Choose a number:").grid(column=1, row=0) number = tk.StringVar() numberChosen = ttk.Combobox(self.monty, width=14, textvariable=number) numberChosen['values'] = (1, 2, 4, 42, 100) numberChosen.grid(column=1, row=1) numberChosen.current(0) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.monty, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin) self.spin.grid(column=0, row=2, sticky='W') # Using a scrolled Text control scrolW = 40 scrolH = 10 self.scr = scrolledtext.ScrolledText(self.monty, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=3, sticky='WE', columnspan=3) # Tab Control 2 refactoring --------------------------------------------------- # We are creating a container frame to hold all other widgets -- Tab2 self.monty2 = ttk.LabelFrame(tab2, text=' The Snake ') self.monty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(self.monty2, text="Disabled", variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.monty2, text="UnChecked", variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.monty2, text="Toggle", variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace( 'w', lambda unused0, unused1, unused2: self.checkCallback()) self.chVarEn.trace( 'w', lambda unused0, unused1, unused2: self.checkCallback()) # ~ Tab Control 2 refactoring ----------------------------------------- # Radiobutton list colors = ["Blue", "Gold", "Red"] self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): curRad = 'rad' + str(col) curRad = tk.Radiobutton(self.monty2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips tt.createToolTip(curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.monty2, text=' Labels in a Frame ') labelsFrame.grid(column=0, row=7) # Place labels into the container element - vertically ttk.Label(labelsFrame, text="Label1").grid(column=0, row=0) ttk.Label(labelsFrame, text="Label2").grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=8) # Create Manage Files Frame ------------------------------------------------ mngFilesFrame = ttk.LabelFrame(tab2, text=' Manage Files: ') mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print(fName) self.fileEntry.config(state='enabled') self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) if len(fName) > self.entryLen: self.fileEntry.config(width=len(fName) + 3) # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text="Browse to File...", command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) #----------------------------------------------------- file = tk.StringVar() self.entryLen = scrolW - 4 self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.grid(column=1, row=0, sticky=tk.W) #----------------------------------------------------- logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() file = src.split('/')[-1] dst = self.netwEntry.get() + '\\' + file try: shutil.copy(src, dst) mBox.showinfo('Copy File to Network', 'Succes: File copied.') except FileNotFoundError as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as ex: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex)) cb = ttk.Button(mngFilesFrame, text="Copy File To : ", command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) # Creating a Menu Bar ========================================================== menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label="New") fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self._quit) menuBar.add_cascade(label="File", menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About") menuBar.add_cascade(label="Help", menu=helpMenu) # Change the main windows icon self.win.iconbitmap(r'C:\Python34\DLLs\pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() # Place cursor into name Entry # nameEntered.focus() # Set focus to Tab 2 tabControl.select(1) # Add a Tooltip to the Spinbox tt.createToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets tt.createToolTip(nameEntered, 'This is an Entry control.') tt.createToolTip(self.action, 'This is a Button control.') tt.createToolTip(self.scr, 'This is a ScrolledText control.')
class OOP(): def __init__(self): # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") # Disable resizing the window self.win.resizable(0,0) # Create a Queue self.guiQueue = Queue() self.createWidgets() # populate Tab 2 Entries self.defaultFileEntries() # Start TCP/IP server in its own thread svrT = Thread(target=startServer, daemon=True) svrT.start() def defaultFileEntries(self): # populate Entry before making it read-only #self.fileEntry.config(state='readonly') self.fileEntry.delete(0, tk.END) #self.fileEntry.insert(0, fDir) self.fileEntry.insert(0, 'Z:\\') # bogus path # if len(fDir) > self.entryLen: # self.fileEntry.config(width=len(fDir) + 3) self.fileEntry.config(state='readonly') self.netwEntry.delete(0, tk.END) #self.netwEntry.insert(0, netDir) self.netwEntry.insert(0, 'Z:\\Backup') # bogus path # if len(netDir) > self.entryLen: # self.netwEntry.config(width=len(netDir) + 3) # Button callback def clickMe(self): self.action.configure(text='Hello ' + self.name.get()) # # Non-threaded code with sleep freezes the GUI # for idx in range(10): # sleep(5) # self.scr.insert(tk.INSERT, str(idx) + '\n') # # Threaded method does not freeze our GUI # self.createThread() # Passing in the current class instance (self) print(self) bq.writeToScrol(self) sleep(2) htmlData = url.getHtml() print(htmlData) self.scr.insert(tk.INSERT, htmlData) # Spinbox callback def _spin(self): value = self.spin.get() #print(value) self.scr.insert(tk.INSERT, value + '\n') # Checkbox callback def checkCallback(self, *ignoredArgs): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton callback function def radCall(self): radSel=self.radVar.get() if radSel == 0: self.monty2.configure(text='Blue') elif radSel == 1: self.monty2.configure(text='Gold') elif radSel == 2: self.monty2.configure(text='Red') # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() def methodInAThread(self): print('Hi, how are you?') # for idx in range(10): # sleep(5) # self.scr.insert(tk.INSERT, str(idx) + '\n') # def methodInAThread(self, numOfLoops=10): # for idx in range(numOfLoops): # sleep(1) # self.scr.insert(tk.INSERT, str(idx) + '\n') # sleep(1) # print('methodInAThread():', self.runT.isAlive()) # Running methods in Threads def createThread(self, num): self.runT = Thread(target=self.methodInAThread, args=[num]) self.runT.setDaemon(True) self.runT.start() print(self.runT) print('createThread():', self.runT.isAlive()) # textBoxes are the Consumers of Queue data writeT = Thread(target=self.useQueues, daemon=True) writeT.start() # Create Queue instance def useQueues(self): # guiQueue = Queue() # print(guiQueue) # for idx in range(10): # guiQueue.put('Message from a queue: ' + str(idx)) # while True: # print(guiQueue.get()) # Now using a class member Queue while True: qItem = self.guiQueue.get() print(qItem) self.scr.insert(tk.INSERT, qItem + '\n') ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='Tab 1') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Tab 2') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.monty = ttk.LabelFrame(tab1, text=' Monty Python ') self.monty.grid(column=0, row=0, padx=8, pady=4) # Changing our Label ttk.Label(self.monty, text="Enter a name:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget self.name = tk.StringVar() nameEntered = ttk.Entry(self.monty, width=24, textvariable=self.name) nameEntered.grid(column=0, row=1, sticky='W') nameEntered.delete(0, tk.END) nameEntered.insert(0, '< default name >') # Adding a Button self.action = ttk.Button(self.monty, text="Click Me!", command=self.clickMe) self.action.grid(column=2, row=1) ttk.Label(self.monty, text="Choose a number:").grid(column=1, row=0) number = tk.StringVar() numberChosen = ttk.Combobox(self.monty, width=14, textvariable=number) numberChosen['values'] = (1, 2, 4, 42, 100) numberChosen.grid(column=1, row=1) numberChosen.current(0) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.monty, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin) self.spin.grid(column=0, row=2, sticky='W') # Using a scrolled Text control scrolW = 40; scrolH = 10 self.scr = scrolledtext.ScrolledText(self.monty, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=3, sticky='WE', columnspan=3) # Tab Control 2 refactoring --------------------------------------------------- # We are creating a container frame to hold all other widgets -- Tab2 self.monty2 = ttk.LabelFrame(tab2, text=' The Snake ') self.monty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(self.monty2, text="Disabled", variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.monty2, text="UnChecked", variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W ) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.monty2, text="Toggle", variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) self.chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) # ~ Tab Control 2 refactoring ----------------------------------------- # Radiobutton list colors = ["Blue", "Gold", "Red"] self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): curRad = 'rad' + str(col) curRad = tk.Radiobutton(self.monty2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips tt.createToolTip(curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.monty2, text=' Labels in a Frame ') labelsFrame.grid(column=0, row=7) # Place labels into the container element - vertically ttk.Label(labelsFrame, text="Label1").grid(column=0, row=0) ttk.Label(labelsFrame, text="Label2").grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=8) # Create Manage Files Frame ------------------------------------------------ mngFilesFrame = ttk.LabelFrame(tab2, text=' Manage Files: ') mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print(fName) self.fileEntry.config(state='enabled') self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) if len(fName) > self.entryLen: self.fileEntry.config(width=len(fName) + 3) # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text="Browse to File...", command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) #----------------------------------------------------- file = tk.StringVar() self.entryLen = scrolW - 4 self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.grid(column=1, row=0, sticky=tk.W) #----------------------------------------------------- logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() file = src.split('/')[-1] dst = self.netwEntry.get() + '\\'+ file try: shutil.copy(src, dst) mBox.showinfo('Copy File to Network', 'Succes: File copied.') except FileNotFoundError as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as ex: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex)) cb = ttk.Button(mngFilesFrame, text="Copy File To : ", command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) # Creating a Menu Bar ========================================================== menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label="New") fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self._quit) menuBar.add_cascade(label="File", menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About") menuBar.add_cascade(label="Help", menu=helpMenu) # Change the main windows icon self.win.iconbitmap(r'C:\Python34\DLLs\pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() # Place cursor into name Entry # nameEntered.focus() # Set focus to Tab 2 tabControl.select(1) # Add a Tooltip to the Spinbox tt.createToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets tt.createToolTip(nameEntered, 'This is an Entry control.') tt.createToolTip(self.action, 'This is a Button control.') tt.createToolTip(self.scr, 'This is a ScrolledText control.')
# Add menu items file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label="New") file_menu.add_separator() file_menu.add_command(label="Exit", command=_quit) menu_bar.add_cascade(label="File", menu=file_menu) # Display a Message Box def _msgBox(): msg.showinfo('Python Message Info Box', 'A Python GUI created using tkinter:\nThe year is 2017.') # Add another Menu to the Menu Bar and an item help_menu = Menu(menu_bar, tearoff=0) help_menu.add_command(label="About", command=_msgBox) # display messagebox when clicked menu_bar.add_cascade(label="Help", menu=help_menu) # Change the main windows icon win.iconbitmap('pyc.ico') # It is not necessary to create a tk.StringVar() # strData = tk.StringVar() strData = spin.get() print("Spinbox value: " + strData) name_entered.focus() # Place cursor into name Entry #====================== # Start GUI #====================== win.mainloop()
class OOP(): def __init__(self): # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") # Disable resizing the window self.win.resizable(0,0) # Create a Queue self.guiQueue = Queue() self.createWidgets() # populate Tab 2 Entries self.defaultFileEntries() # create MySQL instance self.mySQL = MySQL() def defaultFileEntries(self): self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, 'Z:\\') # bogus path self.fileEntry.config(state='readonly') self.netwEntry.delete(0, tk.END) self.netwEntry.insert(0, 'Z:\\Backup') # bogus path # Combobox callback def _combo(self, val=0): value = self.combo.get() self.scr.insert(tk.INSERT, value + '\n') # Spinbox callback def _spin(self): value = self.spin.get() self.scr.insert(tk.INSERT, value + '\n') # Checkbox callback def checkCallback(self, *ignoredArgs): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton callback function def radCall(self): radSel=self.radVar.get() if radSel == 0: self.mySQL2.configure(text=WIDGET_LABEL + 'in Blue') elif radSel == 1: self.mySQL2.configure(text=WIDGET_LABEL + 'in Gold') elif radSel == 2: self.mySQL2.configure(text=WIDGET_LABEL + 'in Red') # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() def methodInAThread(self, numOfLoops=10): for idx in range(numOfLoops): sleep(1) self.scr.insert(tk.INSERT, str(idx) + '\n') sleep(1) print('methodInAThread():', self.runT.isAlive()) # Running methods in Threads def createThread(self, num): self.runT = Thread(target=self.methodInAThread, args=[num]) self.runT.setDaemon(True) self.runT.start() print(self.runT) print('createThread():', self.runT.isAlive()) # textBoxes are the Consumers of Queue data writeT = Thread(target=self.useQueues, daemon=True) writeT.start() # Create Queue instance def useQueues(self): # Now using a class member Queue while True: qItem = self.guiQueue.get() print(qItem) self.scr.insert(tk.INSERT, qItem + '\n') # Button callback def insertQuote(self): title = self.bookTitle.get() page = self.pageNumber.get() quote = self.quote.get(1.0, tk.END) print(title) print(quote) self.mySQL.insertBooks(title, page, quote) # Button callback def getQuote(self): allBooks = self.mySQL.showBooks() print(allBooks) self.quote.insert(tk.INSERT, allBooks) # Button callback def modifyQuote(self): raise NotImplementedError("This still needs to be implemented for the SQL command.") ##################################################################################### def createWidgets(self): # Tab Control introduced here -------------------------------------- tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='MySQL') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Widgets') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # ~ Tab Control introduced here ----------------------------------------- # We are creating a container frame to hold all other widgets self.mySQL = ttk.LabelFrame(tab1, text=' Python Database ') self.mySQL.grid(column=0, row=0, padx=8, pady=4) # Creating a Label ttk.Label(self.mySQL, text="Book Title:").grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget book = tk.StringVar() self.bookTitle = ttk.Entry(self.mySQL, width=34, textvariable=book) self.bookTitle.grid(column=0, row=1, sticky='W') # Adding a Textbox Entry widget book1 = tk.StringVar() self.bookTitle1 = ttk.Entry(self.mySQL, width=34, textvariable=book1) self.bookTitle1.grid(column=0, row=2, sticky='W') # Adding a Textbox Entry widget book2 = tk.StringVar() self.bookTitle2 = ttk.Entry(self.mySQL, width=34, textvariable=book2) self.bookTitle2.grid(column=0, row=3, sticky='W') # Creating a Label ttk.Label(self.mySQL, text="Page:").grid(column=1, row=0, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber.grid(column=1, row=1, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber1 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber1.grid(column=1, row=2, sticky='W') # Adding a Textbox Entry widget page = tk.StringVar() self.pageNumber2 = ttk.Entry(self.mySQL, width=6, textvariable=page) self.pageNumber2.grid(column=1, row=3, sticky='W') # Adding a Button self.action = ttk.Button(self.mySQL, text="Insert Quote", command=self.insertQuote) self.action.grid(column=2, row=1) # Adding a Button self.action1 = ttk.Button(self.mySQL, text="Get Quotes", command=self.getQuote) self.action1.grid(column=2, row=2) # Adding a Button self.action2 = ttk.Button(self.mySQL, text="Mody Quote", command=self.modifyQuote) self.action2.grid(column=2, row=3) # Add some space around each widget for child in self.mySQL.winfo_children(): child.grid_configure(padx=2, pady=4) quoteFrame = ttk.LabelFrame(tab1, text=' Book Quotation ') quoteFrame.grid(column=0, row=1, padx=8, pady=4) # Using a scrolled Text control quoteW = 40; quoteH = 6 self.quote = scrolledtext.ScrolledText(quoteFrame, width=quoteW, height=quoteH, wrap=tk.WORD) self.quote.grid(column=0, row=8, sticky='WE', columnspan=3) # Add some space around each widget for child in quoteFrame.winfo_children(): child.grid_configure(padx=2, pady=4) #====================================================================================================== # Tab Control 2 #====================================================================================================== # We are creating a container frame to hold all other widgets -- Tab2 self.mySQL2 = ttk.LabelFrame(tab2, text=WIDGET_LABEL) self.mySQL2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons self.chVarDis = tk.IntVar() self.check1 = tk.Checkbutton(self.mySQL2, text="Disabled", variable=self.chVarDis, state='disabled') self.check1.select() self.check1.grid(column=0, row=0, sticky=tk.W) self.chVarUn = tk.IntVar() self.check2 = tk.Checkbutton(self.mySQL2, text="UnChecked", variable=self.chVarUn) self.check2.deselect() self.check2.grid(column=1, row=0, sticky=tk.W ) self.chVarEn = tk.IntVar() self.check3 = tk.Checkbutton(self.mySQL2, text="Toggle", variable=self.chVarEn) self.check3.deselect() self.check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons self.chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) self.chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) # Radiobutton list colors = ["Blue", "Gold", "Red"] self.radVar = tk.IntVar() # Selecting a non-existing index value for radVar self.radVar.set(99) # Creating all three Radiobutton widgets within one loop for col in range(3): curRad = 'rad' + str(col) curRad = tk.Radiobutton(self.mySQL2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=6, sticky=tk.W, columnspan=3) # And now adding tooltips tt.createToolTip(curRad, 'This is a Radiobutton control.') # Create a container to hold labels labelsFrame = ttk.LabelFrame(self.mySQL2, text=' Labels within a Frame ') labelsFrame.grid(column=0, row=7, pady=6) # Place labels into the container element - vertically ttk.Label(labelsFrame, text="Choose a number:").grid(column=0, row=0) ttk.Label(labelsFrame, text="Label 2").grid(column=0, row=1) # Add some space around each label for child in labelsFrame.winfo_children(): child.grid_configure(padx=6, pady=1) number = tk.StringVar() self.combo = ttk.Combobox(self.mySQL2, width=12, textvariable=number) self.combo['values'] = (1, 2, 4, 42, 100) self.combo.grid(column=1, row=7, sticky=tk.W) self.combo.current(0) self.combo.bind('<<ComboboxSelected>>', self._combo) # Adding a Spinbox widget using a set of values self.spin = Spinbox(self.mySQL2, values=(1, 2, 4, 42, 100), width=5, bd=8, command=self._spin) self.spin.grid(column=2, row=7, sticky='W,', padx=6, pady=1) # Using a scrolled Text control scrolW = 40; scrolH = 1 self.scr = scrolledtext.ScrolledText(self.mySQL2, width=scrolW, height=scrolH, wrap=tk.WORD) self.scr.grid(column=0, row=8, sticky='WE', columnspan=3) # Create Manage Files Frame ------------------------------------------------ mngFilesFrame = ttk.LabelFrame(tab2, text=' Manage Files: ') mngFilesFrame.grid(column=0, row=1, sticky='WE', padx=10, pady=5) # Button Callback def getFileName(): print('hello from getFileName') fDir = path.dirname(__file__) fName = fd.askopenfilename(parent=self.win, initialdir=fDir) print(fName) self.fileEntry.config(state='enabled') self.fileEntry.delete(0, tk.END) self.fileEntry.insert(0, fName) if len(fName) > self.entryLen: self.fileEntry.config(width=len(fName) + 3) # Add Widgets to Manage Files Frame lb = ttk.Button(mngFilesFrame, text="Browse to File...", command=getFileName) lb.grid(column=0, row=0, sticky=tk.W) #----------------------------------------------------- file = tk.StringVar() self.entryLen = scrolW - 4 self.fileEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=file) self.fileEntry.grid(column=1, row=0, sticky=tk.W) #----------------------------------------------------- logDir = tk.StringVar() self.netwEntry = ttk.Entry(mngFilesFrame, width=self.entryLen, textvariable=logDir) self.netwEntry.grid(column=1, row=1, sticky=tk.W) def copyFile(): import shutil src = self.fileEntry.get() file = src.split('/')[-1] dst = self.netwEntry.get() + '\\'+ file try: shutil.copy(src, dst) mBox.showinfo('Copy File to Network', 'Succes: File copied.') except FileNotFoundError as err: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(err)) except Exception as ex: mBox.showerror('Copy File to Network', '*** Failed to copy file! ***\n\n' + str(ex)) cb = ttk.Button(mngFilesFrame, text="Copy File To : ", command=copyFile) cb.grid(column=0, row=1, sticky=tk.E) # Add some space around each label for child in mngFilesFrame.winfo_children(): child.grid_configure(padx=6, pady=6) # Creating a Menu Bar ========================================================== menuBar = Menu(tab1) self.win.config(menu=menuBar) # Add menu items fileMenu = Menu(menuBar, tearoff=0) fileMenu.add_command(label="New") fileMenu.add_separator() fileMenu.add_command(label="Exit", command=self._quit) menuBar.add_cascade(label="File", menu=fileMenu) # Add another Menu to the Menu Bar and an item helpMenu = Menu(menuBar, tearoff=0) helpMenu.add_command(label="About") menuBar.add_cascade(label="Help", menu=helpMenu) # Change the main windows icon self.win.iconbitmap(r'C:\Python34\DLLs\pyc.ico') # Using tkinter Variable Classes strData = tk.StringVar() strData.set('Hello StringVar') # It is not necessary to create a tk.StringVar() strData = tk.StringVar() strData = self.spin.get() # Place cursor into name Entry self.bookTitle.focus() # Add a Tooltip to the Spinbox tt.createToolTip(self.spin, 'This is a Spin control.') # Add Tooltips to more widgets tt.createToolTip(self.bookTitle, 'This is an Entry control.') tt.createToolTip(self.action, 'This is a Button control.') tt.createToolTip(self.scr, 'This is a ScrolledText control.')
class OOP(): def __init__(self): # Initializer method # Create instance self.win = tk.Tk() # Add a title self.win.title("Python GUI") self.create_widgets() # Create Queue instance def use_queues(self, loops=5): gui_queue = Queue() print(gui_queue) for idx in range(loops): gui_queue.put('Message from a queue: ' + str(idx)) while True: print(gui_queue.get()) def method_in_a_thread(self, num_of_loops=10): for idx in range(num_of_loops): sleep(1) self.scrol.insert(tk.INSERT, str(idx) + '\n') # Running methods in Threads def create_thread(self, num=1): self.run_thread = Thread(target=self.method_in_a_thread, args=[num]) self.run_thread.setDaemon(True) self.run_thread.start() # start queue in its own thread write_thread = Thread(target=self.use_queues, args=[num], daemon=True) write_thread.start() # Button callback def click_me(self): self.action.configure(text='Hello ' + self.name.get()) print(self) # self.create_thread() # now called from imported module bq.write_to_scrol(self) # Spinbox callback def _spin(self): value = self.spin.get() self.scrol.insert(tk.INSERT, value + '\n') # GUI Callback def checkCallback(self, *ignored_args): # only enable one checkbutton if self.chVarUn.get(): self.check3.configure(state='disabled') else: self.check3.configure(state='normal') if self.chVarEn.get(): self.check2.configure(state='disabled') else: self.check2.configure(state='normal') # Radiobutton Callback def radCall(self): radSel = self.radVar.get() if radSel == 0: self.mighty2.configure(text='Blue') elif radSel == 1: self.mighty2.configure(text='Gold') elif radSel == 2: self.mighty2.configure(text='Red') # update progressbar in callback loop def run_progressbar(self): self.progress_bar["maximum"] = 100 for i in range(101): sleep(0.05) self.progress_bar["value"] = i # increment progressbar self.progress_bar.update() # have to call update() in loop self.progress_bar["value"] = 0 # reset/clear progressbar def start_progressbar(self): self.progress_bar.start() def stop_progressbar(self): self.progress_bar.stop() def progressbar_stop_after(self, wait_ms=1000): self.win.after(wait_ms, self.progress_bar.stop) def usingGlobal(self): global GLOBAL_CONST GLOBAL_CONST = 777 # Exit GUI cleanly def _quit(self): self.win.quit() self.win.destroy() exit() ##################################################################################### def create_widgets(self): tabControl = ttk.Notebook(self.win) # Create Tab Control tab1 = ttk.Frame(tabControl) # Create a tab tabControl.add(tab1, text='Tab 1') # Add the tab tab2 = ttk.Frame(tabControl) # Add a second tab tabControl.add(tab2, text='Tab 2') # Make second tab visible tabControl.pack(expand=1, fill="both") # Pack to make visible # LabelFrame using tab1 as the parent mighty = ttk.LabelFrame(tab1, text=' Mighty Python ') mighty.grid(column=0, row=0, padx=8, pady=4) # Modify adding a Label using mighty as the parent instead of win a_label = ttk.Label(mighty, text="Enter a name:") a_label.grid(column=0, row=0, sticky='W') # Adding a Textbox Entry widget self.name = tk.StringVar() self.name_entered = ttk.Entry(mighty, width=24, textvariable=self.name) self.name_entered.grid(column=0, row=1, sticky='W') # Adding a Button self.action = ttk.Button(mighty, text="Click Me!", command=self.click_me) self.action.grid(column=2, row=1) ttk.Label(mighty, text="Choose a number:").grid(column=1, row=0) number = tk.StringVar() self.number_chosen = ttk.Combobox(mighty, width=14, textvariable=number, state='readonly') self.number_chosen['values'] = (1, 2, 4, 42, 100) self.number_chosen.grid(column=1, row=1) self.number_chosen.current(0) # Adding a Spinbox widget self.spin = Spinbox(mighty, values=(1, 2, 4, 42, 100), width=5, bd=9, command=self._spin) # using range self.spin.grid(column=0, row=2, sticky='W') # align left # Using a scrolled Text control scrol_w = 40; scrol_h = 10 # increase sizes self.scrol = scrolledtext.ScrolledText(mighty, width=scrol_w, height=scrol_h, wrap=tk.WORD) self.scrol.grid(column=0, row=3, sticky='WE', columnspan=3) for child in mighty.winfo_children(): # add spacing to align widgets within tabs child.grid_configure(padx=4, pady=2) #===================================================================================== # Tab Control 2 ---------------------------------------------------------------------- self.mighty2 = ttk.LabelFrame(tab2, text=' The Snake ') self.mighty2.grid(column=0, row=0, padx=8, pady=4) # Creating three checkbuttons chVarDis = tk.IntVar() check1 = tk.Checkbutton(self.mighty2, text="Disabled", variable=chVarDis, state='disabled') check1.select() check1.grid(column=0, row=0, sticky=tk.W) chVarUn = tk.IntVar() check2 = tk.Checkbutton(self.mighty2, text="UnChecked", variable=chVarUn) check2.deselect() check2.grid(column=1, row=0, sticky=tk.W) chVarEn = tk.IntVar() check3 = tk.Checkbutton(self.mighty2, text="Enabled", variable=chVarEn) check3.deselect() check3.grid(column=2, row=0, sticky=tk.W) # trace the state of the two checkbuttons chVarUn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) chVarEn.trace('w', lambda unused0, unused1, unused2 : self.checkCallback()) # First, we change our Radiobutton global variables into a list colors = ["Blue", "Gold", "Red"] # create three Radiobuttons using one variable self.radVar = tk.IntVar() # Next we are selecting a non-existing index value for radVar self.radVar.set(99) # Now we are creating all three Radiobutton widgets within one loop for col in range(3): curRad = tk.Radiobutton(self.mighty2, text=colors[col], variable=self.radVar, value=col, command=self.radCall) curRad.grid(column=col, row=1, sticky=tk.W) # row=6 # And now adding tooltips ToolTip(curRad, 'This is a Radiobutton control') # Add a Progressbar to Tab 2 self.progress_bar = ttk.Progressbar(tab2, orient='horizontal', length=286, mode='determinate') self.progress_bar.grid(column=0, row=3, pady=2) # Create a container to hold buttons buttons_frame = ttk.LabelFrame(self.mighty2, text=' ProgressBar ') buttons_frame.grid(column=0, row=2, sticky='W', columnspan=2) # Add Buttons for Progressbar commands ttk.Button(buttons_frame, text=" Run Progressbar ", command=self.run_progressbar).grid(column=0, row=0, sticky='W') ttk.Button(buttons_frame, text=" Start Progressbar ", command=self.start_progressbar).grid(column=0, row=1, sticky='W') ttk.Button(buttons_frame, text=" Stop immediately ", command=self.stop_progressbar).grid(column=0, row=2, sticky='W') ttk.Button(buttons_frame, text=" Stop after second ", command=self.progressbar_stop_after).grid(column=0, row=3, sticky='W') for child in buttons_frame.winfo_children(): child.grid_configure(padx=2, pady=2) for child in self.mighty2.winfo_children(): child.grid_configure(padx=8, pady=2) # Creating a Menu Bar menu_bar = Menu(self.win) self.win.config(menu=menu_bar) # Add menu items file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label="New") file_menu.add_separator() file_menu.add_command(label="Exit", command=self._quit) menu_bar.add_cascade(label="File", menu=file_menu) # Display a Message Box def _msgBox(): msg.showinfo('Python Message Info Box', 'A Python GUI created using tkinter:\nThe year is 2019.') # Add another Menu to the Menu Bar and an item help_menu = Menu(menu_bar, tearoff=0) help_menu.add_command(label="About", command=_msgBox) # display messagebox when clicked menu_bar.add_cascade(label="Help", menu=help_menu) # Change the main windows icon self.win.iconbitmap('pyc.ico') # It is not necessary to create a tk.StringVar() # strData = tk.StringVar() strData = self.spin.get() # call function self.usingGlobal() self.name_entered.focus() # Add Tooltips ----------------------------------------------------- # Add a Tooltip to the Spinbox ToolTip(self.spin, 'This is a Spinbox control') # Add Tooltips to more widgets ToolTip(self.name_entered, 'This is an Entry control') ToolTip(self.action, 'This is a Button control') ToolTip(self.scrol, 'This is a ScrolledText control')
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("") #self.style = Style() #self.style.theme_use("clam") #self.pack(fill=BOTH, expand = 1) self.labelU = Label(self, text="U:") self.labelP = Label(self, text="P:") self.mailrecipient = 'GoldenSights' self.entryUsername = Entry(self) self.entryUsername.focus_set() self.entryUsername.bind('<Return>', lambda event: self.entryPassword.focus_set()) self.entryPassword = Entry(self) self.entryPassword.config(show='•') self.entryPassword.bind('<Return>', lambda event: self.login(self.entryUsername.get(), self.entryPassword.get())) self.newbutton = Button(self, text="Login", command= lambda: self.login(self.entryUsername.get(), self.entryPassword.get())) self.newbutton.bind('<Return>', lambda event: self.login(self.entryUsername.get(), self.entryPassword.get())) self.newbutton.config(width=6) self.quitbutton = Button(self, text="Quit", command= lambda: self.quit()) self.quitbutton.config(width=6) self.labelU.grid(row=0, column=0,padx=0) self.entryUsername.grid(row=0, column=1) self.labelP.grid(row=1, column=0) self.entryPassword.grid(row=1, column=1, pady=4) self.newbutton.grid(row=2, column=1) self.quitbutton.grid(row=3, column=1, pady=4) self.labelErrorPointer = Label(self, text="◀") self.indicatorGreen = PhotoImage(file="indicatorGreen.gif") self.indicatorRed = PhotoImage(file="indicatorRed.gif") self.indicatorBlue = PhotoImage(file="indicatorBlue.gif") self.indicatorBlack = PhotoImage(file="indicatorBlack.gif") sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() w=400 h=480 x = (sw - w) / 2 y = (sh - h) / 2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y-50)) def login(self, username, password): print('U: ' + username) self.username = username if username == '' or not all(char in string.ascii_letters+string.digits+'_-' for char in username): print('Please enter a username') self.entryUsername.focus_set() self.labelErrorPointer.grid(row=0, column=2) elif password == '': print('Please enter a password') self.entryPassword.focus_set() self.labelErrorPointer.grid(row=1, column=2) else: self.labelErrorPointer.grid_forget() print('Attempting login for ' + username) try: self.USERAGENT = username + ' practices Tkinter+PRAW mixing with utility by /u/GoldenSights.' self.r = praw.Reddit(self.USERAGENT) #self.r.login(username, password) print('Success') self.labelU.grid_forget() self.labelP.grid_forget() self.entryUsername.grid_forget() self.entryPassword.grid_forget() self.newbutton.grid_forget() self.quitbutton.grid_forget() self.usernamelabel = Label(self, text=username + ', Sending to /u/' + self.mailrecipient) self.usernamelabel.grid(row=0, column=0, columnspan=8) self.quitbutton.grid(row=900, column=0) self.labellist = [] self.entrylist = [] self.verifylist = [] self.misclist = [] self.optionDiscuss = "Discussion Flair + Crossposting" self.optionRegister = "Register a new Candidate" self.prevmode = self.optionDiscuss self.curmode = self.optionDiscuss self.optionvar = tkinter.StringVar(self) self.optionvar.trace("w",self.permaloop) self.optionvar.set(self.optionDiscuss) self.option = OptionMenu(self, self.optionvar, self.optionDiscuss, self.optionRegister, "three", "four") self.newbutton.unbind("<Return>") self.entryUsername.unbind("<Return>") self.entryPassword.unbind("<Return>") self.option.grid(row=1,column=0,columnspan=8,pady=8) self.updategui(True) except praw.errors.InvalidUserPass: pass print('Invalid username or password') self.entryPassword.delete(0,200) self.labelErrorPointer.grid(row=1, column=2) def permaloop(self, *args): self.curmode = self.optionvar.get() print('Was: ' + self.prevmode + ' | Now: ' + self.curmode) if self.curmode != self.prevmode: self.prevmode = self.curmode self.updategui(True) def updategui(self, *args): if args[0] == True: print('Cleaning GUI') for item in self.labellist: item.grid_forget() for item in self.entrylist: item.grid_forget() for item in self.verifylist: item.grid_forget() for item in self.misclist: item.grid_forget() self.labellist = [] self.entrylist = [] self.verifylist = [] self.misclist = [] if self.curmode == self.optionDiscuss: self.newrowindex = 4 self.labelPermalink = Label(self, text="Thread Permalink:") self.entryPermalink = Entry(self) self.rowconfigure(2,weight=2) self.labelPermalink.grid(row=2,column=0) self.entryPermalink.grid(row=2,column=1) self.labelcrossposting = Label(self,text="Crosspost to:") self.labelcrossposting.grid(row=3,column=0,columnspan=2,sticky="w") for m in range(5): self.redditlabel = Label(self,text="/r/") self.redditlabel.grid(row=self.newrowindex,column=0, sticky="e") self.labellist.append(self.redditlabel) self.redditentry = Entry(self) self.redditentry.grid(row=self.newrowindex,column=1) self.entrylist.append(self.redditentry) self.newrowindex +=1 self.morerowbutton = Button(self,text="+row",command=lambda: self.morerows('/r/', 0, 1, 20)) self.morerowbutton.grid(row=898,column=0,columnspan=2) self.verifybutton = Button(self,text="Verify",command= lambda: self.updategui(False)) self.verifybutton.grid(row=899,column=0,columnspan=2) self.newrowindex += 2 self.misclist.append(self.labelPermalink) self.misclist.append(self.labelcrossposting) self.misclist.append(self.entryPermalink) self.misclist.append(self.morerowbutton) self.misclist.append(self.verifybutton) if self.curmode == self.optionRegister: self.newrowindex = 6 self.labelCanUsername = Label(self, text="Candidate's Username: /u/") self.entryCanUsername = Entry(self) self.labelCanRealname = Label(self, text="Candidate's Realname:") self.entryCanRealname = Entry(self) self.labelCanFlair = Label(self, text="Candidate's Flair:") self.entryCanFlair = Entry(self) self.entryMo = Spinbox(self, width=9, values=('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')) self.entryDa = Spinbox(self, width=2, from_=1, to=31) self.entryYr = Spinbox(self, width=4, from_=2014, to=2500) self.labelHH = Label(self, text="Schedule time UTC:") self.entryHH = Spinbox(self, from_=0, to=23, width=2) self.entryMM = Spinbox(self, from_=0, to=59, width=2) self.entryYr.delete(0,'end') self.entryYr.insert(0,2014) self.morerowbutton = Button(self,text="+question",command=lambda: self.morerows('Q:', 0, 1, 25)) self.morerowbutton.grid(row=898,column=0,columnspan=8) self.verifybutton = Button(self,text="Verify",command= lambda: self.updategui(False)) self.verifybutton.grid(row=899,column=0,columnspan=8) self.misclist.append(self.labelCanUsername) self.misclist.append(self.labelCanRealname) self.misclist.append(self.entryCanUsername) self.misclist.append(self.entryCanRealname) self.misclist.append(self.labelHH) self.misclist.append(self.entryHH) self.misclist.append(self.entryMM) self.misclist.append(self.entryMo) self.misclist.append(self.entryDa) self.misclist.append(self.entryYr) self.labelCanUsername.grid(row=2, column=0, sticky="e") self.labelCanRealname.grid(row=3, column=0, sticky="e") self.entryCanUsername.grid(row=2, column=1, columnspan=3) self.entryCanRealname.grid(row=3, column=1, columnspan=3) self.entryMo.grid(row=4, column=1,sticky="e") self.entryDa.grid(row=4, column=2) self.entryYr.grid(row=4, column=3) self.labelHH.grid(row=4, column=0, sticky="se", pady=5) self.entryHH.grid(row=5, column=1, sticky="e") self.entryMM.grid(row=5, column=2, sticky="w") else: if self.curmode == self.optionDiscuss: verifies = [] i = self.entryPermalink.get() if len(i) == 6: pid = i else: if 'www.reddit.com/r/' in i and '/comments/' in i: pid = i.split('/comments/')[1].split('/')[0] if 'http://redd.it/' in i: pid = i.split('redd.it/')[1] for flag in self.verifylist: flag.grid_forget() self.verifylist.remove(flag) try: print('Fetching Submission ' + pid) self.r.get_info(thing_id="t3_" + pid).title + 'Check' self.redditlabel = Label(self, image=self.indicatorGreen) self.redditlabel.grid(row=2,column=2) self.verifylist.append(self.redditlabel) verifies.append(True) print('\tSuccess') except: print('Failed. Make sure to include the http://. Copy and paste straight from your browser for best result') self.redditlabel = Label(self, image=self.indicatorRed) self.redditlabel.grid(row=2,column=2) self.verifylist.append(self.redditlabel) verifies.append(False) for entry in self.entrylist: i = entry.get() if i != '': print('Fetching /r/' + i) if all(char in string.ascii_letters+string.digits+'_-' for char in i): try: sub = self.r.get_subreddit(i,fetch=True) self.redditlabel = Label(self, image=self.indicatorGreen) self.redditlabel.grid(row=entry.grid_info()['row'],column=2) self.verifylist.append(self.redditlabel) verifies.append(True) print('\tSuccess') except: self.redditlabel = Label(self, image=self.indicatorRed) self.redditlabel.grid(row=entry.grid_info()['row'],column=2) self.verifylist.append(self.redditlabel) verifies.append(False) print('\tFailed') time.sleep(2) else: self.redditlabel = Label(self, image=self.indicatorRed) self.redditlabel.grid(row=entry.grid_info()['row'],column=2) self.verifylist.append(self.redditlabel) verifies.append(False) print('\tFailed') print(verifies) if self.curmode == self.optionRegister: verifies = [] u=self.entryCanUsername.get() print('Fetching /u/' + u) if not all(char in string.ascii_letters+string.digits+'_-' for char in u): self.redditlabel = Label(self, image=self.indicatorRed) self.redditlabel.grid(row=2, column=4) self.verifylist.append(self.redditlabel) verifies.append(False) print('\tBad characterage') else: try: u = self.r.get_redditor(u) print(u) self.redditlabel = Label(self, image=self.indicatorGreen) self.redditlabel.grid(row=2,column=4) self.verifylist.append(self.redditlabel) verifies.append(True) print('\tSuccess') except: self.redditlabel = Label(self, image=self.indicatorRed) self.redditlabel.grid(row=2,column=4) self.verifylist.append(self.redditlabel) verifies.append(False) print('\tFailed') try: print('Checking Time') t = self.entryMo.get() + ' ' + self.entryDa.get() + ' ' + self.entryYr.get() + ' ' + self.entryHH.get() + ':' + self.entryMM.get() plandate = datetime.datetime.strptime(t, "%B %d %Y %H:%M") plandate = datetime.datetime.utcfromtimestamp(plandate.timestamp()) print('\t' + str(plandate.timestamp())) self.redditlabel = Label(self, image=self.indicatorGreen) self.redditlabel.grid(row=5,column=3) self.verifylist.append(self.redditlabel) verifies.append(True) except: print('\tFailed') self.redditlabel = Label(self, image=self.indicatorRed) self.redditlabel.grid(row=5,column=3) self.verifylist.append(self.redditlabel) verifies.append(False) print(verifies) def morerows(self, label, columnm, columnn, limit, *args): self.redditlabel = Label(self,text=label) self.redditlabel.grid(row=self.newrowindex,column=columnm, sticky="e") self.labellist.append(self.redditlabel) self.redditentry = Entry(self) self.redditentry.grid(row=self.newrowindex,column=columnn, columnspan=8) self.entrylist.append(self.redditentry) self.newrowindex += 1 if self.newrowindex >= limit: self.morerowbutton.grid_forget() print(self.newrowindex)
class GUI(): def __init__(self): self.root = Tk( className='Программа для удаление подписей из электронных писем') self.root.geometry("1000x600") self.root.wm_resizable(False, False) self.panelFrame = LabelFrame(self.root, height=100, text="") self.panelFrame.pack(side='top', fill='x') self.labelLogin = Label(self.panelFrame, text="Адрес почты: ") self.labelLogin.place(x=10, y=40) self.loginField = Entry(self.panelFrame, width=20) self.loginField.place(x=100, y=40) self.labelPassword = Label(self.panelFrame, text="Пароль: ") self.labelPassword.place(x=280, y=40) self.passwordField = Entry(self.panelFrame, show="*", width=15) self.passwordField.place(x=340, y=40) self.labelLogin = Label( self.panelFrame, text="Порядковый номер письма \nв папке 'входящие': ") self.labelLogin.place(x=490, y=30) self.sb = Spinbox(self.panelFrame, from_=1, to=10000) self.sb.place(x=690, y=40, width=50) self.buttonDeleteSing = Button(self.panelFrame, text="Удалить подпись", command=self._delete_signature) self.buttonDeleteSing.place(x=770, y=15, width=200) self.buttonInfo = Button(self.panelFrame, text="Помощь") self.buttonInfo.place(x=770, y=45, width=200) self.buttonInfo.bind('<ButtonRelease-1>', GUI._show_info) self.textFrame1 = LabelFrame(self.root, width=500, text='Исходный текст письма') self.textFrame1.pack(fill='y', side='left') self.textbox1 = Text(self.textFrame1, font='Arial 12', wrap='word') self.textbox1.pack(side='left', fill='both') self.textbox1.place(width=490) self.textFrame2 = LabelFrame(self.root, width=500, text='Текст без подписи') self.textFrame2.pack(fill='y', side='right') self.textbox2 = Text(self.textFrame2, font='Arial 12', wrap='word') self.textbox2.pack(side='left', fill='both') self.textbox2.place(width=490) def _show_messagebox(self, messageType, message): if messageType == 'error': messagebox.showerror('Ошибка', message) elif messageType == 'warning': messagebox.showwarning('Предупреждение', message) else: messagebox.showinfo('Info', message) def _delete_signature(self): address = self.loginField.get() password = self.passwordField.get() index = int(self.sb.get()) try: original, without_sign = SignatureRemover.delete_signature( address, password, index) except EmailException as e: self._show_messagebox('error', str(e)) return except EmailWarning as e: self._show_messagebox('warning', str(e)) return except ClassifierException as e: self._show_messagebox( 'error', "Ошибка при загрузке классификатора:\n" + str(e)) return self._show_email_lines(original, self.textbox1) self._show_email_lines(without_sign, self.textbox2) del_lines_count = len(original) - len(without_sign) self._show_messagebox('info', "Удалено строк: " + str(del_lines_count)) def _show_info(self): messagebox.showinfo( 'Информация', 'Программа позволяет удалять подпись ' 'из текстов электронных писем папки "Входящие" почтового ящика gmail.\nУдаление ' 'подписи возможно в письмах, содержащих только текст.' '\nДля удаления подписи из письма введите адрес электронной почты, пароль и порядковый номер' ' письма в папке "Входящие", затем нажмите кнопку "Удалить подпись"' ) def _show_email_lines(self, lines, textbox): textbox.delete('1.0', END) all_lines = "\n".join(lines) textbox.insert('1.0', all_lines) def show(self): self.root.mainloop()