def init_ui(self): self.rowconfigure(3, weight=1) self.columnconfigure(0, weight=1) self.button_load_type = Button(self, text="Load Type JSON", command=lambda: browse_file(self, 1, )) self.button_load_type.grid( row=0, columnspan=2, sticky=W + E, pady=4, padx=5) self.button_load_color = Button( self, text="Load Color JSON", command=lambda: browse_file(self, 2)) self.button_load_color.grid( row=1, columnspan=2, sticky=W + E, pady=4, padx=5) button_load = Button( self, text="Load Images", command=lambda: browse_images(self)) button_load.grid(row=2, columnspan=2, sticky=W + E, pady=4, padx=5) button_learn = Button( self, text="Test", command= lambda: start_testing(self.dtype, self.dcolor, self.picture_frames) ) button_learn.grid(row=4, columnspan=2, sticky=W + E, pady=4, padx=5) canvas = Canvas(self) canvas.grid(row=3, sticky=W + E + N + S, column=0, pady=4, padx=5) frame = self.picture_frame = Frame(canvas) canvas.create_window(0, 0, window=frame, anchor='nw') scroll_bar = Scrollbar(self, orient="vertical", command=canvas.yview) scroll_bar.grid(sticky=E + N + S, padx=5, row=3, column=1) canvas.configure(yscrollcommand=scroll_bar.set) # track changes to the canvas and frame width and sync them, # also updating the scrollbar def _configure_interior(event): # update the scrollbars to match the size of the inner frame size = (frame.winfo_reqwidth(), frame.winfo_reqheight()) canvas.config(scrollregion="0 0 %s %s" % size) if frame.winfo_reqwidth() != canvas.winfo_width(): # update the canvas's width to fit the inner frame canvas.config(width=frame.winfo_reqwidth()) frame.bind('<Configure>', _configure_interior) def _configure_canvas(event): if frame.winfo_reqwidth() != canvas.winfo_width(): # update the inner frame's width to fill the canvas canvas.itemconfigure(frame, width=canvas.winfo_width()) canvas.bind('<Configure>', _configure_canvas)
def _init_ui(self): """ Composes the UI and associates the appropriate handler for the actions to catch. """ self._parent.title("Events") self._style = Style() self._style.theme_use("default") self.pack(fill=BOTH, expand=1) self.columnconfigure(1, weight=1) self.columnconfigure(3, pad=7) self.rowconfigure(3, weight=1) self.rowconfigure(5, pad=7) label = Label(self, text="Actions") label.grid(sticky=W, pady=4, padx=5) self._text_area = self.ReadOnlyText(self) self._text_area.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E + W + S + N) scrollbar = Scrollbar(self, command=self._text_area.yview) scrollbar.grid(row=1, column=2, rowspan=4, sticky=N + S) self._text_area['yscrollcommand'] = scrollbar.set start_button = Button(self, text="Start", command=self._rec_start) start_button.grid(row=1, column=3) stop_button = Button(self, text="Stop", command=self._rec_stop) stop_button.grid(row=2, column=3, pady=4) save_button = Button( self, text="Save", ) save_button.grid(row=5, column=3) quit_button = Button(self, text="Quit", command=self._exit) quit_button.grid(row=5, column=0, padx=5)
def create_scrollable_text_area(self): """ Creates main text area with scrollbars""" xscrollbar = Scrollbar(self, orient=HORIZONTAL) xscrollbar.grid(row=2, column=1, columnspan=5, sticky=E + W) yscrollbar = Scrollbar(self, orient=VERTICAL) yscrollbar.grid(row=1, column=6, sticky=N + S) self.textarea = Text(self, wrap=NONE, bd=0, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set) self.textarea.grid(row=1, column=1, columnspan=5, rowspan=1, padx=0, sticky=E + W + S + N) xscrollbar.config(command=self.textarea.xview) yscrollbar.config(command=self.textarea.yview)
def _init_ui(self): # Load an image self.img = ImageTk.PhotoImage(Image.open(r"images\dna5.png")) # Define a canvas in a frame frame = Frame(self) c = Canvas(frame, bg="white", height=475, width=475) # Display the image in the canvas c.create_image(0, 0, image=self.img, anchor=NW) # Y-scrollbar yscrollbar = Scrollbar(frame, command=c.yview) c.configure(yscrollcommand=yscrollbar.set) # X-scrollbar xscrollbar = Scrollbar(frame, orient=HORIZONTAL, command=c.xview) c.configure(xscrollcommand=xscrollbar.set) # Display widgets using grid layout. frame.grid(row=0, column=0) yscrollbar.grid(row=0, column=2, sticky=S + N) xscrollbar.grid(row=2, column=0, sticky=W + E) c.grid(row=0, column=0) self.pack(fill=BOTH, expand=1)
class TextWindow(Frame): """ A basic, scrollable text window that can either be editable or not """ def __init__(self, master): """ Make a scrollable, resizeable text """ Frame.__init__(self, master) # Add a horizontal and vertical scroller self.hscroller = Scrollbar(self, orient=HORIZONTAL) self.vscroller = Scrollbar(self, orient=VERTICAL) # Make the text box self.text = Text(self, width=90, state=DISABLED, height=15, wrap=NONE, xscrollcommand=self.hscroller.set, yscrollcommand=self.vscroller.set) # Pack everything in there, nice and tight. Let the text expand and the # scroll bars lengthen, but do not let the scroll bars thicken. self.text.grid(column=0, row=0, sticky=N+S+E+W) self.hscroller.grid(column=0, row=1, sticky=N+S+E+W) self.vscroller.grid(column=1, row=0, sticky=N+S+E+W) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=0) self.rowconfigure(0, weight=1) self.rowconfigure(1, weight=0) # Now make the scroll bars actually work self.hscroller.configure(command=self.text.xview) self.vscroller.configure(command=self.text.yview) def write(self, s): """ Writes 's' to the window, such that it will emulate a file. We have to change the state to ACTIVE in order to add text, but then change it back to the original state afterwards """ self.text.configure(state=NORMAL) self.text.insert(END, s) self.text.configure(state=DISABLED) def clear(self, event=None): """ Clears all text from this window """ self.text.config(state=NORMAL) self.text.delete('0.0', END) self.text.config(state=DISABLED)
def __init__(self, master, mixer): Frame.__init__(self, master) scrollbar_h = Scrollbar(self, orient='horizontal') scrollbar_v = Scrollbar(self, orient='vertical') self.canvas = Canvas(self, background='gray', scrollregion=(0, 0, (3 + len(mixer) * FADER_WIDTH), FADER_HEIGHT), yscrollcommand=scrollbar_v.set, xscrollcommand=scrollbar_h.set) scrollbar_v.config(command=self.canvas.yview) scrollbar_h.config(command=self.canvas.xview) master.bind("<MouseWheel>", lambda e: self.canvas.yview_scroll(-e.delta, 'units')) master.bind("<Shift-MouseWheel>", lambda e: self.canvas.xview_scroll(-e.delta, 'units')) Sizegrip(self).grid(column=2, row=1, sticky='se') self.canvas.grid(column=0, row=0, sticky='nwes') scrollbar_h.grid(column=0, row=1, sticky='we') scrollbar_v.grid(column=1, row=0, sticky='sn') master_fader = AudioFader(self, mixer.getVolume, mixer.setVolume, "Master") master_fader.grid(column=2, row=0, sticky='nwes') self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) for i, channel in enumerate(mixer): if channel.device.id_variable is not None: name = channel.device.id_variable else: name = channel.device.name_id fader = AudioFader(self.canvas, channel.get_gain, channel.set_gain, name) self.canvas.create_window(i * FADER_WIDTH, 0, anchor='nw', window=fader)
def _init_ui(self): """ Composes the UI and associates the appropriate handler for the actions to catch. """ self._parent.title("Events") self._style = Style() self._style.theme_use("default") self.pack(fill=BOTH, expand=1) self.columnconfigure(1, weight=1) self.columnconfigure(3, pad=7) self.rowconfigure(3, weight=1) self.rowconfigure(5, pad=7) label = Label(self, text="Actions") label.grid(sticky=W, pady=4, padx=5) self._text_area = self.ReadOnlyText(self) self._text_area.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E+W+S+N) scrollbar = Scrollbar(self, command=self._text_area.yview) scrollbar.grid(row=1, column=2, rowspan=4, sticky=N+S) self._text_area['yscrollcommand'] = scrollbar.set start_button = Button(self, text="Start", command=self._rec_start) start_button.grid(row=1, column=3) stop_button = Button(self, text="Stop", command=self._rec_stop) stop_button.grid(row=2, column=3, pady=4) save_button = Button(self, text="Save",) save_button.grid(row=5, column=3) quit_button = Button(self, text="Quit", command=self._exit) quit_button.grid(row=5, column=0, padx=5)
class Ordered_Listbox(Frame): def __init__(self, master, data=None, ascending_order = True, ignore_case=False, autoscroll=False, vscrollbar=True, hscrollbar=False, scrollbar_background=None, scrollbar_troughcolor=None, **kwargs): Frame.__init__(self, master) self._ignore_case = ignore_case self._ascending_order = ascending_order master.grid_rowconfigure(0, weight=1) master.grid_columnconfigure(0, weight=1) self._listbox = Listbox(self, *kwargs) self._listbox.grid(row=0, column=0, sticky= N+E+W+S) scrollbar_kwargs = {} if scrollbar_background is not None: scrollbar_kwargs["background"] = scrollbar_background if scrollbar_troughcolor is not None: scrollbar_kwargs["throughcolor"] = scrollbar_troughcolor if vscrollbar: self._vbar=Scrollbar(self,takefocus=0, command=self._listbox.yview, **scrollbar_kwargs) self._vbar.grid(row=0, column=1, sticky= N+S) if autoscroll: self._listbox.config(yscrollcommand=lambda f, l: make_autoscroll(self._vbar, f, l)) else: self._listbox.config(yscrollcommand=self._vbar.set) if hscrollbar: self._hbar=Scrollbar(self,takefocus=0, command=self._listbox.xview, **scrollbar_kwargs) self._hbar.grid(row=0, column=1, sticky= E+W) if autoscroll: self._listbox.config(xscrollcommand=lambda f, l: make_autoscroll(self._hbar, f, l)) else: self._listbox.config(xscrollcommand=self._hbar.set) if data is not None: for item in data: self.add_item(item) def add_item(self, item): list_of_items = self._listbox.get(0, END) index = bisect(list_of_items, item, ignore_case=self._ignore_case, ascending_order=self._ascending_order) self._listbox.insert(index, item) def delete_item(self, item): list_of_items = self._listbox.get(0, END) index = bisect(list_of_items, item, ignore_case=self._ignore_case, ascending_order=self._ascending_order) self._listbox.delete(index-1) def selected_items(self): list_of_items = [] for index in self._listbox.curselection(): list_of_items.append(self._listbox.get(index)) return list_of_items def selected_item(self): return self._listbox.curselection()[0] def deselect_all(self): self._listbox.selection_clear(0, END) def select(self, item): index = self.index(item) if index is None: return self._listbox.selection_set(index) def deselect(self, item): index = self.index(item) if index is None: return self._listbox.selection_clear(index) def index(self, item): list_of_items = self._listbox.get(0, END) try: index = list_of_items.index(item) except ValueError: return None return index def bind(self, event, handler): self._listbox.bind(event, handler) def clear(self): self._listbox.delete(1,END) def __iter__(self): return self.items @property def items(self): return self._listbox.get(0, END)
class MacroFrame(Frame): def __init__(self, parent): Frame.__init__(self, parent, background="white") self.parent = parent self.numStates = 0 self.initUI() def initUI(self): self.columnconfigure(0, weight=0) self.columnconfigure(1, weight=0) self.columnconfigure(2, weight=1) self.columnconfigure(3, weight=1) self.rowconfigure(0, weight=1) self.commandFrame = Frame(self, background="white") self.commandFrame.grid(row=0, column=0, columnspan=5, sticky=W+E) self.commandFrame.columnconfigure(1, weight=1) self.btnCommand = Button(self.commandFrame, text="Run") self.btnCommand.grid(row=0, column=0) self.strCommand = StringVar() self.entCommand = Entry(self.commandFrame, textvariable=self.strCommand) self.entCommand.grid(row=0, column=1, sticky=W+E) self.lstMacro = Listbox(self) self.lstMacro.grid(row=1, column=0, sticky=N+S+W+E) self.treeview = Treeview(self, columns=("Angle"), displaycolumns="#all", selectmode="browse") self.treeview.grid(row=1, column=1, columnspan=4, sticky=N+S+W+E) self.treeScrollbar = Scrollbar(self) self.treeScrollbar.grid(row=1, column=5, sticky=N+S) self.treeview.config(yscrollcommand=self.treeScrollbar.set) self.treeScrollbar.config(command=self.treeview.yview) self.btnFrame = Frame(self, background="white") self.btnFrame.grid(row=2, column=0, columnspan=5, sticky=W+E) self.btnRun = Button(self.btnFrame, text="Run", command=self.runMacro) self.btnRun.grid(row=0, column=0) self.btnStop = Button(self.btnFrame, text="Stop") self.btnStop.grid(row=0, column=1) self.btnSaveMacro = Button(self.btnFrame, text="Save Macro", command=self.saveMacro) self.btnSaveMacro.grid(row=0, column=2) self.btnDeleteMacro = Button(self.btnFrame, text="Delete Macro") self.btnDeleteMacro.grid(row=0, column=3) self.btnDeleteState = Button(self.btnFrame, text="Delete State") self.btnDeleteState.grid(row=0, column=4) def addState(self, robot): stateName = "state" + str(self.numStates) self.treeview.insert("", END, iid=stateName, text=stateName) limbNum = 0 for limb in robot.getLimbs(): limbName = "limb" + str(limbNum) self.treeview.insert(stateName, END, iid=stateName + "_" + limbName, text=limbName) partNum = 0 for part in limb.getComponents(): partName = "joint" + str(partNum) if isinstance(part, Joint): self.treeview.insert(stateName + "_" + limbName, END, iid=stateName + "_" + limbName + "_" + partName, text=partName, values=[part.angle]) partNum += 1 limbNum += 1 self.numStates += 1 def getState(self, stateNum, robot): stateName = "state" + str(stateNum) limbNum = 0 for limb in robot.getLimbs(): limbName = "limb" + str(limbNum) partNum = 0 for part in limb.getComponents(): partName = "joint" + str(partNum) if isinstance(part, Joint): part.setAngle(int(self.treeview.item(stateName + "_" + limbName + "_" + partName, "values")[0])) partNum += 1 limbNum += 1 def runMacro(self): thread = threading.Thread(target=self.updateState) thread.start() def updateState(self): for i in range(self.numStates): self.getState(i, self.parent.robotFrame.robot) time.sleep(.1) def saveMacro(self): pass
class Tk_Table(Frame, object): def __init__(self, master, columns, data=None, command=None, editable=True, sort=True, select_mode=None, autoscroll=True, vscrollbar=True, hscrollbar=False, heading_anchor = CENTER, cell_anchor=W, style=None, scrollbar_background=None, scrollbar_troughcolor=None, height=None, padding=None, adjust_heading_to_content=False, stripped_rows=None, selection_background=None, selection_foreground=None, cell_background=None, cell_foreground=None, cell_font=None, field_background=None, heading_font= None, heading_background=None, heading_foreground=None, cell_pady=2, column_header=True, row_numbers=True, entry_background="#d6d6d6", entry_foreground=None, entry_validatecommand=None, entry_selectbackground="#1BA1E2", entry_selectborderwidth=None, entry_selectforeground=None, entry_font = "TkDefaultFont", rowlabel_anchor=E, rowlabel_minwidth=0, rowlabel_hoverbackground="#FFFFFF",frame_relief=None, frame_borderwidth=None, frame_background=None): frame_kwargs = {} if frame_relief is not None: frame_kwargs["relief"] = frame_relief if frame_borderwidth is not None: frame_kwargs["borderwidth"] = frame_borderwidth if frame_background is not None: frame_kwargs["background"] = frame_background Frame.__init__(self, master, class_="Multicolumn_Listbox", **frame_kwargs) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self._multicolumn_listbox = Multicolumn_Listbox(self, columns, data=data, command=command, sort=sort, select_mode=select_mode, heading_anchor = heading_anchor, cell_anchor=cell_anchor, style=style, height=height, padding=padding, adjust_heading_to_content=adjust_heading_to_content, stripped_rows=stripped_rows, selection_background=selection_background, selection_foreground=selection_foreground, cell_background=cell_background, cell_foreground=cell_foreground, cell_font=cell_font, field_background=field_background, heading_font=heading_font, heading_background=heading_background, heading_foreground=heading_foreground, cell_pady=cell_pady, headers=column_header) self._multicolumn_listbox.interior.grid(row=0, column=1, sticky= N+E+W+S) self._mousewheel_detection = True if row_numbers: self._row_numbers = Row_Header(self, font=self._multicolumn_listbox.font, row_height=self._multicolumn_listbox.row_height, row_minwidth=rowlabel_minwidth, hover_background = rowlabel_hoverbackground, anchor=rowlabel_anchor, onclick=self._on_click_row_label) self._row_numbers.grid(row=0, column=0, sticky= N+S+E) self._multicolumn_listbox.interior.bind("<Map>", self._place_vertically_row_numbers) else: self._row_numbers = None if editable: self._selected_cell = None self._entry_popup = None self._multicolumn_listbox.interior.bind("<1>", self._edit_cell) def configure(event): """ if self._entry_popup: self._entry_popup.destroy() return """ self._multicolumn_listbox.interior.update_idletasks() self._update_position_of_entry() self._multicolumn_listbox.interior.bind("<Configure>", configure) self._entry_kwargs = entry_kwargs = {} if entry_background is not None: entry_kwargs["background"] = entry_background if entry_foreground is not None: entry_kwargs["foreground"] = entry_foreground if entry_validatecommand is not None: entry_kwargs["validatecommand"] = entry_validatecommand if entry_selectbackground is not None: entry_kwargs["selectbackground"] = entry_selectbackground if entry_selectforeground is not None: entry_kwargs["selectforeground"] = entry_selectforeground if entry_font is not None: entry_kwargs["font"] = entry_font if command is not None: self._command = command self._multicolumn_listbox.interior.bind("<<TreeviewSelect>>", self._on_select) scrollbar_kwargs = {} if scrollbar_background is not None: scrollbar_kwargs["background"] = scrollbar_background if scrollbar_troughcolor is not None: scrollbar_kwargs["throughcolor"] = scrollbar_troughcolor if vscrollbar: if editable: if row_numbers: def yview_command(*args): self._multicolumn_listbox.interior.yview(*args) self._row_numbers.yview(*args) self._update_position_of_entry() else: def yview_command(*args): self._multicolumn_listbox.interior.yview(*args) self._update_position_of_entry() else: if row_numbers: def yview_command(*args): self._multicolumn_listbox.interior.yview(*args) self._row_numbers.yview(*args) else: yview_command = self._multicolumn_listbox.interior.yview self._vbar=Scrollbar(self,takefocus=0, command=yview_command, **scrollbar_kwargs) self._vbar.grid(row=0, column=2, sticky= N+S) def yscrollcommand(first,last): first, last = float(first), float(last) if first <= 0 and last >= 1: if self._mousewheel_detection: if autoscroll: self._vbar.grid_remove() if row_numbers: unbind_function_onMouseWheel(self._multicolumn_listbox.interior) self._mousewheel_detection = False else: if not self._mousewheel_detection: if autoscroll: self._vbar.grid() if row_numbers: bind_function_onMouseWheel(self._row_numbers, "y", binding_widget=self._multicolumn_listbox.interior, unit="pages") self._mousewheel_detection = True self._vbar.set(first, last) if editable: self._update_position_of_entry() self._multicolumn_listbox.interior.config(yscrollcommand=yscrollcommand) if hscrollbar: if editable: def xview_command(*args): self._multicolumn_listbox.interior.xview(*args) self._update_position_of_entry() else: xview_command = self._multicolumn_listbox.interior.xview self._hbar=Scrollbar(self,takefocus=0, command=xview_command, **scrollbar_kwargs) self._hbar.grid(row=1, column=1, sticky= E+W) if autoscroll: if editable: def xscrollcommand(f,l, self=self): make_autoscroll(self._hbar, f, l) self._update_position_of_entry() else: def xscrollcommand(f,l, hbar=self._hbar): make_autoscroll(hbar, f, l) self._multicolumn_listbox.interior.config(xscrollcommand=xscrollcommand) else: self._multicolumn_listbox.interior.config(xscrollcommand=self._hbar.set) def _place_vertically_row_numbers(self, event): self._multicolumn_listbox.interior.unbind("<Map>") item_ID = self._multicolumn_listbox.interior.insert('', 0, values=[""]*self._multicolumn_listbox.number_of_columns) self._multicolumn_listbox.interior.update() x,y,w,h = self._multicolumn_listbox.interior.bbox(item_ID) self._multicolumn_listbox.interior.delete(item_ID) self._row_numbers.grid_configure(pady=(y,0)) def _edit_cell(self, event): '''Executed, when a row is clicked. Opens an entry popup above the cell, so it is possible to select text ''' # close previous popups if self._entry_popup: self._destroy_entry() # what row and column was clicked on item_ID = self._multicolumn_listbox.interior.identify_row(event.y) if not item_ID: return column = self._multicolumn_listbox.interior.identify_column(event.x) if column == "": return # get column position info x,y,width,height = self._multicolumn_listbox.interior.bbox(item_ID, column) # place Entry popup properly column_number = int(column[1:])-1 cell_data = self._multicolumn_listbox.item_ID_to_row_data(item_ID)[column_number] self._entry_popup = Entry(self._multicolumn_listbox.interior, exportselection=True, borderwidth=0, **self._entry_kwargs) self._entry_popup.place(x=x, y=y, width=width, height=height) self._entry_popup.insert(0, cell_data) self._entry_popup.focus_force() self._entry_popup.bind("<Control-a>", lambda event: self._select_all_entry_data) self._entry_popup.bind("<Escape>", lambda event: self._destroy_entry()) self._entry_popup.bind("<FocusOut>", lambda event: self._destroy_entry()) bind_function_onMouseWheel(self._multicolumn_listbox.interior, "y", binding_widget=self._entry_popup, callback=self._update_position_of_entry, unit="pages") if self._row_numbers: bind_function_onMouseWheel(self._row_numbers, "y", binding_widget=self._entry_popup, unit="pages") self._entry_popup.bind("<Return>", self._on_update_cell) self._selected_cell = item_ID, column, column_number def _on_click_row_label(self, index): if self._selected_cell and self._multicolumn_listbox.item_ID(index) == self._selected_cell[0]: self._destroy_entry() self._multicolumn_listbox.toogle_selection(index) def _select_all_entry_data(self): ''' Set selection on the whole text ''' self._entry_popup.selection_range(0, 'end') # returns 'break' to interrupt default key-bindings return 'break' def _destroy_entry(self): self._entry_popup.destroy() self._entry_popup = None self._selected_cell = None def _on_update_cell(self, event): item_ID, column, column_number = self._selected_cell data = self._entry_popup.get() row_data = self._multicolumn_listbox.item_ID_to_row_data(item_ID) row_data[column_number] = data self._multicolumn_listbox.interior.item(item_ID, values=row_data) self._destroy_entry() def _update_position_of_entry(self): if self._selected_cell: bbox = self._multicolumn_listbox.interior.bbox(self._selected_cell[0], self._selected_cell[1]) if bbox == "": self._entry_popup.place_forget() else: x,y,width,height = bbox self._entry_popup.place(x=x, y=y, width=width, height=height) def configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None): self._multicolumn_listbox.configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None) def row_data(self, index): return self._multicolumn_listbox.row_data(index) def update_row(self, index, data): self._multicolumn_listbox.update_row(index,data) def delete_row(self, index): self._multicolumn_listbox.delete_row(index) if self._row_numbers: self._row_numbers.pop() def insert_row(self, data, index=None): self._multicolumn_listbox.insert_row(data, index) if self._row_numbers: self._row_numbers.new_label() def column_data(self, index): return self._multicolumn_listbox.column_data(index) def update_column(self, index, data): self._multicolumn_listbox.update_column(index, data) def clear(self): self._multicolumn_listbox.clear() if self._row_numbers: self._row_numbers.delete_labels() def update(self, data): current_number_of_rows = self._multicolumn_listbox.number_of_rows self._multicolumn_listbox.update(data) if self._row_numbers: number_of_rows = len(data) if current_number_of_rows < number_of_rows: for i in range(number_of_rows - current_number_of_rows): self._row_numbers.new_label() else: n_labels = current_number_of_rows - number_of_rows self._row_numbers.pop(n_labels =n_labels) def focus(self, index=None): self._multicolumn_listbox.focus(index) def state(self, state=None): self._multicolumn_listbox.state(state) @property def number_of_rows(self): return self._multicolumn_listbox.number_of_rows @property def number_of_columns(self): return self._multicolumn_listbox.number_of_columns def toogle_selection(self, index): self._multicolumn_listbox.toogle_selection(index) def select_row(self, index): self._multicolumn_listbox.select_row(index) def deselect_row(self, index): self._multicolumn_listbox.deselect_row(index) def deselect_all(self): self._multicolumn_listbox.deselect_all() def set_selection(self, indices): self._multicolumn_listbox.set_selection(indices) @property def selected_rows(self): return self._multicolumn_listbox.selected_rows @property def indices_of_selected_rows(self): return self._multicolumn_listbox.indices_of_selected_rows def delete_all_selected_rows(self): number_of_deleted_rows = self._multicolumn_listbox.delete_all_selected_rows() if self._row_numbers: self._row_numbers.pop(n_labels=number_of_deleted_rows) @property def table_data(self): return self._multicolumn_listbox.table_data @table_data.setter def table_data(self, data): self.update(data) def cell_data(self, row, column): return self._multicolumn_listbox.cell_data(row, column) def update_cell(self, row, column, value): self._multicolumn_listbox.update_cell(row, column, value) def __getitem__(self, index): return self._multicolumn_listbox[index] def __setitem__(self, index, value): self._multicolumn_listbox[index] = value def bind(self, event, handler): self._multicolumn_listbox.bind(event, handler) def sort_by(self, col, descending): self._multicolumn_listbox.sort_by(col, descending)
def __init__(self): Frame.__init__(self) self.style = Style() self.style.theme_use("default") self.master.title("Log viewer") self.pack(fill=BOTH, expand=True) self.used = [] # List of currently plotted series ([str]) self.series = {} # List of all series ({str -> [number]}) self.names = [] # List of all nodes in tree view ([str]) self.queues = [] # List of all queues ([str]) self.logs = {} # List of all text logs ({str -> [str]}) self.rowconfigure(1, weight=1) self.columnconfigure(6, weight=3) self.columnconfigure(11, weight=1) # Series selection takes row 1-2, col 0-2 self.series_ui = Treeview(self) self.series_ui.grid(row=1, column=0, columnspan=2, rowspan=2, sticky=N+S) self.series_ui.configure(show="tree") self.series_ui.bind("<Double-Button-1>", self.onselect) self.series_ui.tag_configure("graphall", foreground="#070") self.series_ui.tag_configure("graphnone", foreground="#000") self.series_ui.tag_configure("graphsome", foreground="#007") series_ui_scroll = Scrollbar(self, command=self.series_ui.yview, orient=VERTICAL) series_ui_scroll.grid(row=1, column=2, rowspan=2, sticky=N+S) self.series_ui["yscrollcommand"] = series_ui_scroll.set # The plot takes row 1-2, col 3-6 move_mode = StringVar() move_mode.set("pan") show_path = IntVar() show_path.set(0) event_bars = IntVar() event_bars.set(1) show_debug = IntVar() show_debug.set(1) show_error = IntVar() show_error.set(1) show_warning = IntVar() show_warning.set(1) show_info = IntVar() show_info.set(1) self.plot = HackPlot(self, move_mode, show_path, event_bars, [(show_debug, "[DEBUG]"), (show_error, "[ERROR]"), (show_warning, "[WARNING]"), (show_info, "[INFO]")]) self.plot.canvas.grid(row=1, column=3, columnspan=4, rowspan=2, sticky=N+S+E+W) # Text logs take row 1-2, col 7-12 self.plot.listbox.grid(row=1, column=7, columnspan=5, sticky=N+S+E+W) listbox_yscroll = Scrollbar(self, command=self.plot.listbox.yview, orient=VERTICAL) listbox_yscroll.grid(row=1, column=12, sticky=N+S) self.plot.listbox["yscrollcommand"] = listbox_yscroll.set listbox_xscroll = Scrollbar(self, command=self.plot.listbox.xview, orient=HORIZONTAL) listbox_xscroll.grid(row=2, column=7, columnspan=5, sticky=E+W) self.plot.listbox["xscrollcommand"] = listbox_xscroll.set # Controls take row 0, col 0-12 Button(self, text="Load Directory", command=self.loaddir).grid(row=0, column=0) Button(self, text="Load File", command=self.loadfile).grid(row=0, column=1) Button(self, text="Fit X", command=self.plot.fit_x).grid(row=0, column=3, sticky=W) Button(self, text="Fit Y", command=self.plot.fit_y).grid(row=0, column=4, sticky=W) Button(self, text="Fit Auto", command=self.plot.fit_auto).grid(row=0, column=5, sticky=W) Button(self, text="Fit Tele", command=self.plot.fit_tele).grid(row=0, column=6, sticky=W) # Plot controls in a subframe to manage padding so it doesn't look awful move_mode_control = Frame(self, padx=10) Radiobutton(move_mode_control, text="Pan", value="pan", variable=move_mode).grid(row=0, column=0, sticky=W) Radiobutton(move_mode_control, text="Zoom In", value="zoomin", variable=move_mode).grid(row=0, column=1, sticky=W) Radiobutton(move_mode_control, text="Zoom Out", value="zoomout", variable=move_mode).grid(row=0, column=2, sticky=W) move_mode_control.grid(row=0, column=7, sticky=W) Checkbutton(self, text="Event Bars", variable=event_bars, command=self.plot.show_textlogs).grid(row=0, column=8, sticky=W) Checkbutton(self, text="Debug", variable=show_debug, command=self.plot.show_textlogs).grid(row=0, column=9, sticky=W) Checkbutton(self, text="Error", variable=show_error, command=self.plot.show_textlogs).grid(row=0, column=10, sticky=W) Checkbutton(self, text="Warning", variable=show_warning, command=self.plot.show_textlogs).grid(row=0, column=11, sticky=W) Checkbutton(self, text="Info", variable=show_info, command=self.plot.show_textlogs).grid(row=0, column=12, sticky=W) Checkbutton(self, text="Directories", variable=show_path, command=self.plot.show_textlogs).grid(row=0, column=13, sticky=E)
def create_gui_elements(self): top_frame = Frame(self) top_frame.grid(row=0, column=0, columnspan=9, rowspan=6) # top_frame.pack(fill=X) # image display photo2 = ImageTk.PhotoImage(Image.open('back.png')) image_display = Label(top_frame) image_display.configure(image=photo2) image_display.image = photo2 image_display.grid(row=0, columnspan=9, column=1, rowspan=6) # image_lb.pack(side=TOP) self.add_gui_element(GUI_ELEMENT.IMAGE_DISPLAY_LABEL, image_display) close_button = Button(self, text='Close', command=close) close_button.grid(row=9, column=9) # close_button.pack(side=RIGHT, padx=5, pady=5) self.add_gui_element(GUI_ELEMENT.CLOSE_BTN, close_button) bottom_frame = Frame(self) bottom_frame.grid(row=5, column=0, columnspan=9, rowspan=3) # bottom_frame.pack(fill=X) config_frame = Frame(bottom_frame) config_frame.grid(row=5, column=6, columnspan=3, rowspan=3) # config_frame.pack(fill=X) list_box_frame = Frame(config_frame) list_box_frame.grid(row=5, column=6, columnspan=3, rowspan=3) # list_box_frame.pack(side=RIGHT) scrollbar = Scrollbar(list_box_frame) # scrollbar.pack(side=RIGHT, fill=Y) resolution_lb = Listbox(list_box_frame, selectmode=SINGLE, height=4, yscrollcommand=scrollbar.set) i = 0 for resolution in ScreenPaper.get_resolution(): resolution_lb.insert(i, '%dx%d' % (resolution[0], resolution[1])) i += 1 scrollbar.grid(row=5, column=9, rowspan=9) resolution_lb.grid(row=5, column=6, rowspan=4, columnspan=3) scrollbar.config(command=resolution_lb.yview) # resolution_lb.pack(side=RIGHT) self.add_gui_element(GUI_ELEMENT.RESOLUTION_LB, resolution_lb) ok_btn = Button(self, text='Create', command=self.create_pape) ok_btn.grid(row=9, column=7) # ok_btn.pack(side=RIGHT) self.add_gui_element(GUI_ELEMENT.OK_BTN, ok_btn) save_btn = Button(self, text='Save', command=self.save_image_as) save_btn.grid(row=9, column=8) # save_btn.pack(side=RIGHT) self.add_gui_element(GUI_ELEMENT.SAVE_BTN, save_btn) checkbox_frame = Frame(config_frame) checkbox_frame.grid(row=5, column=0, rowspan=3, columnspan=6) auto_save_var = IntVar() auto_save_chk = Checkbutton(checkbox_frame, text="Save automatically", variable=auto_save_var, onvalue=1, offvalue=0) auto_save_chk.grid(row=5, column=1) # auto_save_chk.pack(side=BOTTOM) self.add_gui_element(GUI_ELEMENT.AUTOMATICALLY_SAVE_CK, {'element':auto_save_chk, 'var': auto_save_var}) auto_upload_var = IntVar() auto_upload_chk = Checkbutton(checkbox_frame, text="Upload to imgur automatically", variable=auto_upload_var, onvalue=1, offvalue=0) auto_upload_chk.grid(row=6, column=1) # auto_upload_chk.pack(side=BOTTOM) self.add_gui_element(GUI_ELEMENT.AUTOMATICALLY_UPLOAD_CK, {'element': auto_upload_chk, 'var': auto_upload_var}) # checkbox_frame.pack(side=RIGHT) message_lb = Label(self) message_lb.grid(row=7, column=1) # message_lb.pack(side=BOTTOM) self.add_gui_element(GUI_ELEMENT.MESSAGE_LABEL, message_lb)
class TreeTable(Frame): """ A table based on :class:`ttk.Treeview`. :Parameters: **master** : Tkinter or ttk widget The widget in which the :class:`TableTree` will reside. **headers** : list of str The column headers for the table. **data** : list of tuples Table data. There must be as many elements in each tuple as there \ are headers. Each tuple in the list corresponds to a row in the \ table. """ def __init__(self, master, headers, data, name=None): Frame.__init__(self, master, name=name) #: column headers self.headers = headers #: table data self.data = data #: :class:`~ttk.Treeview` that only shows "headings" not "tree columns" self.tree = Treeview(self, columns=self.headers, show="headings", name='tabletree') #: vertical scrollbar self.yscroll = Scrollbar(self, orient="vertical", command=self.tree.yview, name='table_yscroll') #: horizontal scrollbar self.xscroll = Scrollbar(self, orient="horizontal", command=self.tree.xview, name='table_xscroll') self.tree['yscrollcommand'] = self.yscroll.set # bind to scrollbars self.tree['xscrollcommand'] = self.xscroll.set # position widgets and set resize behavior self.tree.grid(column=0, row=0, sticky=(N + E + W + S)) self.yscroll.grid(column=1, row=0, sticky=(N + S)) self.xscroll.grid(column=0, row=1, sticky=(E + W)) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) # build tree for col in self.headers: # NOTE: Use col as column identifiers, crafty! # NOTE: Also change col to title case using str.title() # NOTE: make lambda behave nicely in a loop using default arg! callback = lambda c=col: self.sortby(c, False) self.tree.heading(col, text=col.title(), command=callback) # adjust the column's width to the header string self.tree.column(col, width=tkFont.Font().measure(col.title())) # insert a new top-level treeview item by suing an empty string for item in self.data: self.tree.insert('', END, values=item) # adjust column's width if necessary to fit each value for idx, val in enumerate(item): col_width = tkFont.Font().measure(val) # option can be specified at least 3 ways: as (a) width=None, # (b) option='width' or (c) 'width', where 'width' can be any # valid column option. if self.tree.column(self.headers[idx], 'width') < col_width: self.tree.column(self.headers[idx], width=col_width) def sortby(self, col, descending): """ Sort table contents when a column header is clicked. :Parameters: **col** The column identifier of the column to sort. **descending** False if ascending, True if descending, switches each time. """ logging.debug('sortby %s, descending: %s', col, descending) # grab values to sort data = [(self.tree.set(child, col), child) for child in self.tree.get_children('')] # now sort the data in place data.sort(reverse=descending) for idx, item in enumerate(data): self.tree.move(item[1], '', idx) # switch the heading so it will sort in the opposite direction callback = lambda: self.sortby(col, not descending) self.tree.heading(col, command=callback)
class Scrolling_Area(Frame, object): def __init__(self, master, width=None, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, outer_background=None, inner_frame=Frame, **kw): super(Scrolling_Area, self).__init__(master, **kw) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._clipper = Frame(self, background=outer_background, width=width, height=height) self._clipper.grid(row=0, column=0, sticky=N+E+W+S) self._width = width self._height = height self.innerframe = inner_frame(self._clipper, padx=0, pady=0, highlightthickness=0) self.innerframe.place(in_=self._clipper, x=0, y=0) if scroll_vertically: if yscrollbar is not None: self.yscrollbar = yscrollbar else: self.yscrollbar = Scrollbar(self, orient=VERTICAL) self.yscrollbar.grid(row=0, column=1,sticky=N+S) self.yscrollbar.set(0.0, 1.0) self.yscrollbar.config(command=self.yview) else: self.yscrollbar = None self._scroll_vertically = scroll_vertically if scroll_horizontally: if xscrollbar is not None: self.xscrollbar = xscrollbar else: self.xscrollbar = Scrollbar(self, orient=HORIZONTAL) self.xscrollbar.grid(row=1, column=0, sticky=E+W) self.xscrollbar.set(0.0, 1.0) self.xscrollbar.config(command=self.xview) else: self.xscrollbar = None self._scroll_horizontally = scroll_horizontally self._jfraction=0.05 self._startX = 0 self._startY = 0 # Whenever the clipping window or scrolled frame change size, # update the scrollbars. self.innerframe.bind('<Configure>', self._on_configure) self._clipper.bind('<Configure>', self._on_configure) self.innerframe.xview = self.xview self.innerframe.yview = self.yview Mousewheel_Support(self).add_support_to(self.innerframe, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar) def update_viewport(self): # compute new height and width self.update() frameHeight = float(self.innerframe.winfo_reqheight()) frameWidth = float(self.innerframe.winfo_reqwidth()) if self._width is not None: width = min(self._width, frameWidth) else: width = self._frameWidth if self._height is not None: height = min(self._height, frameHeight) else: height = self._frameHeight self._clipper.configure(width=width, height=height) def _on_configure(self, event): self._frameHeight = float(self.innerframe.winfo_reqheight()) self._frameWidth = float(self.innerframe.winfo_reqwidth()) # resize the visible part if self._scroll_horizontally: self.xview("scroll", 0, "unit") if self._scroll_vertically: self.yview("scroll", 0, "unit") def xview(self, mode = None, value = None, units = None): value = float(value) clipperWidth = self._clipper.winfo_width() frameWidth = self._frameWidth _startX = self._startX if mode is None: return self.xscrollbar.get() elif mode == 'moveto': # absolute movement self._startX = int(value * frameWidth) else: # mode == 'scroll' # relative movement if units == 'units': jump = int(clipperWidth * self._jfraction) else: jump = clipperWidth self._startX = self._startX + value * jump if frameWidth <= clipperWidth: # The scrolled frame is smaller than the clipping window. self._startX = 0 hi = 1.0 #use expand by default relwidth = 1 else: # The scrolled frame is larger than the clipping window. #use expand by default if self._startX + clipperWidth > frameWidth: self._startX = frameWidth - clipperWidth hi = 1.0 else: if self._startX < 0: self._startX = 0 hi = (self._startX + clipperWidth) / frameWidth relwidth = '' if self._startX != _startX: # Position frame relative to clipper. self.innerframe.place(x = -self._startX, relwidth = relwidth) lo = self._startX / frameWidth self.xscrollbar.set(lo, hi) def yview(self, mode = None, value = None, units = None): value = float(value) clipperHeight = self._clipper.winfo_height() frameHeight = self._frameHeight _startY = self._startY if mode is None: return self.yscrollbar.get() elif mode == 'moveto': self._startY = value * frameHeight else: # mode == 'scroll' if units == 'units': jump = int(clipperHeight * self._jfraction) else: jump = clipperHeight self._startY = self._startY + value * jump if frameHeight <= clipperHeight: # The scrolled frame is smaller than the clipping window. self._startY = 0 hi = 1.0 # use expand by default relheight = 1 else: # The scrolled frame is larger than the clipping window. # use expand by default if self._startY + clipperHeight > frameHeight: self._startY = frameHeight - clipperHeight hi = 1.0 else: if self._startY < 0: self._startY = 0 hi = (self._startY + clipperHeight) / frameHeight relheight = '' if self._startY != _startY: # Position frame relative to clipper. self.innerframe.place(y = -self._startY, relheight = relheight) lo = self._startY / frameHeight self.yscrollbar.set(lo, hi)
class MainWindow(object): def __init__(self, root, debugger): ''' ----------------------------------------------------- | main button toolbar | ----------------------------------------------------- | < ma | in content area > | | | | | | | File list | File name | Inspector | | (stack/ | Code area | | | breakpnts) | | | | | | | | | | | ----------------------------------------------------- | status bar area | ----------------------------------------------------- ''' # Obtain and expand the current working directory. base_path = os.path.abspath(os.getcwd()) base_path = os.path.normcase(base_path) + '/' # Create a filename normalizer based on the CWD. self.filename_normalizer = filename_normalizer(base_path) self.debugger = debugger # Associate the debugger with this view. self.debugger.view = self # Root window self.root = root self.root.title('Bugjar') self.root.geometry('1024x768') # Prevent the menus from having the empty tearoff entry self.root.option_add('*tearOff', False) # Catch the close button self.root.protocol("WM_DELETE_WINDOW", self.cmd_quit) # Catch the "quit" event. self.root.createcommand('exit', self.cmd_quit) # Setup the menu self._setup_menubar() # Set up the main content for the window. self._setup_button_toolbar() self._setup_main_content() self._setup_status_bar() # Now configure the weights for the root frame self.root.columnconfigure(0, weight=1) self.root.rowconfigure(0, weight=0) self.root.rowconfigure(1, weight=1) self.root.rowconfigure(2, weight=0) debugger.start() ###################################################### # Internal GUI layout methods. ###################################################### def _setup_menubar(self): # Menubar self.menubar = Menu(self.root) # self.menu_Apple = Menu(self.menubar, name='Apple') # self.menubar.add_cascade(menu=self.menu_Apple) self.menu_file = Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_file, label='File') self.menu_program = Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_program, label='Program') self.menu_help = Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_help, label='Help') # self.menu_Apple.add_command(label='Test', command=self.cmd_dummy) # self.menu_file.add_command(label='New', command=self.cmd_dummy, accelerator="Command-N") self.menu_file.add_command(label='Open...', command=self.cmd_open_file, accelerator="Command-O") self.root.bind('<Command-o>', self.cmd_open_file) # self.menu_file.add_command(label='Close', command=self.cmd_dummy) self.menu_program.add_command(label='Run', command=self.cmd_run, accelerator="R") self.root.bind('<r>', self.cmd_run) self.menu_program.add_command(label='Step', command=self.cmd_step, accelerator="S") self.root.bind('<s>', self.cmd_step) self.menu_program.add_command(label='Next', command=self.cmd_next, accelerator="N") self.root.bind('<n>', self.cmd_next) self.menu_program.add_command(label='Return', command=self.cmd_return, accelerator="BackSpace") self.root.bind('<BackSpace>', self.cmd_return) self.menu_help.add_command(label='Open Documentation', command=self.cmd_bugjar_docs) self.menu_help.add_command(label='Open Bugjar project page', command=self.cmd_bugjar_page) self.menu_help.add_command(label='Open Bugjar on GitHub', command=self.cmd_bugjar_github) self.menu_help.add_command(label='Open BeeWare project page', command=self.cmd_beeware_page) # last step - configure the menubar self.root['menu'] = self.menubar def _setup_button_toolbar(self): ''' The button toolbar runs as a horizontal area at the top of the GUI. It is a persistent GUI component ''' # Main toolbar self.toolbar = Frame(self.root) self.toolbar.grid(column=0, row=0, sticky=(W, E)) # Buttons on the toolbar self.run_button = Button(self.toolbar, text='Run', command=self.cmd_run) self.run_button.grid(column=0, row=0) self.step_button = Button(self.toolbar, text='Step', command=self.cmd_step) self.step_button.grid(column=1, row=0) self.next_button = Button(self.toolbar, text='Next', command=self.cmd_next) self.next_button.grid(column=2, row=0) self.return_button = Button(self.toolbar, text='Return', command=self.cmd_return) self.return_button.grid(column=3, row=0) self.toolbar.columnconfigure(0, weight=0) self.toolbar.rowconfigure(0, weight=0) def _setup_main_content(self): ''' Sets up the main content area. It is a persistent GUI component ''' # Main content area self.content = PanedWindow(self.root, orient=HORIZONTAL) self.content.grid(column=0, row=1, sticky=(N, S, E, W)) # Create subregions of the content self._setup_file_lists() self._setup_code_area() self._setup_inspector() # Set up weights for the left frame's content self.content.columnconfigure(0, weight=1) self.content.rowconfigure(0, weight=1) self.content.pane(0, weight=1) self.content.pane(1, weight=2) self.content.pane(2, weight=1) def _setup_file_lists(self): self.file_notebook = Notebook(self.content, padding=(0, 5, 0, 5)) self.content.add(self.file_notebook) self._setup_stack_frame_list() self._setup_breakpoint_list() def _setup_stack_frame_list(self): self.stack_frame = Frame(self.content) self.stack_frame.grid(column=0, row=0, sticky=(N, S, E, W)) self.file_notebook.add(self.stack_frame, text='Stack') self.stack = StackView(self.stack_frame, normalizer=self.filename_normalizer) self.stack.grid(column=0, row=0, sticky=(N, S, E, W)) # # The tree's vertical scrollbar self.stack_scrollbar = Scrollbar(self.stack_frame, orient=VERTICAL) self.stack_scrollbar.grid(column=1, row=0, sticky=(N, S)) # # Tie the scrollbar to the text views, and the text views # # to each other. self.stack.config(yscrollcommand=self.stack_scrollbar.set) self.stack_scrollbar.config(command=self.stack.yview) # Setup weights for the "stack" tree self.stack_frame.columnconfigure(0, weight=1) self.stack_frame.columnconfigure(1, weight=0) self.stack_frame.rowconfigure(0, weight=1) # Handlers for GUI events self.stack.bind('<<TreeviewSelect>>', self.on_stack_frame_selected) def _setup_breakpoint_list(self): self.breakpoints_frame = Frame(self.content) self.breakpoints_frame.grid(column=0, row=0, sticky=(N, S, E, W)) self.file_notebook.add(self.breakpoints_frame, text='Breakpoints') self.breakpoints = BreakpointView(self.breakpoints_frame, normalizer=self.filename_normalizer) self.breakpoints.grid(column=0, row=0, sticky=(N, S, E, W)) # The tree's vertical scrollbar self.breakpoints_scrollbar = Scrollbar(self.breakpoints_frame, orient=VERTICAL) self.breakpoints_scrollbar.grid(column=1, row=0, sticky=(N, S)) # Tie the scrollbar to the text views, and the text views # to each other. self.breakpoints.config(yscrollcommand=self.breakpoints_scrollbar.set) self.breakpoints_scrollbar.config(command=self.breakpoints.yview) # Setup weights for the "breakpoint list" tree self.breakpoints_frame.columnconfigure(0, weight=1) self.breakpoints_frame.columnconfigure(1, weight=0) self.breakpoints_frame.rowconfigure(0, weight=1) # Handlers for GUI events self.breakpoints.tag_bind('breakpoint', '<Double-Button-1>', self.on_breakpoint_double_clicked) self.breakpoints.tag_bind('breakpoint', '<<TreeviewSelect>>', self.on_breakpoint_selected) self.breakpoints.tag_bind('file', '<<TreeviewSelect>>', self.on_breakpoint_file_selected) def _setup_code_area(self): self.code_frame = Frame(self.content) self.code_frame.grid(column=1, row=0, sticky=(N, S, E, W)) # Label for current file self.current_file = StringVar() self.current_file_label = Label(self.code_frame, textvariable=self.current_file) self.current_file_label.grid(column=0, row=0, sticky=(W, E)) # Code display area self.code = DebuggerCode(self.code_frame, debugger=self.debugger) self.code.grid(column=0, row=1, sticky=(N, S, E, W)) # Set up weights for the code frame's content self.code_frame.columnconfigure(0, weight=1) self.code_frame.rowconfigure(0, weight=0) self.code_frame.rowconfigure(1, weight=1) self.content.add(self.code_frame) def _setup_inspector(self): self.inspector_frame = Frame(self.content) self.inspector_frame.grid(column=2, row=0, sticky=(N, S, E, W)) self.inspector = InspectorView(self.inspector_frame) self.inspector.grid(column=0, row=0, sticky=(N, S, E, W)) # The tree's vertical scrollbar self.inspector_scrollbar = Scrollbar(self.inspector_frame, orient=VERTICAL) self.inspector_scrollbar.grid(column=1, row=0, sticky=(N, S)) # Tie the scrollbar to the text views, and the text views # to each other. self.inspector.config(yscrollcommand=self.inspector_scrollbar.set) self.inspector_scrollbar.config(command=self.inspector.yview) # Setup weights for the "breakpoint list" tree self.inspector_frame.columnconfigure(0, weight=1) self.inspector_frame.columnconfigure(1, weight=0) self.inspector_frame.rowconfigure(0, weight=1) self.content.add(self.inspector_frame) def _setup_status_bar(self): # Status bar self.statusbar = Frame(self.root) self.statusbar.grid(column=0, row=2, sticky=(W, E)) # Current status self.run_status = StringVar() self.run_status_label = Label(self.statusbar, textvariable=self.run_status) self.run_status_label.grid(column=0, row=0, sticky=(W, E)) self.run_status.set('Not running') # Main window resize handle self.grip = Sizegrip(self.statusbar) self.grip.grid(column=1, row=0, sticky=(S, E)) # Set up weights for status bar frame self.statusbar.columnconfigure(0, weight=1) self.statusbar.columnconfigure(1, weight=0) self.statusbar.rowconfigure(0, weight=0) ###################################################### # Utility methods for controlling content ###################################################### def show_file(self, filename, line=None, breakpoints=None): """Show the content of the nominated file. If specified, line is the current line number to highlight. If the line isn't currently visible, the window will be scrolled until it is. breakpoints is a list of line numbers that have current breakpoints. If refresh is true, the file will be reloaded and redrawn. """ # Set the filename label for the current file self.current_file.set(self.filename_normalizer(filename)) # Update the code view; this means changing the displayed file # if necessary, and updating the current line. if filename != self.code.filename: self.code.filename = filename for bp in self.debugger.breakpoints(filename).values(): if bp.enabled: self.code.enable_breakpoint(bp.line) else: self.code.disable_breakpoint(bp.line) self.code.line = line ###################################################### # TK Main loop ###################################################### def mainloop(self): self.root.mainloop() ###################################################### # TK Command handlers ###################################################### def cmd_quit(self): "Quit the debugger" self.debugger.stop() self.root.quit() def cmd_run(self, event=None): "Run until the next breakpoint, or end of execution" self.debugger.do_run() def cmd_step(self, event=None): "Step into the next line of code" self.debugger.do_step() def cmd_next(self, event=None): "Run the next line of code in the current frame" self.debugger.do_next() def cmd_return(self, event=None): "Return to the previous frame" self.debugger.do_return() def cmd_open_file(self, event=None): "Open a file in the breakpoint pane" filename = tkFileDialog.askopenfilename( initialdir=os.path.abspath(os.getcwd())) if filename: # Convert to canonical form filename = os.path.abspath(filename) filename = os.path.normcase(filename) # Show the file contents self.code.filename = filename # Ensure the file appears on the breakpoint list self.breakpoints.insert_filename(filename) # Show the breakpoint panel self.file_notebook.select(self.breakpoints_frame) # ... select the new filename self.breakpoints.selection_set(filename) # .. and clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) def cmd_bugjar_page(self): "Show the Bugjar project page" webbrowser.open_new('http://pybee.org/bugjar') def cmd_bugjar_github(self): "Show the Bugjar GitHub repo" webbrowser.open_new('http://github.com/pybee/bugjar') def cmd_bugjar_docs(self): "Show the Bugjar documentation" # If this is a formal release, show the docs for that # version. otherwise, just show the head docs. if len(NUM_VERSION) == 3: webbrowser.open_new('http://bugjar.readthedocs.org/en/v%s/' % VERSION) else: webbrowser.open_new('http://bugjar.readthedocs.org/') def cmd_beeware_page(self): "Show the BeeWare project page" webbrowser.open_new('http://pybee.org/') ###################################################### # Handlers for GUI actions ###################################################### def on_stack_frame_selected(self, event): "When a stack frame is selected, highlight the file and line" if event.widget.selection(): _, index = event.widget.selection()[0].split(':') line, frame = self.debugger.stack[int(index)] # Display the file in the code view self.show_file(filename=frame['filename'], line=line) # Display the contents of the selected frame in the inspector self.inspector.show_frame(frame) # Clear any currently selected item on the breakpoint tree self.breakpoints.selection_remove(self.breakpoints.selection()) def on_breakpoint_selected(self, event): "When a breakpoint on the tree has been selected, show the breakpoint" if event.widget.selection(): parts = event.widget.focus().split(':') bp = self.debugger.breakpoint((parts[0], int(parts[1]))) self.show_file(filename=bp.filename, line=bp.line) # Clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) def on_breakpoint_file_selected(self, event): "When a file is selected on the breakpoint tree, show the file" if event.widget.selection(): filename = event.widget.focus() self.show_file(filename=filename) # Clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) def on_breakpoint_double_clicked(self, event): "When a breakpoint on the tree is double clicked, toggle it's status" if event.widget.selection(): parts = event.widget.focus().split(':') bp = self.debugger.breakpoint((parts[0], int(parts[1]))) if bp.enabled: self.debugger.disable_breakpoint(bp) else: self.debugger.enable_breakpoint(bp) # Clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) ###################################################### # Handlers for debugger responses ###################################################### def on_stack(self, stack): "A report of a new stack" # Make sure the stack frame list is displayed self.file_notebook.select(self.stack_frame) # Update the stack list self.stack.update_stack(stack) if len(stack) > 0: # Update the display of the current file line = stack[-1][0] filename = stack[-1][1]['filename'] self.show_file(filename=filename, line=line) # Select the current stack frame in the frame list self.stack.selection_set('frame:%s' % (len(stack) - 1)) else: # No current frame (probably end of execution), # so clear the current line marker self.code.line = None def on_line(self, filename, line): "A single line of code has been executed" self.run_status.set('Line (%s:%s)' % (filename, line)) def on_call(self, args): "A callable has been invoked" self.run_status.set('Call: %s' % args) def on_return(self, retval): "A callable has returned" self.run_status.set('Return: %s' % retval) def on_exception(self, name, value): "An exception has been raised" self.run_status.set('Exception: %s - %s' % (name, value)) tkMessageBox.showwarning(message='%s: %s' % (name, value)) def on_postmortem(self): "An exception has been raised" self.run_status.set('Post mortem mode') tkMessageBox.showerror( message='Entering post mortem mode. Step/Next will restart') def on_restart(self): "The code has finished running, and will start again" self.run_status.set('Not running') tkMessageBox.showinfo( message='Program has finished, and will restart.') def on_info(self, message): "The debugger needs to inform the user of something" tkMessageBox.showinfo(message=message) def on_warning(self, message): "The debugger needs to warn the user of something" tkMessageBox.showwarning(message=message) def on_error(self, message): "The debugger needs to report an error" tkMessageBox.showerror(message=message) def on_breakpoint_enable(self, bp): "A breakpoint has been enabled in the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.enable_breakpoint(bp.line, temporary=bp.temporary) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp) def on_breakpoint_disable(self, bp): "A breakpoint has been disabled in the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.disable_breakpoint(bp.line) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp) def on_breakpoint_ignore(self, bp, count): "A breakpoint has been ignored by the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.ignore_breakpoint(bp.line) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp) def on_breakpoint_clear(self, bp): "A breakpoint has been cleared in the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.clear_breakpoint(bp.line) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp)
class Scrolling_Area(Frame, object): def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, outer_background=None, inner_frame=Frame, **kw): Frame.__init__(self, master, class_=self.__class__) if outer_background: self.configure(background=outer_background) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._width = width self._height = height self.canvas = Canvas(self, background=outer_background, highlightthickness=0, width=width, height=height) self.canvas.grid(row=0, column=0, sticky=N+E+W+S) if scroll_vertically: if yscrollbar is not None: self.yscrollbar = yscrollbar else: self.yscrollbar = Scrollbar(self, orient=VERTICAL) self.yscrollbar.grid(row=0, column=1,sticky=N+S) self.canvas.configure(yscrollcommand=self.yscrollbar.set) self.yscrollbar['command']=self.canvas.yview else: self.yscrollbar = None if scroll_horizontally: if xscrollbar is not None: self.xscrollbar = xscrollbar else: self.xscrollbar = Scrollbar(self, orient=HORIZONTAL) self.xscrollbar.grid(row=1, column=0, sticky=E+W) self.canvas.configure(xscrollcommand=self.xscrollbar.set) self.xscrollbar['command']=self.canvas.xview else: self.xscrollbar = None self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.innerframe = inner_frame(self.canvas, **kw) self.innerframe.pack(anchor=anchor) self.canvas.create_window(0, 0, window=self.innerframe, anchor='nw', tags="inner_frame") self.canvas.bind('<Configure>', self._on_canvas_configure) Mousewheel_Support(self).add_support_to(self.canvas, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar) @property def width(self): return self.canvas.winfo_width() @width.setter def width(self, width): self.canvas.configure(width= width) @property def height(self): return self.canvas.winfo_height() @height.setter def height(self, height): self.canvas.configure(height = height) def set_size(self, width, height): self.canvas.configure(width=width, height = height) def _on_canvas_configure(self, event): width = max(self.innerframe.winfo_reqwidth(), event.width) height = max(self.innerframe.winfo_reqheight(), event.height) self.canvas.configure(scrollregion="0 0 %s %s" % (width, height)) self.canvas.itemconfigure("inner_frame", width=width, height=height) def update_viewport(self): self.update() window_width = self.innerframe.winfo_reqwidth() window_height = self.innerframe.winfo_reqheight() if self._width is None: canvas_width = window_width else: canvas_width = min(self._width, window_width) if self._height is None: canvas_height = window_height else: canvas_height = min(self._height, window_height) self.canvas.configure(scrollregion="0 0 %s %s" % (window_width, window_height), width=canvas_width, height=canvas_height) self.canvas.itemconfigure("inner_frame", width=window_width, height=window_height)
class Display(object): def __init__(self,image): self.map = SVG(image) self.width = self.map.width self.height = self.map.height self.font = "helvetica 16" self.col_bg = "#FFFFFE" self.col_text = "#CCCCCF" self.col_min = (255,14,47) self.col_max = (111,130,158) self.states = ['WA', 'DE', 'DC', 'WI', 'WV', 'HI', 'FL', 'WY', 'NH', 'NJ', 'NM', 'TX', 'LA', 'NC', 'ND', 'NE', 'TN', 'NY', 'PA', 'MT', 'RI', 'NV', 'VA', 'CO', 'AK', 'AL', 'AR', 'VT', 'GA', 'IN', 'IA', 'MA', 'AZ', 'CA', 'ID', 'CT', 'ME', 'MD', 'OH', 'UT', 'MO', 'MN', 'MI', 'KS', 'OK', 'MS', 'SC', 'KY', 'SD', 'OR', 'IL'] self.colorDict = {key:"azure" for key in self.states} def init_interface(self,root): #widget declarations self.searchbar = Entry(root,font=self.font,bg=self.col_bg,foreground=self.col_text) self.execute = Button(root,text="Get Trends",command=self.query) self.scrolltime = Scrollbar(root,orient=HORIZONTAL,command=self.temp) #self.scrolltime.config(command=self.output.yview) #gridding of widgets self.space = Canvas(root,width=self.width,height=self.height,bg=self.col_bg) self.space.grid(row=2,column=2,rowspan=4,columnspan=4,sticky=W+E+N+S) self.searchbar.grid(row=1,column=2,columnspan=3,sticky=W+E+N+S,padx=20,pady=20) self.execute.grid(row=1,column=5,sticky=W)#,sticky=W+E+N+S) self.scrolltime.grid(row=6,column=2,columnspan=4,sticky=W+E+N+S) self.draw_map() def draw_map(self): self.space.delete(ALL) self.map.draw(self.space,self.colorDict) def temp(self,x,y): print "%s,%s"%(x,y) def convert(self,data): print data results = {} for pair in data: (state,factor) = (pair[0], pair[1]) print (state, factor) (r,g,b) = tuple(map(lambda x, y: int((float(factor)/100)*x + (1 - float(factor)/100)*y), self.col_min, self.col_max)) print (r,g,b) results[state] = "#%02x%02x%02x"%(r,g,b) return results def query(self): term = self.searchbar.get() if term !="": self.searchbar.delete(0,'end') colors = Data(term) if colors != []: self.colorDict = self.convert(colors.getData()) self.draw_map() def run(self): root = Tk() self.init_interface(root) root.mainloop()
class MainWindow(object): def __init__(self, root, debugger): ''' ----------------------------------------------------- | main button toolbar | ----------------------------------------------------- | < ma | in content area > | | | | | | | File list | File name | Inspector | | (stack/ | Code area | | | breakpnts) | | | | | | | | | | | ----------------------------------------------------- | status bar area | ----------------------------------------------------- ''' # Obtain and expand the current working directory. base_path = os.path.abspath(os.getcwd()) base_path = os.path.normcase(base_path) + '/' # Create a filename normalizer based on the CWD. self.filename_normalizer = filename_normalizer(base_path) self.debugger = debugger # Associate the debugger with this view. self.debugger.view = self # Root window self.root = root self.root.title('Bugjar') self.root.geometry('1024x768') # Prevent the menus from having the empty tearoff entry self.root.option_add('*tearOff', False) # Catch the close button self.root.protocol("WM_DELETE_WINDOW", self.cmd_quit) # Catch the "quit" event. self.root.createcommand('exit', self.cmd_quit) # Setup the menu self._setup_menubar() # Set up the main content for the window. self._setup_button_toolbar() self._setup_main_content() self._setup_status_bar() # Now configure the weights for the root frame self.root.columnconfigure(0, weight=1) self.root.rowconfigure(0, weight=0) self.root.rowconfigure(1, weight=1) self.root.rowconfigure(2, weight=0) debugger.start() ###################################################### # Internal GUI layout methods. ###################################################### def _setup_menubar(self): # Menubar self.menubar = Menu(self.root) # self.menu_Apple = Menu(self.menubar, name='Apple') # self.menubar.add_cascade(menu=self.menu_Apple) self.menu_file = Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_file, label='File') self.menu_program = Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_program, label='Program') self.menu_help = Menu(self.menubar) self.menubar.add_cascade(menu=self.menu_help, label='Help') # self.menu_Apple.add_command(label='Test', command=self.cmd_dummy) # self.menu_file.add_command(label='New', command=self.cmd_dummy, accelerator="Command-N") self.menu_file.add_command(label='Open...', command=self.cmd_open_file, accelerator="Command-O") self.root.bind('<Command-o>', self.cmd_open_file) # self.menu_file.add_command(label='Close', command=self.cmd_dummy) self.menu_program.add_command(label='Run', command=self.cmd_run, accelerator="R") self.root.bind('<r>', self.cmd_run) self.menu_program.add_command(label='Step', command=self.cmd_step, accelerator="S") self.root.bind('<s>', self.cmd_step) self.menu_program.add_command(label='Next', command=self.cmd_next, accelerator="N") self.root.bind('<n>', self.cmd_next) self.menu_program.add_command(label='Return', command=self.cmd_return, accelerator="BackSpace") self.root.bind('<BackSpace>', self.cmd_return) self.menu_help.add_command(label='Open Documentation', command=self.cmd_bugjar_docs) self.menu_help.add_command(label='Open Bugjar project page', command=self.cmd_bugjar_page) self.menu_help.add_command(label='Open Bugjar on GitHub', command=self.cmd_bugjar_github) self.menu_help.add_command(label='Open BeeWare project page', command=self.cmd_beeware_page) # last step - configure the menubar self.root['menu'] = self.menubar def _setup_button_toolbar(self): ''' The button toolbar runs as a horizontal area at the top of the GUI. It is a persistent GUI component ''' # Main toolbar self.toolbar = Frame(self.root) self.toolbar.grid(column=0, row=0, sticky=(W, E)) # Buttons on the toolbar self.run_button = Button(self.toolbar, text='Run', command=self.cmd_run) self.run_button.grid(column=0, row=0) self.step_button = Button(self.toolbar, text='Step', command=self.cmd_step) self.step_button.grid(column=1, row=0) self.next_button = Button(self.toolbar, text='Next', command=self.cmd_next) self.next_button.grid(column=2, row=0) self.return_button = Button(self.toolbar, text='Return', command=self.cmd_return) self.return_button.grid(column=3, row=0) self.toolbar.columnconfigure(0, weight=0) self.toolbar.rowconfigure(0, weight=0) def _setup_main_content(self): ''' Sets up the main content area. It is a persistent GUI component ''' # Main content area self.content = PanedWindow(self.root, orient=HORIZONTAL) self.content.grid(column=0, row=1, sticky=(N, S, E, W)) # Create subregions of the content self._setup_file_lists() self._setup_code_area() self._setup_inspector() # Set up weights for the left frame's content self.content.columnconfigure(0, weight=1) self.content.rowconfigure(0, weight=1) self.content.pane(0, weight=1) self.content.pane(1, weight=2) self.content.pane(2, weight=1) def _setup_file_lists(self): self.file_notebook = Notebook(self.content, padding=(0, 5, 0, 5)) self.content.add(self.file_notebook) self._setup_stack_frame_list() self._setup_breakpoint_list() def _setup_stack_frame_list(self): self.stack_frame = Frame(self.content) self.stack_frame.grid(column=0, row=0, sticky=(N, S, E, W)) self.file_notebook.add(self.stack_frame, text='Stack') self.stack = StackView(self.stack_frame, normalizer=self.filename_normalizer) self.stack.grid(column=0, row=0, sticky=(N, S, E, W)) # # The tree's vertical scrollbar self.stack_scrollbar = Scrollbar(self.stack_frame, orient=VERTICAL) self.stack_scrollbar.grid(column=1, row=0, sticky=(N, S)) # # Tie the scrollbar to the text views, and the text views # # to each other. self.stack.config(yscrollcommand=self.stack_scrollbar.set) self.stack_scrollbar.config(command=self.stack.yview) # Setup weights for the "stack" tree self.stack_frame.columnconfigure(0, weight=1) self.stack_frame.columnconfigure(1, weight=0) self.stack_frame.rowconfigure(0, weight=1) # Handlers for GUI events self.stack.bind('<<TreeviewSelect>>', self.on_stack_frame_selected) def _setup_breakpoint_list(self): self.breakpoints_frame = Frame(self.content) self.breakpoints_frame.grid(column=0, row=0, sticky=(N, S, E, W)) self.file_notebook.add(self.breakpoints_frame, text='Breakpoints') self.breakpoints = BreakpointView(self.breakpoints_frame, normalizer=self.filename_normalizer) self.breakpoints.grid(column=0, row=0, sticky=(N, S, E, W)) # The tree's vertical scrollbar self.breakpoints_scrollbar = Scrollbar(self.breakpoints_frame, orient=VERTICAL) self.breakpoints_scrollbar.grid(column=1, row=0, sticky=(N, S)) # Tie the scrollbar to the text views, and the text views # to each other. self.breakpoints.config(yscrollcommand=self.breakpoints_scrollbar.set) self.breakpoints_scrollbar.config(command=self.breakpoints.yview) # Setup weights for the "breakpoint list" tree self.breakpoints_frame.columnconfigure(0, weight=1) self.breakpoints_frame.columnconfigure(1, weight=0) self.breakpoints_frame.rowconfigure(0, weight=1) # Handlers for GUI events self.breakpoints.tag_bind('breakpoint', '<Double-Button-1>', self.on_breakpoint_double_clicked) self.breakpoints.tag_bind('breakpoint', '<<TreeviewSelect>>', self.on_breakpoint_selected) self.breakpoints.tag_bind('file', '<<TreeviewSelect>>', self.on_breakpoint_file_selected) def _setup_code_area(self): self.code_frame = Frame(self.content) self.code_frame.grid(column=1, row=0, sticky=(N, S, E, W)) # Label for current file self.current_file = StringVar() self.current_file_label = Label(self.code_frame, textvariable=self.current_file) self.current_file_label.grid(column=0, row=0, sticky=(W, E)) # Code display area self.code = DebuggerCode(self.code_frame, debugger=self.debugger) self.code.grid(column=0, row=1, sticky=(N, S, E, W)) # Set up weights for the code frame's content self.code_frame.columnconfigure(0, weight=1) self.code_frame.rowconfigure(0, weight=0) self.code_frame.rowconfigure(1, weight=1) self.content.add(self.code_frame) def _setup_inspector(self): self.inspector_frame = Frame(self.content) self.inspector_frame.grid(column=2, row=0, sticky=(N, S, E, W)) self.inspector = InspectorView(self.inspector_frame) self.inspector.grid(column=0, row=0, sticky=(N, S, E, W)) # The tree's vertical scrollbar self.inspector_scrollbar = Scrollbar(self.inspector_frame, orient=VERTICAL) self.inspector_scrollbar.grid(column=1, row=0, sticky=(N, S)) # Tie the scrollbar to the text views, and the text views # to each other. self.inspector.config(yscrollcommand=self.inspector_scrollbar.set) self.inspector_scrollbar.config(command=self.inspector.yview) # Setup weights for the "breakpoint list" tree self.inspector_frame.columnconfigure(0, weight=1) self.inspector_frame.columnconfigure(1, weight=0) self.inspector_frame.rowconfigure(0, weight=1) self.content.add(self.inspector_frame) def _setup_status_bar(self): # Status bar self.statusbar = Frame(self.root) self.statusbar.grid(column=0, row=2, sticky=(W, E)) # Current status self.run_status = StringVar() self.run_status_label = Label(self.statusbar, textvariable=self.run_status) self.run_status_label.grid(column=0, row=0, sticky=(W, E)) self.run_status.set('Not running') # Main window resize handle self.grip = Sizegrip(self.statusbar) self.grip.grid(column=1, row=0, sticky=(S, E)) # Set up weights for status bar frame self.statusbar.columnconfigure(0, weight=1) self.statusbar.columnconfigure(1, weight=0) self.statusbar.rowconfigure(0, weight=0) ###################################################### # Utility methods for controlling content ###################################################### def show_file(self, filename, line=None, breakpoints=None): """Show the content of the nominated file. If specified, line is the current line number to highlight. If the line isn't currently visible, the window will be scrolled until it is. breakpoints is a list of line numbers that have current breakpoints. If refresh is true, the file will be reloaded and redrawn. """ # Set the filename label for the current file self.current_file.set(self.filename_normalizer(filename)) # Update the code view; this means changing the displayed file # if necessary, and updating the current line. if filename != self.code.filename: self.code.filename = filename for bp in self.debugger.breakpoints(filename).values(): if bp.enabled: self.code.enable_breakpoint(bp.line) else: self.code.disable_breakpoint(bp.line) self.code.line = line ###################################################### # TK Main loop ###################################################### def mainloop(self): self.root.mainloop() ###################################################### # TK Command handlers ###################################################### def cmd_quit(self): "Quit the debugger" self.debugger.stop() self.root.quit() def cmd_run(self, event=None): "Run until the next breakpoint, or end of execution" self.debugger.do_run() def cmd_step(self, event=None): "Step into the next line of code" self.debugger.do_step() def cmd_next(self, event=None): "Run the next line of code in the current frame" self.debugger.do_next() def cmd_return(self, event=None): "Return to the previous frame" self.debugger.do_return() def cmd_open_file(self, event=None): "Open a file in the breakpoint pane" filename = tkFileDialog.askopenfilename(initialdir=os.path.abspath(os.getcwd())) if filename: # Convert to canonical form filename = os.path.abspath(filename) filename = os.path.normcase(filename) # Show the file contents self.code.filename = filename # Ensure the file appears on the breakpoint list self.breakpoints.insert_filename(filename) # Show the breakpoint panel self.file_notebook.select(self.breakpoints_frame) # ... select the new filename self.breakpoints.selection_set(filename) # .. and clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) def cmd_bugjar_page(self): "Show the Bugjar project page" webbrowser.open_new('http://pybee.org/bugjar') def cmd_bugjar_github(self): "Show the Bugjar GitHub repo" webbrowser.open_new('http://github.com/pybee/bugjar') def cmd_bugjar_docs(self): "Show the Bugjar documentation" # If this is a formal release, show the docs for that # version. otherwise, just show the head docs. if len(NUM_VERSION) == 3: webbrowser.open_new('http://bugjar.readthedocs.org/en/v%s/' % VERSION) else: webbrowser.open_new('http://bugjar.readthedocs.org/') def cmd_beeware_page(self): "Show the BeeWare project page" webbrowser.open_new('http://pybee.org/') ###################################################### # Handlers for GUI actions ###################################################### def on_stack_frame_selected(self, event): "When a stack frame is selected, highlight the file and line" if event.widget.selection(): _, index = event.widget.selection()[0].split(':') line, frame = self.debugger.stack[int(index)] # Display the file in the code view self.show_file(filename=frame['filename'], line=line) # Display the contents of the selected frame in the inspector self.inspector.show_frame(frame) # Clear any currently selected item on the breakpoint tree self.breakpoints.selection_remove(self.breakpoints.selection()) def on_breakpoint_selected(self, event): "When a breakpoint on the tree has been selected, show the breakpoint" if event.widget.selection(): parts = event.widget.focus().split(':') bp = self.debugger.breakpoint((parts[0], int(parts[1]))) self.show_file(filename=bp.filename, line=bp.line) # Clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) def on_breakpoint_file_selected(self, event): "When a file is selected on the breakpoint tree, show the file" if event.widget.selection(): filename = event.widget.focus() self.show_file(filename=filename) # Clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) def on_breakpoint_double_clicked(self, event): "When a breakpoint on the tree is double clicked, toggle it's status" if event.widget.selection(): parts = event.widget.focus().split(':') bp = self.debugger.breakpoint((parts[0], int(parts[1]))) if bp.enabled: self.debugger.disable_breakpoint(bp) else: self.debugger.enable_breakpoint(bp) # Clear any currently selected item on the stack tree self.stack.selection_remove(self.stack.selection()) ###################################################### # Handlers for debugger responses ###################################################### def on_stack(self, stack): "A report of a new stack" # Make sure the stack frame list is displayed self.file_notebook.select(self.stack_frame) # Update the stack list self.stack.update_stack(stack) if len(stack) > 0: # Update the display of the current file line = stack[-1][0] filename = stack[-1][1]['filename'] self.show_file(filename=filename, line=line) # Select the current stack frame in the frame list self.stack.selection_set('frame:%s' % (len(stack) - 1)) else: # No current frame (probably end of execution), # so clear the current line marker self.code.line = None def on_line(self, filename, line): "A single line of code has been executed" self.run_status.set('Line (%s:%s)' % (filename, line)) def on_call(self, args): "A callable has been invoked" self.run_status.set('Call: %s' % args) def on_return(self, retval): "A callable has returned" self.run_status.set('Return: %s' % retval) def on_exception(self, name, value): "An exception has been raised" self.run_status.set('Exception: %s - %s' % (name, value)) tkMessageBox.showwarning(message='%s: %s' % (name, value)) def on_postmortem(self): "An exception has been raised" self.run_status.set('Post mortem mode') tkMessageBox.showerror(message='Entering post mortem mode. Step/Next will restart') def on_restart(self): "The code has finished running, and will start again" self.run_status.set('Not running') tkMessageBox.showinfo(message='Program has finished, and will restart.') def on_info(self, message): "The debugger needs to inform the user of something" tkMessageBox.showinfo(message=message) def on_warning(self, message): "The debugger needs to warn the user of something" tkMessageBox.showwarning(message=message) def on_error(self, message): "The debugger needs to report an error" tkMessageBox.showerror(message=message) def on_breakpoint_enable(self, bp): "A breakpoint has been enabled in the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.enable_breakpoint(bp.line, temporary=bp.temporary) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp) def on_breakpoint_disable(self, bp): "A breakpoint has been disabled in the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.disable_breakpoint(bp.line) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp) def on_breakpoint_ignore(self, bp, count): "A breakpoint has been ignored by the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.ignore_breakpoint(bp.line) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp) def on_breakpoint_clear(self, bp): "A breakpoint has been cleared in the debugger" # If the breakpoint is in the currently displayed file, updated # the display of the breakpoint. if bp.filename == self.code.filename: self.code.clear_breakpoint(bp.line) # ... then update the display of the breakpoint on the tree self.breakpoints.update_breakpoint(bp)
class Scrolling_Area(Frame, object): def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed = 2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, background=None, inner_frame=Frame, **kw): Frame.__init__(self, master, class_="Scrolling_Area", background=background) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._width = width self._height = height self.canvas = Canvas(self, background=background, highlightthickness=0, width=width, height=height) self.canvas.grid(row=0, column=0, sticky=N+E+W+S) if scroll_vertically: if yscrollbar is not None: self.yscrollbar = yscrollbar else: self.yscrollbar = Scrollbar(self, orient=VERTICAL) self.yscrollbar.grid(row=0, column=1,sticky=N+S) self.canvas.configure(yscrollcommand=self.yscrollbar.set) self.yscrollbar['command']=self.canvas.yview else: self.yscrollbar = None if scroll_horizontally: if xscrollbar is not None: self.xscrollbar = xscrollbar else: self.xscrollbar = Scrollbar(self, orient=HORIZONTAL) self.xscrollbar.grid(row=1, column=0, sticky=E+W) self.canvas.configure(xscrollcommand=self.xscrollbar.set) self.xscrollbar['command']=self.canvas.xview else: self.xscrollbar = None self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.innerframe = inner_frame(self.canvas, **kw) self.innerframe.pack(anchor=anchor) self.canvas.create_window(0, 0, window=self.innerframe, anchor='nw', tags="inner_frame") self.canvas.bind('<Configure>', self._on_canvas_configure) Mousewheel_Support(self).add_support_to(self.canvas, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar) @property def width(self): return self.canvas.winfo_width() @width.setter def width(self, width): self.canvas.configure(width= width) @property def height(self): return self.canvas.winfo_height() @height.setter def height(self, height): self.canvas.configure(height = height) def set_size(self, width, height): self.canvas.configure(width=width, height = height) def _on_canvas_configure(self, event): width = max(self.innerframe.winfo_reqwidth(), event.width) height = max(self.innerframe.winfo_reqheight(), event.height) self.canvas.configure(scrollregion="0 0 %s %s" % (width, height)) self.canvas.itemconfigure("inner_frame", width=width, height=height) def update_viewport(self): self.update() window_width = self.innerframe.winfo_reqwidth() window_height = self.innerframe.winfo_reqheight() if self._width is None: canvas_width = window_width else: canvas_width = min(self._width, window_width) if self._height is None: canvas_height = window_height else: canvas_height = min(self._height, window_height) self.canvas.configure(scrollregion="0 0 %s %s" % (window_width, window_height), width=canvas_width, height=canvas_height) self.canvas.itemconfigure("inner_frame", width=window_width, height=window_height)
class MacroFrame(Frame): def __init__(self, parent): Frame.__init__(self, parent, background="white") self.parent = parent self.numStates = 0 self.initUI() def initUI(self): self.columnconfigure(0, weight=0) self.columnconfigure(1, weight=0) self.columnconfigure(2, weight=1) self.columnconfigure(3, weight=1) self.rowconfigure(0, weight=1) self.commandFrame = Frame(self, background="white") self.commandFrame.grid(row=0, column=0, columnspan=5, sticky=W + E) self.commandFrame.columnconfigure(1, weight=1) self.btnCommand = Button(self.commandFrame, text="Run") self.btnCommand.grid(row=0, column=0) self.strCommand = StringVar() self.entCommand = Entry(self.commandFrame, textvariable=self.strCommand) self.entCommand.grid(row=0, column=1, sticky=W + E) self.lstMacro = Listbox(self) self.lstMacro.grid(row=1, column=0, sticky=N + S + W + E) self.treeview = Treeview(self, columns=("Angle"), displaycolumns="#all", selectmode="browse") self.treeview.grid(row=1, column=1, columnspan=4, sticky=N + S + W + E) self.treeScrollbar = Scrollbar(self) self.treeScrollbar.grid(row=1, column=5, sticky=N + S) self.treeview.config(yscrollcommand=self.treeScrollbar.set) self.treeScrollbar.config(command=self.treeview.yview) self.btnFrame = Frame(self, background="white") self.btnFrame.grid(row=2, column=0, columnspan=5, sticky=W + E) self.btnRun = Button(self.btnFrame, text="Run", command=self.runMacro) self.btnRun.grid(row=0, column=0) self.btnStop = Button(self.btnFrame, text="Stop") self.btnStop.grid(row=0, column=1) self.btnSaveMacro = Button(self.btnFrame, text="Save Macro", command=self.saveMacro) self.btnSaveMacro.grid(row=0, column=2) self.btnDeleteMacro = Button(self.btnFrame, text="Delete Macro") self.btnDeleteMacro.grid(row=0, column=3) self.btnDeleteState = Button(self.btnFrame, text="Delete State") self.btnDeleteState.grid(row=0, column=4) def addState(self, robot): stateName = "state" + str(self.numStates) self.treeview.insert("", END, iid=stateName, text=stateName) limbNum = 0 for limb in robot.getLimbs(): limbName = "limb" + str(limbNum) self.treeview.insert(stateName, END, iid=stateName + "_" + limbName, text=limbName) partNum = 0 for part in limb.getComponents(): partName = "joint" + str(partNum) if isinstance(part, Joint): self.treeview.insert( stateName + "_" + limbName, END, iid=stateName + "_" + limbName + "_" + partName, text=partName, values=[part.angle], ) partNum += 1 limbNum += 1 self.numStates += 1 def getState(self, stateNum, robot): stateName = "state" + str(stateNum) limbNum = 0 for limb in robot.getLimbs(): limbName = "limb" + str(limbNum) partNum = 0 for part in limb.getComponents(): partName = "joint" + str(partNum) if isinstance(part, Joint): part.setAngle(int(self.treeview.item(stateName + "_" + limbName + "_" + partName, "values")[0])) partNum += 1 limbNum += 1 def runMacro(self): thread = threading.Thread(target=self.updateState) thread.start() def updateState(self): for i in range(self.numStates): self.getState(i, self.parent.robotFrame.robot) time.sleep(0.1) def saveMacro(self): pass
def initUI(self): # Configures the GUI self.parent.title("Neural Networks for Handwritten Digit Recognition") self.style = Style() self.pack(fill=BOTH, expand=1) # Creates a grid 5x4 in to which we will place elements. self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=0) self.columnconfigure(3, weight=0) self.columnconfigure(4, weight=0) self.columnconfigure(5, weight=0) self.columnconfigure(6, weight=0) self.columnconfigure(7, weight=0) self.columnconfigure(8, weight=0) self.rowconfigure(1, weight=1) self.rowconfigure(2, weight=0) self.rowconfigure(3, weight=0) self.rowconfigure(4, weight=0) # Create explanation text for app explanation = """ "This program is capable of utilizing different learning algorithms as a mean to achieve a +90% accuracy in recognizing MNIST digits based on Neural Networks as a way of detecting the different numbers and classifying them correctly" \n Select the checkboxes that you wish to utilize ([ ] Learn from starting random values, [X] Learn from preexisting data / [ ] Do not save the results [X] Save the final values of the Weights and Biases), Press the Run button to start the Neural Network\n""" self.exp = Label(self, text=explanation) self.exp.grid( row=2, column=1, columnspan=4, padx=2, pady=2, ) # Creates the Y scrollbar that is spawned through the whole grid yscrollbar = Scrollbar(self, orient=VERTICAL) yscrollbar.grid(row=1, column=8, sticky=N + S) # Creates the text area and spawns it through the whole window self.textarea = Text(self, wrap=NONE, bd=0, yscrollcommand=yscrollbar.set) self.textarea.grid(row=1, column=1, columnspan=4, rowspan=1, padx=0, sticky=E + W + S + N) yscrollbar.config(command=self.textarea.yview) # Creates the run button in the lower row self.runButton = Button(self, text="Run Neural Network") self.runButton.grid(row=4, column=1, padx=5, pady=5, sticky=W) self.runButton.bind("<ButtonRelease-1>", self.runNN) # Creates the variable initialization checkbox in the lower row self.initvalVar = StringVar() initvalCheck = Checkbutton(self, text="Learn from Initial Values", variable=self.initvalVar, onvalue="-l", offvalue="") initvalCheck.grid(row=4, column=2, padx=5, pady=5) # Creates the save variables checkbox in the lower row self.saveValVar = StringVar() saveVal = Checkbutton(self, text="Save final Weights & Biases", variable=self.saveValVar, onvalue="-s", offvalue="") saveVal.grid(row=4, column=3, padx=5, pady=5) # Creates the clear button for the textbox self.clearButton = Button(self, text="Clear") self.clearButton.grid(row=4, column=4, padx=5, pady=5) self.clearButton.bind("<ButtonRelease-1>", self.clearText) # Defines the tags that are used to colorise the text added to the text widget. self.textarea.tag_config("errorstring", foreground="#CC0000") # Red Color self.textarea.tag_config("infostring", foreground="#008800") # Green Color
class wine_DB_manager: #Class for wrapping TKinter widgets def __init__(self, master): #Initilize the attributes of the class master.minsize(width=600, height=700) #Set window size and title master.title("Member and Store Manager") master.grid_columnconfigure( 0, weight=1 ) #Configure first and last columns for centering columns 1-5 master.grid_columnconfigure(6, weight=1) master.grid_rowconfigure( 12, weight=1 ) #Configure last row for filling left over space at the bottom self.imp_store_label = Label( master, text="Import Store Information (.CSV)" ) #Initilize lable, entry, and buttons for importing stores self.imp_store_entry = Entry(master, width=70) self.imp_store_browse_button = Button( master, text="Browse", command=lambda: self.browse_for_CSV("store")) self.imp_store_import_button = Button( master, text="Import", command=lambda: self.import_to_DB(self.imp_store_entry.get(), "store")) self.imp_member_label = Label( master, text="Import Member Information (.CSV)" ) #Initilize lable, entry, and buttons for importing members self.imp_member_entry = Entry(master, width=70) self.imp_member_browse_button = Button( master, text="Browse", command=lambda: self.browse_for_CSV("member")) self.imp_member_import_button = Button( master, text="Import", command=lambda: self.import_to_DB(self.imp_member_entry.get(), "member")) self.horz_divider = Frame( master, height=1, width=500, bg="black" ) #Initilize a frame shaped as a horizonal line as a divider self.view_all_members_button = Button( master, text="View All Members", width=17, command=lambda: self.select_all_members() ) #Initilize button for selecting all members and displaying them in tree self.zip_label = Label( master, text="Zip Code" ) #Initilize lable, entry, combobox, and buttons for self.zip_entry = Entry( master, width=10) #finding who paid dues by zip code and month paid self.month_label = Label(master, text="Month") self.month_combobox = Combobox(master, width=10) self.month_combobox['values'] = ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') self.find_users_that_paid = Button( master, text="Current Paid Users", width=20, command=lambda: self.select_paid_dues_month( self.zip_entry.get(), self.month_combobox.current())) self.state_label = Label( master, text="State") #Initilize lable, entry, combobox, and buttons for self.state_combobox = Combobox( master, width=3) #finding users who have joined the club since a date self.state_combobox['values'] = ('MD', 'NC', 'PA', 'VA', 'WV' ) #and belong to a specific state self.date_label = Label(master, text="Date (YYYY-MM-DD)") self.date_entry = Entry(master, width=10) self.find_users_that_joined = Button( master, text="Users Joined Since", width=20, command=lambda: self.select_users_joined_since( self.state_combobox.get(), self.date_entry.get())) self.users_that_love_total_wine = Button( master, text="Users that Love Total Wine", width=20, command=lambda: self.select_users_love_Tot_Wine( )) #Initilize button for finding users that love Total Wines self.users_favorite_stores = Button( master, text="User's Favorite Stores", width=20, command=lambda: self.select_users_fav_stores() ) #Initilize button for finding users, their favorite stores, and store locations self.table_tree = Treeview( master, selectmode="extended") #Initilize tree for data viewing self.table_tree["columns"] = ( "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven") #Provide max column count and identifiers for columns in self.table_tree[ "columns"]: #For loop to add all columns self.table_tree.column(columns, width=70, anchor=W) self.table_tree['show'] = 'headings' #Remove empty identity column self.vert_scroll_bar = Scrollbar( orient="vertical", command=self.table_tree.yview) #Initilize scroll bar self.table_tree.configure(yscrollcommand=self.vert_scroll_bar.set ) #Add scroll bar to table_tree self.imp_store_label.grid( sticky="W", row=1, column=1, padx=10, pady=(20, 0)) #Grid positioning for all initialized attributes self.imp_store_entry.grid(sticky="W", row=2, column=1, columnspan=3, padx=10) self.imp_store_browse_button.grid(row=2, column=4, padx=10) self.imp_store_import_button.grid(row=2, column=5) self.imp_member_label.grid(sticky="W", row=3, column=1, padx=10) self.imp_member_entry.grid(sticky="W", row=4, column=1, columnspan=3, padx=10) self.imp_member_browse_button.grid(row=4, column=4, padx=10) self.imp_member_import_button.grid(row=4, column=5) self.horz_divider.grid(row=5, column=0, columnspan=7, pady=20) self.view_all_members_button.grid(row=6, column=1, columnspan=5) self.zip_label.grid(sticky="W", row=7, column=1, pady=(15, 0)) self.zip_entry.grid(sticky="W", row=8, column=1, pady=5) self.month_label.grid(sticky="W", row=7, column=1, padx=(100, 0), pady=(15, 0)) self.month_combobox.grid(sticky="W", row=8, column=1, padx=(100, 0), pady=5) self.find_users_that_paid.grid(sticky="W", row=9, column=1, columnspan=3, pady=5) self.state_label.grid(sticky="W", row=7, column=4, pady=(15, 0)) self.state_combobox.grid(sticky="W", row=8, column=4, pady=5) self.date_label.grid(sticky="W", row=7, column=4, columnspan=3, padx=(85, 0), pady=(15, 0)) self.date_entry.grid(sticky="W", row=8, column=4, columnspan=2, padx=(85, 0), pady=5) self.find_users_that_joined.grid(sticky="W", row=9, column=4, columnspan=2, pady=5) self.users_that_love_total_wine.grid(sticky="W", row=10, column=1, columnspan=3, pady=(15, 0)) self.users_favorite_stores.grid(sticky="W", row=10, column=4, columnspan=2, pady=(15, 0)) self.table_tree.grid(sticky="NWES", row=11, column=0, columnspan=7, rowspan=2, pady=10, padx=(10, 0)) self.vert_scroll_bar.grid(sticky="NWES", row=11, column=7, rowspan=2, pady=10, padx=(0, 10)) def browse_for_CSV( self, CSV_type ): #Class method for browse buttons. Used for passing file path to TKinter entries file = tkFileDialog.askopenfile( parent=root, mode='rb', title='Choose a file') #Opens browse for file window if (file != None): #If file exists read into data and close file data = file.read() file.close() if ( CSV_type == "store" ): #In order to resuse code, this method works for both buttons self.imp_store_entry.delete( 0, END) #through using a passed button identity variable self.imp_store_entry.insert(0, os.path.abspath(file.name)) else: self.imp_member_entry.delete(0, END) #Empties entry widget self.imp_member_entry.insert( 0, os.path.abspath(file.name) ) #Inserts file path into entry widget using os.path import else: #Catches no file selected possibility tkMessageBox.showinfo("Error", "No File Selected") return None def create_DB_connection( self ): #Class method for opening a database connection to the pythonsqlite.db file try: DB_file = "SQLite_db\pythonsqlite.db" conn = sqlite3.connect(DB_file) return conn except Error as e: #Catches non-connectivity errors print(e) return None def import_to_DB( self, file_path, CSV_type ): #Class method for import buttons. Used to open csv files from path string #in entry widgets. Then opens db connection to import data to db try: self.CSV_file = open(file_path, "r") #Opens CSV file in read mode except IOError as e: #Catches file not found error tkMessageBox.showinfo("Error", "File Not Found") return CSV_reader = csv.reader( self.CSV_file ) #Reads CSV file into CSV_reader using csv.reader import conn = self.create_DB_connection() #Calls for DB connection to open cur = conn.cursor() if ( CSV_type == "store" ): #In order to resuse code, this method works for both buttons by passed type. if (next(CSV_reader)[0][0:8] != "Store id"): #Checks CSV for proper store headings tkMessageBox.showinfo( "CSV Type Error", "Please Import a CSV file formated for store data.") self.CSV_file.close( ) #If not proper headings close file and display message return else: #Create table Stores cur.execute( '''CREATE TABLE IF NOT EXISTS Stores ( store_id INTEGER PRIMARY KEY, store_name VARCHAR, location VARCHAR)''') for row in CSV_reader: #Insert new values for each row in CSV cur.execute( '''INSERT OR IGNORE INTO Stores ( store_id, store_name, location) VALUES (?, ?, ?)''', row) tkMessageBox.showinfo( "Success!", "Successfully Updated the Database") #Display confirmation self.imp_store_entry.delete(0, END) #Clear import entry else: if (next(CSV_reader)[0][0:6] != "Member"): #Checks CSV for proper member headings tkMessageBox.showinfo( "CSV Type Error", "Please Import a CSV file formated for member data.") self.CSV_file.close( ) #If not proper headings close file and display message return else: #Create table Members cur.execute('''CREATE TABLE IF NOT EXISTS Members ( member_id INTEGER PRIMARY KEY, last_name VARCHAR, first_name VARCHAR, street VARCHAR, city VARCHAR, state VARCHAR, zip VARCHAR, phone VARCHAR, favorite_store INTEGER, date_joined DATE, dues_paid DATE, FOREIGN KEY(favorite_store) REFERENCES Stores(store_id))''') for row in CSV_reader: #Insert new values for each row in CSV cur.execute( '''INSERT OR IGNORE INTO Members ( member_id, last_name, first_name, street, city , state, zip, phone, favorite_store, date_joined, dues_paid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', row) tkMessageBox.showinfo("Success!", "Successfully Updated the Database") self.imp_member_entry.delete(0, END) self.CSV_file.close() #Close CSV file conn.commit() #Commit DB changes conn.close() #Close DB Connection return None def generate_member_column_names( self ): #Class utility method for adding member column headers to tree all_member_column_names = ("Member ID", "Last Name", "First Name", "Street", "City", "State", "Zip Code", "Phone", "Favorite Store", "Date Joined", "Dues Paid") for index, columns in enumerate(self.table_tree["columns"] ): #For loop to add all column headers self.table_tree.heading(columns, text=all_member_column_names[index]) return None def select_all_members( self ): #Class method for View All Members Buttons and outputs new data to tree cur = self.create_DB_connection().cursor( ) #Calls for DB connection to open cur.execute("SELECT * FROM Members ORDER BY last_name ASC" ) #SQL Statement to SELECT all members and their data. rows = cur.fetchall() #Fetches data into rows self.table_tree.delete(*self.table_tree.get_children() ) #Deletes old data in tree if present self.generate_member_column_names( ) #Call utility to generate column member headers for index, row in enumerate( rows): #Inserts sql data into tree rows for viewing self.table_tree.insert('', index, values=(row)) self.create_DB_connection().close() #Close DB Connection return None def select_paid_dues_month( self, zip, month ): #Class method for Current Paid User Button and outputs new data to tree month = month + 1 #Add 1 to month index count since it range is 0-11 and months are 1-12 if (month < 10): self.month_string = "0" + str(month) cur = self.create_DB_connection().cursor( ) #Calls for DB connection to open if (month not in range(1, 12)): #If no month selected display message tkMessageBox.showinfo("Error", "No Month Selected") return if (len(zip) != 5): #If zip not 5 digits display message tkMessageBox.showinfo("Error", "Enter a Zip Code") return try: cur.execute("SELECT * FROM Members WHERE zip = " + zip + " AND strftime('%m',dues_paid) = '" + self.month_string + "'") #If zip is numeric execute Select Statement except Error as e: #Catches error if zip not numeric tkMessageBox.showinfo("Error", "Enter a Zip Code") return rows = cur.fetchall() self.table_tree.delete(*self.table_tree.get_children() ) #Deletes old data in tree if present self.generate_member_column_names( ) #Call utility to generate column member headers for index, row in enumerate( rows): #Inserts sql data into tree rows for viewing self.table_tree.insert('', index, values=(row)) self.create_DB_connection().close() #Close DB Connection return None def select_users_joined_since( self, state, the_date ): #Class method for Current Paid User Button and outputs new data to tree cur = self.create_DB_connection().cursor( ) #Calls for DB connection to open if state == "": #if no state selected display message tkMessageBox.showinfo("Error", "No State Selected") return try: #Checks date format YYYY-MM-DD datetime.datetime.strptime(the_date, '%Y-%m-%d') except ValueError: #Catches invalid date format tkMessageBox.showinfo( "Error", "Incorrect data format, should be YYYY-MM-DD") return cur.execute( "SELECT * FROM Members WHERE state = '" + state + "' AND date_joined > '" + the_date + "'" ) #Execute Select members Where state and date are what user selected. rows = cur.fetchall() self.table_tree.delete(*self.table_tree.get_children() ) #Deletes old data in tree if present self.generate_member_column_names( ) #Call utility to generate column member headers for index, row in enumerate( rows): #Inserts sql data into tree rows for viewing self.table_tree.insert('', index, values=(row)) self.create_DB_connection().close() #Close DB Connection return None def select_users_love_Tot_Wine( self ): #Class method for Users That Love Tot Wine and outputs new data to tree cur = self.create_DB_connection().cursor( ) #Calls for DB connection to open #Execute Select Where, and Join on foreign key values. cur.execute('''SELECT Members.last_name, Members.first_name, Stores.store_name FROM Members JOIN Stores ON Members.favorite_store = Stores.store_id WHERE favorite_store = '3' ''') rows = cur.fetchall() self.table_tree.delete(*self.table_tree.get_children() ) #Deletes old data in tree if present all_member_column_names = ("Last Name", "First Name", "Favorite Store", "", "", "", "", "", "", "", "") for index, columns in enumerate( self.table_tree["columns"] ): #Generate *custom* column member headers self.table_tree.heading(columns, text=all_member_column_names[index]) for index, row in enumerate( rows): #Inserts sql data into tree rows for viewing self.table_tree.insert('', index, values=(row)) self.create_DB_connection().close() #Close DB Connection return None def select_users_fav_stores( self ): #Class method for Users Favorite Stores and outputs new data to tree cur = self.create_DB_connection().cursor( ) #Calls for DB connection to open #Execute Select Where, and Join on foreign key values. cur.execute('''SELECT Members.last_name, Members.first_name, Stores.store_name, Stores.location FROM Members JOIN Stores ON Members.favorite_store = Stores.store_id ''') rows = cur.fetchall() self.table_tree.delete(*self.table_tree.get_children() ) #Deletes old data in tree if present all_member_column_names = ("Last Name", "First Name", "Favorite Store", "Location", "", "", "", "", "", "", "") for index, columns in enumerate( self.table_tree["columns"] ): #Generate *custom* column member headers self.table_tree.heading(columns, text=all_member_column_names[index]) for index, row in enumerate( rows): #Inserts sql data into tree rows for viewing self.table_tree.insert('', index, values=(row)) self.create_DB_connection().close() #Close DB Connection return None
class Ordered_Listbox(Frame): def __init__(self, master, data=None, ascending_order=True, ignore_case=False, autoscroll=False, vscrollbar=True, hscrollbar=False, scrollbar_background=None, scrollbar_troughcolor=None, **kwargs): Frame.__init__(self, master) self._ignore_case = ignore_case self._ascending_order = ascending_order master.grid_rowconfigure(0, weight=1) master.grid_columnconfigure(0, weight=1) self._listbox = Listbox(self, *kwargs) self._listbox.grid(row=0, column=0, sticky=N + E + W + S) scrollbar_kwargs = {} if scrollbar_background is not None: scrollbar_kwargs["background"] = scrollbar_background if scrollbar_troughcolor is not None: scrollbar_kwargs["throughcolor"] = scrollbar_troughcolor if vscrollbar: self._vbar = Scrollbar(self, takefocus=0, command=self._listbox.yview, **scrollbar_kwargs) self._vbar.grid(row=0, column=1, sticky=N + S) if autoscroll: self._listbox.config(yscrollcommand=lambda f, l: make_autoscroll(self._vbar, f, l)) else: self._listbox.config(yscrollcommand=self._vbar.set) if hscrollbar: self._hbar = Scrollbar(self, takefocus=0, command=self._listbox.xview, **scrollbar_kwargs) self._hbar.grid(row=0, column=1, sticky=E + W) if autoscroll: self._listbox.config(xscrollcommand=lambda f, l: make_autoscroll(self._hbar, f, l)) else: self._listbox.config(xscrollcommand=self._hbar.set) if data is not None: for item in data: self.add_item(item) def add_item(self, item): list_of_items = self._listbox.get(0, END) index = bisect(list_of_items, item, ignore_case=self._ignore_case, ascending_order=self._ascending_order) self._listbox.insert(index, item) def delete_item(self, item): list_of_items = self._listbox.get(0, END) index = bisect(list_of_items, item, ignore_case=self._ignore_case, ascending_order=self._ascending_order) self._listbox.delete(index - 1) def selected_items(self): list_of_items = [] for index in self._listbox.curselection(): list_of_items.append(self._listbox.get(index)) return list_of_items def selected_item(self): return self._listbox.curselection()[0] def deselect_all(self): self._listbox.selection_clear(0, END) def select(self, item): index = self.index(item) if index is None: return self._listbox.selection_set(index) def deselect(self, item): index = self.index(item) if index is None: return self._listbox.selection_clear(index) def index(self, item): list_of_items = self._listbox.get(0, END) try: index = list_of_items.index(item) except ValueError: return None return index def bind(self, event, handler): self._listbox.bind(event, handler) def clear(self): self._listbox.delete(1, END) def __iter__(self): return self.items @property def items(self): return self._listbox.get(0, END)
class Multicolumn_Listbox(object): _style_index = 0 class List_Of_Rows(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.row_data(index) def get(self, index): return Row(self._multicolumn_listbox, index) def insert(self, data, index=None): self._multicolumn_listbox.insert_row(data, index) def delete(self, index): self._multicolumn_listbox.delete_row(index) def update(self, index, data): self._multicolumn_listbox.update_row(index, data) def select(self, index): self._multicolumn_listbox.select_row(index) def deselect(self, index): self._multicolumn_listbox.deselect_row(index) def set_selection(self, indices): self._multicolumn_listbox.set_selection(indices) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_row(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_row(index) def __len__(self): return self._multicolumn_listbox.number_of_rows class List_Of_Columns(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.get_column(index) def get(self, index): return Column(self._multicolumn_listbox, index) def delete(self, index): self._multicolumn_listbox.delete_column(index) def update(self, index, data): self._multicolumn_listbox.update_column(index, data) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_column(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_column(index) def __len__(self): return self._multicolumn_listbox.number_of_columns def __init__(self, master, columns, data=None, command=None, sort=True, select_mode=None, heading_anchor=CENTER, cell_anchor=W, style=None, height=None, padding=None, adjust_heading_to_content=False, striped_rows=None, selection_background=None, selection_foreground=None, field_background=None, heading_font=None, heading_background=None, heading_foreground=None, cell_pady=2, cell_background=None, cell_foreground=None, cell_font=None, headers=True, right_click_command=None): self._striped_rows = striped_rows self._columns = columns self._number_of_rows = 0 self._number_of_columns = len(columns) self.row = self.List_Of_Rows(self) self.column = self.List_Of_Columns(self) s = Style() if style is None: style_name = "Multicolumn_Listbox%s.Treeview" % self._style_index self._style_index += 1 else: style_name = style style_map = {} if selection_background is not None: style_map["background"] = [('selected', selection_background)] if selection_foreground is not None: style_map["foreground"] = [('selected', selection_foreground)] if style_map: s.map(style_name, **style_map) style_config = {} if cell_background is not None: style_config["background"] = cell_background if cell_foreground is not None: style_config["foreground"] = cell_foreground if cell_font is None: font_name = s.lookup(style_name, "font") cell_font = nametofont(font_name) else: if not isinstance(cell_font, Font): if isinstance(cell_font, basestring): cell_font = nametofont(cell_font) else: if len(cell_font) == 1: cell_font = Font(family=cell_font[0]) elif len(cell_font) == 2: cell_font = Font(family=cell_font[0], size=cell_font[1]) elif len(cell_font) == 3: cell_font = Font(family=cell_font[0], size=cell_font[1], weight=cell_font[2]) else: raise ValueError( "Not possible more than 3 values for font") style_config["font"] = cell_font self._cell_font = cell_font self._rowheight = cell_font.metrics("linespace") + cell_pady style_config["rowheight"] = self._rowheight if field_background is not None: style_config["fieldbackground"] = field_background s.configure(style_name, **style_config) heading_style_config = {} if heading_font is not None: heading_style_config["font"] = heading_font if heading_background is not None: heading_style_config["background"] = heading_background if heading_foreground is not None: heading_style_config["foreground"] = heading_foreground heading_style_name = style_name + ".Heading" s.configure(heading_style_name, **heading_style_config) treeview_kwargs = {"style": style_name} if height is not None: treeview_kwargs["height"] = height if padding is not None: treeview_kwargs["padding"] = padding if headers: treeview_kwargs["show"] = "headings" else: treeview_kwargs["show"] = "" if select_mode is not None: treeview_kwargs["selectmode"] = select_mode self.interior = Treeview(master, columns=columns, **treeview_kwargs) # tjw Scrollbar add self.scrollbar = Scrollbar(master, orient=VERTICAL, command=self.interior.yview) self.interior.configure(yscrollcommand=self.scrollbar.set) self.scrollbar.grid(row=1, column=len(columns), sticky='NSE') self.interior.grid(row=1, column=0) #master.grid_columnconfigure(0, weight=1) #master.grid_columnconfigure(1, weight=1) if command is not None: self._command = command self.interior.bind("<<TreeviewSelect>>", self._on_select) if right_click_command is not None: self._right_click_command = right_click_command self.interior.bind("<Button-3>", self._on_right_click) for i in range(0, self._number_of_columns): if sort: self.interior.heading( i, text=columns[i], anchor=heading_anchor, command=lambda col=i: self.sort_by(col, descending=False)) else: self.interior.heading(i, text=columns[i], anchor=heading_anchor) if adjust_heading_to_content: self.interior.column(i, width=Font().measure(columns[i])) self.interior.column(i, anchor=cell_anchor) if data is not None: for row in data: self.insert_row(row) @property def row_height(self): return self._rowheight @property def font(self): return self._cell_font def configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None): kwargs = {} for config_name in ("width", "anchor", "stretch", "minwidth"): config_value = locals()[config_name] if config_value is not None: kwargs[config_name] = config_value self.interior.column('#%s' % (index + 1), **kwargs) def row_data(self, index): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d" % index) return self.item_ID_to_row_data(item_ID) def update_row(self, index, data): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d" % index) if len(data) == len(self._columns): self.interior.item(item_ID, values=data) else: raise ValueError("The multicolumn listbox has only %d columns" % self._number_of_columns) def delete_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.delete(item_ID) self._number_of_rows -= 1 if self._striped_rows: for i in range(index, self._number_of_rows): self.interior.tag_configure(list_of_items[i + 1], background=self._striped_rows[i % 2]) def insert_row(self, data, index=None): if len(data) != self._number_of_columns: raise ValueError("The multicolumn listbox has only %d columns" % self._number_of_columns) if index is None: index = self._number_of_rows - 1 item_ID = self.interior.insert('', index, values=data) self.interior.item(item_ID, tags=item_ID) self._number_of_rows += 1 if self._striped_rows: list_of_items = self.interior.get_children() self.interior.tag_configure(item_ID, background=self._striped_rows[index % 2]) for i in range(index + 1, self._number_of_rows): self.interior.tag_configure(list_of_items[i], background=self._striped_rows[i % 2]) def column_data(self, index): return [ self.interior.set(child_ID, index) for child_ID in self.interior.get_children('') ] def update_column(self, index, data): for i, item_ID in enumerate(self.interior.get_children()): data_row = self.item_ID_to_row_data(item_ID) data_row[index] = data[i] self.interior.item(item_ID, values=data_row) return data def clear(self): # Another possibility: # self.interior.delete(*self.interior.get_children()) for row in self.interior.get_children(): self.interior.delete(row) self._number_of_rows = 0 def update(self, data): self.clear() for row in data: self.insert_row(row) def focus(self, index=None): if index is None: return self.interior.item(self.interior.focus()) else: item = self.interior.get_children()[index] self.interior.focus(item) def state(self, state=None): if state is None: return self.interior.state() else: self.interior.state(state) @property def number_of_rows(self): return self._number_of_rows @property def number_of_columns(self): return self._number_of_columns def toogle_selection(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_toggle(item_ID) def select_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_add(item_ID) def deselect_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_remove(item_ID) def deselect_all(self): self.interior.selection_remove(self.interior.selection()) def set_selection(self, indices): list_of_items = self.interior.get_children() self.interior.selection_set(" ".join(list_of_items[row_index] for row_index in indices)) @property def selected_rows(self): data = [] for item_ID in self.interior.selection(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @property def indices_of_selected_rows(self): list_of_indices = [] for index, item_ID in enumerate(self.interior.get_children()): if item_ID in self.interior.selection(): list_of_indices.append(index) return list_of_indices def delete_all_selected_rows(self): selected_items = self.interior.selection() for item_ID in selected_items: self.interior.delete(item_ID) number_of_deleted_rows = len(selected_items) self._number_of_rows -= number_of_deleted_rows return number_of_deleted_rows def _on_select(self, event): for item_ID in event.widget.selection(): data_row = self.item_ID_to_row_data(item_ID) self._command(data_row) def _on_right_click(self, event): item_ID = event.widget.identify_row(event.y) data_row = self.item_ID_to_row_data(item_ID) if data_row: self._right_click_command(data_row) def item_ID_to_row_data(self, item_ID): item = self.interior.item(item_ID) return item["values"] @property def table_data(self): data = [] for item_ID in self.interior.get_children(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @table_data.setter def table_data(self, data): self.update(data) def cell_data(self, row, column): """Get the value of a table cell""" try: item = self.interior.get_children()[row] except IndexError: raise ValueError("Row index out of range: %d" % row) return self.interior.set(item, column) def update_cell(self, row, column, value): """Set the value of a table cell""" item_ID = self.interior.get_children()[row] data = self.item_ID_to_row_data(item_ID) data[column] = value self.interior.item(item_ID, values=data) def __getitem__(self, index): if isinstance(index, tuple): row, column = index return self.cell_data(row, column) else: raise Exception("Row and column indices are required") def __setitem__(self, index, value): if isinstance(index, tuple): row, column = index self.update_cell(row, column, value) else: raise Exception("Row and column indices are required") def bind(self, event, handler): self.interior.bind(event, handler) def sort_by(self, col, descending): """ sort tree contents when a column header is clicked """ # grab values to sort data = [(self.interior.set(child_ID, col), child_ID) for child_ID in self.interior.get_children('')] # if the data to be sorted is numeric change to float try: data = [(float(number), child_ID) for number, child_ID in data] # now sort the data in place data.sort(reverse=descending) except ValueError: # now sort the strings in place, ignoring case data.sort(reverse=descending, key=lambda x: x[0].lower()) for idx, item in enumerate(data): self.interior.move(item[1], '', idx) # switch the heading so that it will sort in the opposite direction self.interior.heading( col, command=lambda col=col: self.sort_by(col, not descending)) if self._striped_rows: list_of_items = self.interior.get_children('') for i in range(len(list_of_items)): self.interior.tag_configure(list_of_items[i], background=self._striped_rows[i % 2]) def destroy(self): self.interior.destroy() def item_ID(self, index): return self.interior.get_children()[index]
class JobList(Frame): # NOTE: job_params contains information about a Job in the Joblist # NOTE: plot_args contains information about plotting information, which occurs after the jobs have been and the data files have been created def __init__(self, parent=None, **kwargs): Frame.__init__(self, parent) self.parent = parent self.job_list_yscroll = Scrollbar(self, orient=Tkinter.VERTICAL) self.job_list_xscroll = Scrollbar(self, orient=Tkinter.HORIZONTAL) self.job_list = Listbox(self, xscrollcommand=self.job_list_xscroll, yscrollcommand=self.job_list_yscroll) self.job_list_xscroll['command'] = self.job_list.xview self.job_list_yscroll['command'] = self.job_list.yview self.new_job_frame = Frame(self) add_icon_filename = kwargs['add_icon_filename'] if 'add_icon_filename' in kwargs else None if add_icon_filename == None: self.add_job_button = Button(self.new_job_frame, text='Add Job', command=self.on_add) else: add_icon = PhotoImage(file=add_icon_filename) self.add_job_button = Button(self.new_job_frame, text='Add Job', compound='bottom', image=add_icon, command=self.on_add) self.remove_job_button = Button(self.new_job_frame, text='Remove Job', command=self.on_remove) self.progress_frame = Frame(self) self.progress_value = Tkinter.IntVar() self.progress_bar = Progressbar(self.progress_frame, variable=self.progress_value) self.button_frame = Frame(self) self.process_button = ProcessButton(parent=self.button_frame, start_jobs=self.start_jobs) self.quit_button = QuitButton(parent=self.button_frame, close_other_windows=self.close_top_level_windows) self.run_job = kwargs['run_job'] if 'run_job' in kwargs else None self.create_plots = kwargs['create_plots'] if 'create_plots' in kwargs else None self.log_filename = kwargs['log_filename'] if 'log_filename' in kwargs else None self.bind('<<AskToClearJobs>>', self.ask_to_clear_jobs) self.bind('<<AskToPlotGraphs>>', self.ask_to_plot_graphs) self.bind('<<CreatePlotGUI>>', self.create_plot_gui) self.parent.bind('<ButtonPress>', self.on_press) self.parent.bind('<Configure>', self.on_resize) self.reinit_variables() self.top_level_windows = list() # NOTE: Because there seems to be an issue resizing child widgets when the top level (Tk) widget is being resized, # the resize option will be disabled for this window self.parent.resizable(width=False, height=False) self.lift() def reinit_variables(self): self.job_params = dict() self.last_job_id = -1 self.job_outcomes = list() self.plot_args = list() self.on_button = False def add_job_params(self, input_args): self.job_params = input_args # Add each element to the job list for job in self.job_params: self.add_job(job) def add_job(self, job): try: index_end = job['input_directory'].rindex('/') index_start = job['input_directory'].rindex('/', 0, index_end) input_directory_text = job['input_directory'] list_text = 'Job ' + str(job['job_id']) + ' \'' + input_directory_text + '\'' if job['start'] != None: list_text += ' ' + str(job['start']) if job['end'] != None: list_text += ' to' if job['end'] != None: list_text += ' ' + str(job['end']) if job['job_id'] > self.last_job_id: self.last_job_id = job['job_id'] self.job_list.insert(Tkinter.END, list_text) # Add the list text to the job params as an optional parameter to read later to display in a future Graph GUI (or for any other useful purpose) job['list_text'] = list_text # The line number is used wrt the GUI to indicate which job in the job list is being currently executed. job['line_number'] = self.job_list.size() - 1 #print str(job['line_number']) self.job_params[job['job_id']] = job except KeyError as ke: # Should show some error message indicating that there is a problem. pass #print str(self.job_params) #print 'Added Job ' + str(job['job_id']) def ask_to_clear_jobs(self, event): for job in self.job_params.itervalues(): line_number = job['line_number'] self.job_list.itemconfig(line_number, foreground='black') # Update parent to refresh widget appearance self.parent.update() # Reactivate process button self.process_button.config(state = Tkinter.NORMAL) # Note: Display a pop-up that tells the user that the job is done and asks if the job list should be cleared. clearList = msg.askyesno(title='Jobs Finished', message='All jobs have been completed. Would you like to clear the job list?', master=self) if clearList: self.clear_list() def ask_to_plot_graphs(self, event): # TODO: Add a dialog that also asks to create a graph of the 'Other Type Of Plot' plotGraphs = msg.askyesno(title='Plot Graphs', message='Create plots of data?', master=self) if not plotGraphs: return # TODO: Iterate through the jobs to display to the user an interface that asks if they want to graphs of the outputs if self.create_plots != None: output_files_list = list() for job_outcome in self.job_outcomes: for output_outcomes in job_outcome[2]: (station, output_directory, output_files) = output_outcomes for output_files_tuple in output_files: for output_file_tuple in output_files_tuple: (output_file, output_file_success) = output_file_tuple if output_file_success: # If there is a list text variable (the 4th (or 3rd by 0 based index) variable), then add it to our output list if len(job_outcome) == 4: output_files_list.append([output_file, job_outcome[3]]) else: output_files_list.append([output_file]) plots_thread = PlotsThread(self.create_plots, output_files_list, self) plots_thread.start() def add_plot(self, args=dict()): self.plot_args.append(args) def finished_adding_plots(self): self.event_generate('<<CreatePlotGUI>>', when='tail') def create_plot_gui(self, event): # TODO: This should be replaced with a new window that allows the user to drag and drop the icons from one frame to another graph_names = list() for args in self.plot_args: graph_name = args['output_file'] graph_names.append(graph_name) dnd_graphs_frame = Dnd.createFrame(self, 'Drag and Drop Output Plots', graph_names, self.finish_creating_plot_gui) # This is the entry point for the def finish_creating_plot_gui(self, plot_labels): graph_count = 1 for plot_label in plot_labels: for args in self.plot_args: #print 'Looking in ' + args['plot_title'] + ' for ' + plot_label #print 'The plot label is: ' + plot_label #print 'The output file is: ' + args['output_file'] if plot_label == args['output_file']: #print 'Creating graph ' + str(graph_count) graph_count += 1 graph_window = ModelRunnerGraphGUI.GraphWindow(parent=self, title=args['window_title'], df=args['df'], plot=args['plot'], plot_title=args['plot_title'], y_label=args['y_label'], log_filename=self.log_filename) graph_window.set_grid() self.top_level_windows.append(graph_window) #print 'Creating plot GUI # Have to clear out list here instead of clear_list because clear_list() removes plot_args before this method has a chance to read # them and create the appropriate plot graph windows self.reinit_variables() # Clear all the elements in the list def clear_list(self): # Save plot args because they are need later in this run plot_args = self.plot_args self.reinit_variables() # Restore the plot args self.plot_args = plot_args self.job_list.delete(0, self.job_list.size()) self.progress_value.set(0) # Update parent to refresh widget appearance self.parent.update() def on_add(self): single_job = JobParameters(parent=self.parent, beginning_year=1950, ending_year=2100, job_id=self.last_job_id + 1, entry=self) single_job.set_grid() def on_remove(self): selection = self.job_list.curselection() for line_number in selection: line_text = self.job_list.get(line_number) job_id = int(line_text[4:line_text.index(' ', 4)]) job = self.job_params.pop(job_id) self.job_list.delete(line_number) print 'Removed Job ' + str(job['job_id']) # Fix line number for line_number in range(self.job_list.size()): line_text = self.job_list.get(line_number) job_id = int(line_text[4:line_text.index(' ', 4)]) #print 'Job ' + str(job_id) + ' is now on line ' + str(line_number) self.job_params[job_id]['line_number'] = line_number def set_grid(self): self.grid(sticky=Tkinter.N + Tkinter.S + Tkinter.W + Tkinter.E, padx=4, pady=4) self.columnconfigure(0, minsize=600) self.rowconfigure(0, minsize=300) self.job_list.grid(row=0, column=0, sticky=Tkinter.N + Tkinter.S + Tkinter.E + Tkinter.W) self.job_list_yscroll.grid(row=0, column=1, sticky=Tkinter.N + Tkinter.S + Tkinter.W) self.job_list_xscroll.grid(row=1, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N) self.new_job_frame.grid(row=2, column=0, pady=3, sticky=Tkinter.W) self.remove_job_button.grid(row=0, column=0) self.add_job_button.grid(row=0, column=1) self.progress_frame.grid(row=3, column=0, pady=3) self.progress_frame.columnconfigure(0, minsize=600) self.progress_bar.grid(row=0, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S) self.button_frame.grid(row=4, column=0, sticky=Tkinter.E + Tkinter.W + Tkinter.N + Tkinter.S) self.button_frame.columnconfigure(0, minsize=300) self.button_frame.columnconfigure(1, minsize=300) self.process_button.pack(side=Tkinter.RIGHT) self.quit_button.pack(side=Tkinter.RIGHT) def start_jobs(self): # If there are no queued jobs then simply return if len(self.job_params) == 0 or len(self.job_list.get(0)) == 0: return # Deactivate the process button self.process_button.config(state = Tkinter.DISABLED) # Initialize the progress bar self.progress_value.set(0) # Update parent to refresh widget appearance self.parent.update() # Start process thread jobs_thread = JobsThread(self.job_params, self.run_job, self.on_update, self.on_resume) jobs_thread.start() self['cursor'] = 'wait' def on_update(self, status, line_number, step): if status == 'init': self.job_list.itemconfig(line_number, foreground='green') self.job_list.activate(line_number) elif status == 'success': self.job_list.itemconfig(line_number, foreground='blue') elif status == 'fail': self.job_list.itemconfig(line_number, foreground='red') self.progress_value.set(step) # Update parent to refresh widget appearance self.parent.update() def on_resume(self, job_outcomes=list()): self.progress_value.set(100) self.job_outcomes = job_outcomes self.event_generate('<<AskToClearJobs>>', when='tail') self.event_generate('<<AskToPlotGraphs>>', when='tail') self['cursor'] = 'arrow' def close_top_level_windows(self): #print 'Closing other top level windows' for top_level_window in self.top_level_windows: if top_level_window: top_level_window.withdraw() top_level_window.destroy() def notify_of_close(self, top_level_window): if top_level_window in self.top_level_windows: #print 'Removing top level window' self.top_level_windows.remove(top_level_window) def on_press(self, event): self.on_button = True self.release_pattern = "<B%d-ButtonRelease-%d>" % (event.num, event.num) self.parent.bind(self.release_pattern, self.on_release) def on_release(self, event): self.on_button = False def on_resize(self, event): self.parent.lift() if self.on_button: self.set_grid() def on_close(self): self.plot_args = list() self.withdraw() self.destroy()
class XML_Viwer(Frame): def __init__(self, master, xml=None, heading_text=None, heading_anchor=None, padding=None, cursor=None, takefocus=None, style=None): Frame.__init__(self, master, class_="XML_Viwer") self._vsb = Scrollbar(self, orient=VERTICAL) self._hsb = Scrollbar(self, orient=HORIZONTAL) kwargs = {} kwargs["yscrollcommand"] = lambda f, l: autoscroll(self._vsb, f, l) kwargs["xscrollcommand"] = lambda f, l: autoscroll(self._hsb, f, l) if style is not None: kwargs["style"] = style if padding is not None: kwargs["padding"] = padding if cursor is not None: kwargs["cursor"] = cursor if takefocus is not None: kwargs["takefocus"] = takefocus self._treeview = Treeview(self, **kwargs) if heading_text is not None: if heading_anchor is not None: self._treeview.heading("#0", text=heading_text, anchor=heading_anchor) else: self._treeview.heading("#0", text=heading_text) self._treeview.bind("<<TreeviewOpen>>", self._on_open) self._treeview.bind("<<TreeviewClose>>", self._on_close) # Without this line, horizontal scrolling doesn't work properly. self._treeview.column("#0", stretch= False) self._vsb['command'] = self._treeview.yview self._hsb['command'] = self._treeview.xview self._treeview.grid(column=0, row=0, sticky=N+S+W+E) self._vsb.grid(column=1, row=0, sticky=N+S) self._hsb.grid(column=0, row=1, sticky=E+W) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._element_tree = None self._item_ID_to_element = {} if xml is not None: self.parse_xml(xml) def _on_open(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] self._treeview.item(item_ID, text = self._repr_of_openning_tag(node)) def _on_close(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag(node) self._treeview.item(item_ID, text = text) def parse_xml(self, xml): self._element_tree = ET.ElementTree(ET.fromstring(xml)) self.clear() self._walk_xml(self._element_tree.getroot()) @property def element_tree(self): return self._element_tree @element_tree.setter def element_tree(self, element_tree): self._element_tree = element_tree self.clear() self._walk_xml(element_tree.getroot()) def clear(self): self._item_ID_to_element = {} self._treeview.delete(*self._treeview.get_children()) def _repr_of_openning_tag(self, node): text = "<" + node.tag attrs = node.attrib # list function is here necessary to provide support to Python 3 a_names = list(attrs.keys()) a_names.sort() for a_name in a_names: text += ' %s="' % a_name text += attrs[a_name] text += '"' text += ">" return text def _repr_of_closing_tag(self, node): return "</%s>"%node.tag def _walk_xml(self, node, depth=0, parent=""): text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag(node) item = self._treeview.insert(parent, END, text = text) self._item_ID_to_element[item] = node if node.text: text = node.text.strip() if text != "": for line in text.splitlines(): self._treeview.insert(item, END, text = line) child_nodes = sorted(list(node), key=attrgetter('tag')) for child_node in node: self._walk_xml(child_node, depth+1, parent=item) if node.tail: tail = node.tail.strip() if tail != "": for line in tail.splitlines(): self._treeview.insert(parent, END, text = line)
def __init__(self, master, columns, column_weights=None, column_minwidths=None, height=500, minwidth=20, minheight=20, padx=5, pady=5, cell_font=None, cell_foreground="black", cell_background="white", cell_anchor=W, header_font=None, header_background="white", header_foreground="black", header_anchor=CENTER, bordercolor = "#999999", innerborder=True, outerborder=True, stripped_rows=("#EEEEEE", "white"), on_change_data=None, mousewheel_speed = 2, scroll_horizontally=True, scroll_vertically=True): outerborder_width = 1 if outerborder else 0 Frame.__init__(self,master, bd= 0) self._cell_background = cell_background self._cell_foreground = cell_foreground self._cell_font = cell_font self._cell_anchor = cell_anchor self._stripped_rows = stripped_rows self._padx = padx self._pady = pady self._bordercolor = bordercolor self._innerborder_width = 1 if innerborder else 0 self._data_vars = [] self._columns = columns self._number_of_rows = 0 self._number_of_columns = len(columns) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(1, weight=1) self._head = Frame(self, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=outerborder_width, bd= 0) self._head.grid(row=0, column=0, sticky=E+W) header_separator = False if outerborder else True for j in range(len(columns)): column_name = columns[j] header_cell = Header_Cell(self._head, text=column_name, borderwidth=self._innerborder_width, font=header_font, background=header_background, foreground=header_foreground, padx=padx, pady=pady, bordercolor=bordercolor, anchor=header_anchor, separator=header_separator) header_cell.grid(row=0, column=j, sticky=N+E+W+S) add_scrollbars = scroll_horizontally or scroll_vertically if add_scrollbars: if scroll_horizontally: xscrollbar = Scrollbar(self, orient=HORIZONTAL) xscrollbar.grid(row=2, column=0, sticky=E+W) else: xscrollbar = None if scroll_vertically: yscrollbar = Scrollbar(self, orient=VERTICAL) yscrollbar.grid(row=1, column=1, sticky=N+S) else: yscrollbar = None scrolling_area = Scrolling_Area(self, width=self._head.winfo_reqwidth(), height=height, scroll_horizontally=scroll_horizontally, xscrollbar=xscrollbar, scroll_vertically=scroll_vertically, yscrollbar=yscrollbar) scrolling_area.grid(row=1, column=0, sticky=E+W) self._body = Frame(scrolling_area.innerframe, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=outerborder_width, bd= 0) self._body.pack() def on_change_data(): scrolling_area.update_viewport() else: self._body = Frame(self, height=height, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=outerborder_width, bd= 0) self._body.grid(row=1, column=0, sticky=N+E+W+S) if column_weights is None: for j in range(len(columns)): self._body.grid_columnconfigure(j, weight=1) else: for j, weight in enumerate(column_weights): self._body.grid_columnconfigure(j, weight=weight) if column_minwidths is not None: for j, minwidth in enumerate(column_minwidths): if minwidth is None: header_cell = self._head.grid_slaves(row=0, column=j)[0] minwidth = header_cell.winfo_reqwidth() self._body.grid_columnconfigure(j, minsize=minwidth) else: for j in range(len(columns)): header_cell = self._head.grid_slaves(row=0, column=j)[0] minwidth = header_cell.winfo_reqwidth() self._body.grid_columnconfigure(j, minsize=minwidth) self._on_change_data = on_change_data
def StartGui(self): self.tkRoot = Tk(baseName="") self.tkRoot.geometry("350x300+0+0") self.tkRoot.title("Engine SAPI GUI") self.GUIVisible = True frame = Frame(self.tkRoot) frame.style = Style() frame.style.theme_use("alt") frame.pack(fill=BOTH, expand=1) frame.columnconfigure(1, weight=1) frame.columnconfigure(7, pad=7) frame.rowconfigure(13, weight=1) frame.rowconfigure(13, pad=7) Label(frame, text="Start:").grid(row = 0, column=0) self.labelStart = Label(frame, text="0") self.labelStart.grid(row = 1, column=0) Label(frame, text="Length:").grid(row = 0, column=1) self.labelLength = Label(frame, text="0") self.labelLength.grid(row = 1, column=1) Label(frame, text="Total:").grid(row = 0, column=2) self.labelTotal = Label(frame, text="0") self.labelTotal.grid(row = 1, column=2) self.labelSentenceLeft = Label(frame, text="...") self.labelSentenceLeft.grid(row = 2, column=0, sticky=E) self.labelSentenceSpoken = Label(frame, text="...", foreground="red") self.labelSentenceSpoken.grid(row = 2, column=1) self.labelSentenceRight = Label(frame, text="...") self.labelSentenceRight.grid(row = 2, column=2, sticky=W, columnspan=2) scrollbar = Scrollbar(frame, orient=VERTICAL) self.labelQueueToSpeak = Label(frame, text="Queue to speak:").grid(row = 3, column=0, pady=4, padx=5, sticky=W) self.listboxQueueToSpeak = Listbox(frame, width=50, height=3, yscrollcommand=scrollbar.set) scrollbar.config(command=self.listboxQueueToSpeak.yview) self.listboxQueueToSpeak.grid( sticky=N+S+E+W, row = 4, column = 0, columnspan = 2 ,rowspan = 3, padx=3) scrollbar.grid(sticky=N+S+W, row = 4, column = 2, rowspan = 3) self.buttonPauze = Button(frame, text="Pauze", command=self.communicationProtocal.handlePauze) self.buttonPauze.grid(row = 4, column=3) self.buttonStop = Button(frame, text="Stop", command=self.communicationProtocal.restartProcess) self.buttonStop.grid(row = 5, column=3) self.buttonResume = Button(frame, text="Resume", command=self.communicationProtocal.handleResume) self.buttonResume.grid(row = 6, column=3) Label(frame, text="Text to say:").grid(row = 7, column=0, padx=3, sticky=W) self.stringVarTextToSay = StringVar() self.entryTextToSay = Entry(frame, textvariable=self.stringVarTextToSay, width=500) self.entryTextToSay.grid(row=8, column=0, columnspan=3, padx=3, sticky=W) self.stringVarTextToSay.set("Hello SAPI Speak Engine") self.entryTextToSay.bind('<Return>', self.CallBackReturnSay) self.buttonSay = Button(frame, text="Say", command=self.CallBackButtonSay) self.buttonSay.grid(row = 8, column=3) Label(frame, text="Recover action:").grid(row = 9, column=0, padx=3, sticky=W) self.recoverActionLabelText = "None" self.labelRecoverAction = Label(frame, text=self.recoverActionLabelText, foreground="blue") self.labelRecoverAction.grid(row = 10, column=0) Label(frame, text="Voice speed:").grid(row = 9, column=1, sticky=W) self.buttonSpeedDown = Button(frame, text="Speed down", command=self.communicationProtocal.handleSpeedDown) self.buttonSpeedDown.grid(row = 10, column=1, padx=3, sticky=E) self.speedValue = 0 self.intVarSpeed = IntVar() vcmd = (self.tkRoot.register(self.OnValidateEntrySpeakSpeed), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') self.entrySpeakSpeed = Entry(frame, textvariable=self.intVarSpeed, validate="key", validatecommand=vcmd, width=5) self.entrySpeakSpeed.grid(row=10,column=2) self.entrySpeakSpeed.bind('<Return>', self.CallBackSetSpeed) self.buttonSpeedUp = Button(frame, text="Speed up", command=self.communicationProtocal.handleSpeedUp) self.buttonSpeedUp.grid(row = 10, column=3) Label(frame, text="voice:").grid(row = 11, column=0, padx=3, sticky=W) self.buttonPrevVoice = Button(frame, text="Prev voice", command=self.communicationProtocal.handlePrevVoice) self.buttonPrevVoice.grid(row = 12, column=0, padx=3, sticky=W) self.buttonNextVoice = Button(frame, text="Next voice", command=self.communicationProtocal.handleNextVoice) self.buttonNextVoice.grid(row = 12, column=3) self.currentVoice = StringVar(self.tkRoot) self.currentVoice.set(self.communicationProtocal.CurrentVoiceName) engine = pyttsx.init() voices = engine.getProperty("voices") voiceNames = list() for x in xrange(0, len(voices)): voiceNames.append(voices[x].name) self.optionMenuVoices = OptionMenu(frame, self.currentVoice, *tuple(voiceNames), command=self.CallBackOptionMenuVoices) self.optionMenuVoices.config(width=500) self.optionMenuVoices.grid(sticky=W, row = 12, column = 1) #hide if close button is clicked self.tkRoot.protocol("WM_DELETE_WINDOW", self.HideGui) self.tkRoot.after(1000/32, self.Update) self.tkRoot.mainloop()
class XML_Viwer(Frame): def __init__(self, master, xml=None, heading_text=None, heading_anchor=None, padding=None, cursor=None, takefocus=None, style=None): Frame.__init__(self, master, class_="XML_Viwer") self._vsb = Scrollbar(self, orient=VERTICAL) self._hsb = Scrollbar(self, orient=HORIZONTAL) kwargs = {} kwargs["yscrollcommand"] = lambda f, l: autoscroll(self._vsb, f, l) kwargs["xscrollcommand"] = lambda f, l: autoscroll(self._hsb, f, l) if style is not None: kwargs["style"] = style if padding is not None: kwargs["padding"] = padding if cursor is not None: kwargs["cursor"] = cursor if takefocus is not None: kwargs["takefocus"] = takefocus self._treeview = Treeview(self, **kwargs) if heading_text is not None: if heading_anchor is not None: self._treeview.heading("#0", text=heading_text, anchor=heading_anchor) else: self._treeview.heading("#0", text=heading_text) self._treeview.bind("<<TreeviewOpen>>", self._on_open) self._treeview.bind("<<TreeviewClose>>", self._on_close) # Without this line, horizontal scrolling doesn't work properly. self._treeview.column("#0", stretch=False) self._vsb['command'] = self._treeview.yview self._hsb['command'] = self._treeview.xview self._treeview.grid(column=0, row=0, sticky=N + S + W + E) self._vsb.grid(column=1, row=0, sticky=N + S) self._hsb.grid(column=0, row=1, sticky=E + W) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._element_tree = None self._item_ID_to_element = {} if xml is not None: self.parse_xml(xml) def _on_open(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] self._treeview.item(item_ID, text=self._repr_of_openning_tag(node)) def _on_close(self, event): item_ID = self._treeview.focus() if item_ID not in self._item_ID_to_element: return node = self._item_ID_to_element[item_ID] text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag( node) self._treeview.item(item_ID, text=text) def parse_xml(self, xml): self._element_tree = ET.ElementTree(ET.fromstring(xml)) self.clear() self._walk_xml(self._element_tree.getroot()) @property def element_tree(self): return self._element_tree @element_tree.setter def element_tree(self, element_tree): self._element_tree = element_tree self.clear() self._walk_xml(element_tree.getroot()) def clear(self): self._item_ID_to_element = {} self._treeview.delete(*self._treeview.get_children()) def _repr_of_openning_tag(self, node): text = "<" + node.tag attrs = node.attrib # list function is here necessary to provide support to Python 3 a_names = list(attrs.keys()) a_names.sort() for a_name in a_names: text += ' %s="' % a_name text += attrs[a_name] text += '"' text += ">" return text def _repr_of_closing_tag(self, node): return "</%s>" % node.tag def _walk_xml(self, node, depth=0, parent=""): text = self._repr_of_openning_tag(node) + self._repr_of_closing_tag( node) item = self._treeview.insert(parent, END, text=text) self._item_ID_to_element[item] = node if node.text: text = node.text.strip() if text != "": for line in text.splitlines(): self._treeview.insert(item, END, text=line) child_nodes = sorted(list(node), key=attrgetter('tag')) for child_node in node: self._walk_xml(child_node, depth + 1, parent=item) if node.tail: tail = node.tail.strip() if tail != "": for line in tail.splitlines(): self._treeview.insert(parent, END, text=line)
class Tk_Table(Frame, object): def __init__(self, master, columns, data=None, command=None, editable=True, sort=True, select_mode=None, autoscroll=True, vscrollbar=True, hscrollbar=False, heading_anchor = CENTER, cell_anchor=W, style=None, scrollbar_background=None, scrollbar_troughcolor=None, height=None, padding=None, adjust_heading_to_content=False, stripped_rows=None, selection_background=None, selection_foreground=None, cell_background=None, cell_foreground=None, cell_font=None, field_background=None, heading_font= None, heading_background=None, heading_foreground=None, cell_pady=2, column_header=True, row_numbers=True, entry_background="#d6d6d6", entry_foreground=None, entry_validatecommand=None, entry_selectbackground="#1BA1E2", entry_selectborderwidth=None, entry_selectforeground=None, entry_font = "TkDefaultFont", rowlabel_anchor=E, rowlabel_minwidth=0, rowlabel_hoverbackground="#FFFFFF",frame_relief=None, frame_borderwidth=None, frame_background=None): frame_kwargs = {} if frame_relief is not None: frame_kwargs["relief"] = frame_relief if frame_borderwidth is not None: frame_kwargs["borderwidth"] = frame_borderwidth if frame_background is not None: frame_kwargs["background"] = frame_background Frame.__init__(self, master, class_="Multicolumn_Listbox", **frame_kwargs) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self._multicolumn_listbox = Multicolumn_Listbox(self, columns, data=data, command=command, sort=sort, select_mode=select_mode, heading_anchor = heading_anchor, cell_anchor=cell_anchor, style=style, height=height, padding=padding, adjust_heading_to_content=adjust_heading_to_content, stripped_rows=stripped_rows, selection_background=selection_background, selection_foreground=selection_foreground, cell_background=cell_background, cell_foreground=cell_foreground, cell_font=cell_font, field_background=field_background, heading_font=heading_font, heading_background=heading_background, heading_foreground=heading_foreground, cell_pady=cell_pady, headers=column_header) self._multicolumn_listbox.interior.grid(row=0, column=1, sticky= N+E+W+S) self._mousewheel_detection = True if row_numbers: self._row_numbers = Row_Header(self, font=self._multicolumn_listbox.font, row_height=self._multicolumn_listbox.row_height, row_minwidth=rowlabel_minwidth, hover_background = rowlabel_hoverbackground, anchor=rowlabel_anchor, onclick=self._on_click_row_label) self._row_numbers.grid(row=0, column=0, sticky= N+S+E) self._multicolumn_listbox.interior.bind("<Map>", self._place_vertically_row_numbers) else: self._row_numbers = None if editable: self._selected_cell = None self._entry_popup = None self._multicolumn_listbox.interior.bind("<1>", self._edit_cell) def configure(event): """ if self._entry_popup: self._entry_popup.destroy() return """ self._multicolumn_listbox.interior.update_idletasks() self._update_position_of_entry() self._multicolumn_listbox.interior.bind("<Configure>", configure) self._entry_kwargs = entry_kwargs = {} if entry_background is not None: entry_kwargs["background"] = entry_background if entry_foreground is not None: entry_kwargs["foreground"] = entry_foreground if entry_validatecommand is not None: entry_kwargs["validatecommand"] = entry_validatecommand if entry_selectbackground is not None: entry_kwargs["selectbackground"] = entry_selectbackground if entry_selectforeground is not None: entry_kwargs["selectforeground"] = entry_selectforeground if entry_font is not None: entry_kwargs["font"] = entry_font if command is not None: self._command = command self._multicolumn_listbox.interior.bind("<<TreeviewSelect>>", self._on_select) scrollbar_kwargs = {} if scrollbar_background is not None: scrollbar_kwargs["background"] = scrollbar_background if scrollbar_troughcolor is not None: scrollbar_kwargs["throughcolor"] = scrollbar_troughcolor if vscrollbar: if editable: if row_numbers: def yview_command(*args): self._multicolumn_listbox.interior.yview(*args) self._row_numbers.yview(*args) self._update_position_of_entry() else: def yview_command(*args): self._multicolumn_listbox.interior.yview(*args) self._update_position_of_entry() else: if row_numbers: def yview_command(*args): self._multicolumn_listbox.interior.yview(*args) self._row_numbers.yview(*args) else: yview_command = self._multicolumn_listbox.interior.yview self._vbar=Scrollbar(self,takefocus=0, command=yview_command, **scrollbar_kwargs) self._vbar.grid(row=0, column=2, sticky= N+S) def yscrollcommand(first,last): first, last = float(first), float(last) if first <= 0 and last >= 1: if self._mousewheel_detection: if autoscroll: self._vbar.grid_remove() if row_numbers: unbind_function_onMouseWheel(self._multicolumn_listbox.interior) self._mousewheel_detection = False else: if not self._mousewheel_detection: if autoscroll: self._vbar.grid() if row_numbers: bind_function_onMouseWheel(self._row_numbers, "y", binding_widget=self._multicolumn_listbox.interior, unit="pages") self._mousewheel_detection = True self._vbar.set(first, last) if editable: self._update_position_of_entry() self._multicolumn_listbox.interior.config(yscrollcommand=yscrollcommand) if hscrollbar: if editable: def xview_command(*args): self._multicolumn_listbox.interior.xview(*args) self._update_position_of_entry() else: xview_command = self._multicolumn_listbox.interior.xview self._hbar=Scrollbar(self,takefocus=0, command=xview_command, **scrollbar_kwargs) self._hbar.grid(row=1, column=1, sticky= E+W) if autoscroll: if editable: def xscrollcommand(f,l, self=self): make_autoscroll(self._hbar, f, l) self._update_position_of_entry() else: def xscrollcommand(f,l, hbar=self._hbar): make_autoscroll(hbar, f, l) self._multicolumn_listbox.interior.config(xscrollcommand=xscrollcommand) else: self._multicolumn_listbox.interior.config(xscrollcommand=self._hbar.set) def _place_vertically_row_numbers(self, event): self._multicolumn_listbox.interior.unbind("<Map>") item_ID = self._multicolumn_listbox.interior.insert('', 0, values=[""]*self._multicolumn_listbox.number_of_columns) self._multicolumn_listbox.interior.update() x,y,w,h = self._multicolumn_listbox.interior.bbox(item_ID) self._multicolumn_listbox.interior.delete(item_ID) self._row_numbers.grid_configure(pady=(y,0)) def _edit_cell(self, event): '''Executed, when a row is clicked. Opens an entry popup above the cell, so it is possible to select text ''' # close previous popups if self._entry_popup: self._destroy_entry() # what row and column was clicked on item_ID = self._multicolumn_listbox.interior.identify_row(event.y) if not item_ID: return column = self._multicolumn_listbox.interior.identify_column(event.x) if column == "": return # get column position info x,y,width,height = self._multicolumn_listbox.interior.bbox(item_ID, column) # place Entry popup properly column_number = int(column[1:])-1 cell_data = self._multicolumn_listbox.item_ID_to_row_data(item_ID)[column_number] self._entry_popup = Entry(self._multicolumn_listbox.interior, exportselection=True, borderwidth=0, **self._entry_kwargs) self._entry_popup.place(x=x, y=y, width=width, height=height) self._entry_popup.insert(0, cell_data) self._entry_popup.focus_force() self._entry_popup.bind("<Control-a>", lambda event: self._select_all_entry_data) self._entry_popup.bind("<Escape>", lambda event: self._destroy_entry()) self._entry_popup.bind("<FocusOut>", lambda event: self._destroy_entry()) bind_function_onMouseWheel(self._multicolumn_listbox.interior, "y", binding_widget=self._entry_popup, callback=self._update_position_of_entry, unit="pages") if self._row_numbers: bind_function_onMouseWheel(self._row_numbers, "y", binding_widget=self._entry_popup, unit="pages") self._entry_popup.bind("<Return>", self._on_update_cell) self._selected_cell = item_ID, column, column_number def _on_click_row_label(self, index): if self._selected_cell and self._multicolumn_listbox.item_ID(index) == self._selected_cell[0]: self._destroy_entry() self._multicolumn_listbox.toogle_selection(index) def _select_all_entry_data(self): ''' Set selection on the whole text ''' self._entry_popup.selection_range(0, 'end') # returns 'break' to interrupt default key-bindings return 'break' def _destroy_entry(self): self._entry_popup.destroy() self._entry_popup = None self._selected_cell = None def _on_update_cell(self, event): item_ID, column, column_number = self._selected_cell data = self._entry_popup.get() row_data = self._multicolumn_listbox.item_ID_to_row_data(item_ID) row_data[column_number] = data self._multicolumn_listbox.interior.item(item_ID, values=row_data) self._destroy_entry() def _update_position_of_entry(self): if self._selected_cell: bbox = self._multicolumn_listbox.interior.bbox(self._selected_cell[0], self._selected_cell[1]) if bbox == "": self._entry_popup.place_forget() else: x,y,width,height = bbox self._entry_popup.place(x=x, y=y, width=width, height=height) def configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None): self._multicolumn_listbox.configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None) def row_data(self, index): return self._multicolumn_listbox.row_data(index) def update_row(self, index, data): self._multicolumn_listbox.update_row(index,data) def delete_row(self, index): self._multicolumn_listbox.delete_row(index) if self._row_numbers: self._row_numbers.pop() def insert_row(self, data, index=None): self._multicolumn_listbox.insert_row(data, index) if self._row_numbers: self._row_numbers.new_label() def column_data(self, index): return self._multicolumn_listbox.column_data(index) def update_column(self, index, data): self._multicolumn_listbox.update_column(index, data) def clear(self): self._multicolumn_listbox.clear() if self._row_numbers: self._row_numbers.delete_labels() def update(self, data): current_number_of_rows = self._multicolumn_listbox.number_of_rows self._multicolumn_listbox.update(data) if self._row_numbers: number_of_rows = len(data) if current_number_of_rows < number_of_rows: for i in range(number_of_rows - current_number_of_rows): self._row_numbers.new_label() else: n_labels = current_number_of_rows - number_of_rows self._row_numbers.pop(n_labels =n_labels) def focus(self, index=None): self._multicolumn_listbox.focus(index) def state(self, state=None): self._multicolumn_listbox.state(state) @property def number_of_rows(self): return self._multicolumn_listbox.number_of_rows @property def number_of_columns(self): return self._multicolumn_listbox.number_of_columns def toogle_selection(self, index): self._multicolumn_listbox.toogle_selection(index) def select_row(self, index): self._multicolumn_listbox.select_row(index) def deselect_row(self, index): self._multicolumn_listbox.deselect_row(index) def deselect_all(self): self._multicolumn_listbox.deselect_all() def set_selection(self, indices): self._multicolumn_listbox.set_selection(indices) @property def selected_rows(self): return self._multicolumn_listbox.selected_rows @property def indices_of_selected_rows(self): return self._multicolumn_listbox.indices_of_selected_rows def delete_all_selected_rows(self): number_of_deleted_rows = self._multicolumn_listbox.delete_all_selected_rows() if self._row_numbers: self._row_numbers.pop(n_labels=number_of_deleted_rows) @property def table_data(self): return self._multicolumn_listbox.table_data @table_data.setter def table_data(self, data): self.update(data) def cell_data(self, row, column): return self._multicolumn_listbox.cell_data(row, column) def update_cell(self, row, column, value): self._multicolumn_listbox.update_cell(row, column, value) def __getitem__(self, index): return self._multicolumn_listbox[index] def __setitem__(self, index, value): self._multicolumn_listbox[index] = value def bind(self, event, handler): self._multicolumn_listbox.bind(event, handler) def sort_by(self, col, descending): self._multicolumn_listbox.sort_by(col, descending)
class Scrolling_Area(Frame, object): def __init__(self, master, width=None, height=None, mousewheel_speed=2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, outer_background=None, inner_frame=Frame, **kw): super(Scrolling_Area, self).__init__(master, **kw) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) self._clipper = Frame(self, background=outer_background, width=width, height=height) self._clipper.grid(row=0, column=0, sticky=N + E + W + S) self._width = width self._height = height self.innerframe = inner_frame(self._clipper, padx=0, pady=0, highlightthickness=0) self.innerframe.place(in_=self._clipper, x=0, y=0) if scroll_vertically: if yscrollbar is not None: self.yscrollbar = yscrollbar else: self.yscrollbar = Scrollbar(self, orient=VERTICAL) self.yscrollbar.grid(row=0, column=1, sticky=N + S) self.yscrollbar.set(0.0, 1.0) self.yscrollbar.config(command=self.yview) else: self.yscrollbar = None self._scroll_vertically = scroll_vertically if scroll_horizontally: if xscrollbar is not None: self.xscrollbar = xscrollbar else: self.xscrollbar = Scrollbar(self, orient=HORIZONTAL) self.xscrollbar.grid(row=1, column=0, sticky=E + W) self.xscrollbar.set(0.0, 1.0) self.xscrollbar.config(command=self.xview) else: self.xscrollbar = None self._scroll_horizontally = scroll_horizontally self._jfraction = 0.05 self._startX = 0 self._startY = 0 # Whenever the clipping window or scrolled frame change size, # update the scrollbars. self.innerframe.bind('<Configure>', self._on_configure) self._clipper.bind('<Configure>', self._on_configure) self.innerframe.xview = self.xview self.innerframe.yview = self.yview Mousewheel_Support(self).add_support_to(self.innerframe, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar) def update_viewport(self): # compute new height and width self.update() frameHeight = float(self.innerframe.winfo_reqheight()) frameWidth = float(self.innerframe.winfo_reqwidth()) if self._width is not None: width = min(self._width, frameWidth) else: width = self._frameWidth if self._height is not None: height = min(self._height, frameHeight) else: height = self._frameHeight self._clipper.configure(width=width, height=height) def _on_configure(self, event): self._frameHeight = float(self.innerframe.winfo_reqheight()) self._frameWidth = float(self.innerframe.winfo_reqwidth()) # resize the visible part if self._scroll_horizontally: self.xview("scroll", 0, "unit") if self._scroll_vertically: self.yview("scroll", 0, "unit") def xview(self, mode=None, value=None, units=None): value = float(value) clipperWidth = self._clipper.winfo_width() frameWidth = self._frameWidth _startX = self._startX if mode is None: return self.xscrollbar.get() elif mode == 'moveto': # absolute movement self._startX = int(value * frameWidth) else: # mode == 'scroll' # relative movement if units == 'units': jump = int(clipperWidth * self._jfraction) else: jump = clipperWidth self._startX = self._startX + value * jump if frameWidth <= clipperWidth: # The scrolled frame is smaller than the clipping window. self._startX = 0 hi = 1.0 #use expand by default relwidth = 1 else: # The scrolled frame is larger than the clipping window. #use expand by default if self._startX + clipperWidth > frameWidth: self._startX = frameWidth - clipperWidth hi = 1.0 else: if self._startX < 0: self._startX = 0 hi = (self._startX + clipperWidth) / frameWidth relwidth = '' if self._startX != _startX: # Position frame relative to clipper. self.innerframe.place(x=-self._startX, relwidth=relwidth) lo = self._startX / frameWidth self.xscrollbar.set(lo, hi) def yview(self, mode=None, value=None, units=None): value = float(value) clipperHeight = self._clipper.winfo_height() frameHeight = self._frameHeight _startY = self._startY if mode is None: return self.yscrollbar.get() elif mode == 'moveto': self._startY = value * frameHeight else: # mode == 'scroll' if units == 'units': jump = int(clipperHeight * self._jfraction) else: jump = clipperHeight self._startY = self._startY + value * jump if frameHeight <= clipperHeight: # The scrolled frame is smaller than the clipping window. self._startY = 0 hi = 1.0 # use expand by default relheight = 1 else: # The scrolled frame is larger than the clipping window. # use expand by default if self._startY + clipperHeight > frameHeight: self._startY = frameHeight - clipperHeight hi = 1.0 else: if self._startY < 0: self._startY = 0 hi = (self._startY + clipperHeight) / frameHeight relheight = '' if self._startY != _startY: # Position frame relative to clipper. self.innerframe.place(y=-self._startY, relheight=relheight) lo = self._startY / frameHeight self.yscrollbar.set(lo, hi)
def __init__(self, master, columns, column_weights=None, column_minwidths=None, height=500, minwidth=20, minheight=20, padx=5, pady=5, cell_font=None, cell_foreground="black", cell_background="white", cell_anchor=W, header_font=None, header_background="white", header_foreground="black", header_anchor=CENTER, bordercolor = "#999999", innerborder=True, outerborder=True, stripped_rows=("#EEEEEE", "white"), on_change_data=None, mousewheel_speed = 2, scroll_horizontally=False, scroll_vertically=True): outerborder_width = 1 if outerborder else 0 Frame.__init__(self,master, bd= 0) self._cell_background = cell_background self._cell_foreground = cell_foreground self._cell_font = cell_font self._cell_anchor = cell_anchor self._stripped_rows = stripped_rows self._padx = padx self._pady = pady self._bordercolor = bordercolor self._innerborder_width = 1 if innerborder else 0 self._data_vars = [] self._columns = columns self._number_of_rows = 0 self._number_of_columns = len(columns) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(1, weight=1) self._head = Frame(self, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=outerborder_width, bd= 0) self._head.grid(row=0, column=0, sticky=E+W) header_separator = False if outerborder else True for j in range(len(columns)): column_name = columns[j] header_cell = Header_Cell(self._head, text=column_name, borderwidth=self._innerborder_width, font=header_font, background=header_background, foreground=header_foreground, padx=padx, pady=pady, bordercolor=bordercolor, anchor=header_anchor, separator=header_separator) header_cell.grid(row=0, column=j, sticky=N+E+W+S) add_scrollbars = scroll_horizontally or scroll_vertically if add_scrollbars: if scroll_horizontally: xscrollbar = Scrollbar(self, orient=HORIZONTAL) xscrollbar.grid(row=2, column=0, sticky=E+W) else: xscrollbar = None if scroll_vertically: yscrollbar = Scrollbar(self, orient=VERTICAL) yscrollbar.grid(row=1, column=1, sticky=N+S) else: yscrollbar = None scrolling_area = Scrolling_Area(self, width=self._head.winfo_reqwidth(), height=height, scroll_horizontally=scroll_horizontally, xscrollbar=xscrollbar, scroll_vertically=scroll_vertically, yscrollbar=yscrollbar) scrolling_area.grid(row=1, column=0, sticky=E+W) self._body = Frame(scrolling_area.innerframe, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=outerborder_width, bd= 0) self._body.pack() def on_change_data(): scrolling_area.update_viewport() else: self._body = Frame(self, height=height, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=outerborder_width, bd= 0) self._body.grid(row=1, column=0, sticky=N+E+W+S) if column_weights is None: for j in range(len(columns)): self._body.grid_columnconfigure(j, weight=1) else: for j, weight in enumerate(column_weights): self._body.grid_columnconfigure(j, weight=weight) if column_minwidths is not None: for j, minwidth in enumerate(column_minwidths): if minwidth is None: header_cell = self._head.grid_slaves(row=0, column=j)[0] minwidth = header_cell.winfo_reqwidth() self._body.grid_columnconfigure(j, minsize=minwidth) else: for j in range(len(columns)): header_cell = self._head.grid_slaves(row=0, column=j)[0] minwidth = header_cell.winfo_reqwidth() self._body.grid_columnconfigure(j, minsize=minwidth) self._on_change_data = on_change_data